curious about what AGK allows for surfaces (verticescount, trianglescount)

Started by RemiD, February 24, 2018, 23:10:02

Previous topic - Next topic

Rick Nasher

@RemiD:

QuoteThanks for the example to create a texture, can you show us what it outputs ? (or describe it)

Already posted it before, check out the woodtexture on the stairs railing and the pole:


[deleted code due to objection of original creator]

Random Texture Demo using the function:





Really like the powerful effect of such a small function.
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

Rick Nasher

@RemiD
QuoteAnd from what i understand in the code, a "memblock" in agk, is what we call a "surface" in blitzbasic / unity.

Here's my 50cents:  ;)

No, for if you check the other examples(soundgenerator, texture creation) you see they all use memblocks. It's more like Blitz'es memorybanks or a buffer I think.
You can use them for anything really. Handy for manipulating files, like images, sound, meshes or other kinds of structured data.

Memblock related commands:
•CreateMemblockFromSound ( soundID )
•CreateSoundFromMemblock ( memID )
•CopyMemblock ( memSrcID, memDstID, srcOffset, dstOffset, size )
•CreateMemblock ( memID, size )
•DeleteMemblock ( memID )
•GetMemblockByte ( memID, offset )
•GetMemblockByteSigned ( memID, offset )
•GetMemblockExists ( memID )
•GetMemblockFloat ( memID, offset )
•GetMemblockInt ( memID, offset )
•GetMemblockShort ( memID, offset )
•GetMemblockSize ( memID )
•GetMemblockString ( memID, offset, length )
•SetMemblockByte ( memID, offset, value )
•SetMemblockByteSigned ( memID, offset, value )
•SetMemblockFloat ( memID, offset, value )
•SetMemblockInt ( memID, offset, value )
•SetMemblockShort ( memID, offset, value )
•SetMemblockString ( memID, offset, value )
•CreateFileFromMemblock ( filename, memID )
•CreateMemblockFromFile ( filename )
•CreateImageFromMemblock ( imageID, memID )
•CreateMemblockFromImage ( imageID )
•AddObjectMeshFromMemblock ( objID, memID )
•CreateMemblockFromObjectMesh ( objID, meshIndex )
•CreateObjectFromMeshMemblock ( memID )
•GetMeshMemblockVertexAlpha ( memID, vertexIndex )
•GetMeshMemblockVertexBlue ( memID, vertexIndex )
•GetMeshMemblockVertexGreen ( memID, vertexIndex )
•GetMeshMemblockVertexNormalX ( memID, vertexIndex )
•GetMeshMemblockVertexNormalY ( memID, vertexIndex )
•GetMeshMemblockVertexNormalZ ( memID, vertexIndex )
•GetMeshMemblockVertexRed ( memID, vertexIndex )
•GetMeshMemblockVertexU ( memID, vertexIndex )
•GetMeshMemblockVertexV ( memID, vertexIndex )
•GetMeshMemblockVertexX ( memID, vertexIndex )
•GetMeshMemblockVertexY ( memID, vertexIndex )
•GetMeshMemblockVertexZ ( memID, vertexIndex )
•SetMeshMemblockVertexColor ( memID, vertexIndex, red, green, blue, alpha )
•SetMeshMemblockVertexNormal ( memID, vertexIndex, x, y, z )
•SetMeshMemblockVertexPosition ( memID, vertexIndex, x, y, z )
•SetMeshMemblockVertexUV ( memID, vertexIndex, u, v )
•SetObjectMeshFromMemblock ( objID, meshIndex, memID )


_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RemiD

Quote
It's more like Blitz'es memorybanks or a buffer I think.
yes i agree, i edited my post while you were writing this post...

Rick Nasher

Quote from: RemiD on March 02, 2018, 22:33:28
Quote
It's more like Blitz'es memorybanks or a buffer I think.
yes i agree, i edited my post while you were writing this post...

D.. Now I have to re-re-edit my post not too look silly again.. lol

But you are right: there are no AddVertex() or DeleteVertex() commands afaik.
Unless SetMeshMemblockVertexPosition ( memID, vertexIndex, x, y, z ) add's one if it doesn't exits yet?


_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RemiD

No, apparently you can't create a vertex or create a triangle, you can only analyze an existing surface or modify an existing surface. Or if it is possible, where are the commands ?

That may be why the code example that Qube posted shows how to export (save) a mesh as an obj file and then load it...


TomToad

I am very close to getting a triangle done. Unfortunately,I ran out of time and won't be back at my computer for the next 12 hours. Creating a mesh is a little complicated as you also need to provide information for the shaders, even if you don't use one as AGK still uses a default shader.  Fortunately, once you create the long and difficult mesh header, you can just copy it over to any mesh using the same structure, just change the vertex count and offset to point to the right locations.

------------------------------------------------
8 rabbits equals 1 rabbyte.

Rick Nasher

@TomToad
That's sounds really interesting. Can't wait to see how that works.

BTW: hope you don't mind, but I think your previous example is a pretty good demo of the commands, so I submitted it to the AGK command help like this:


// Project: CreateObjectFromMeshMemblock
// Created: 2018-03-02
// By: TomToad

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "CreateObjectFromMeshMemblock" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts


box = CreateObjectBox(10,10,10)
meshmemblock = CreateMemblockFromObjectMesh(box,1)
direction as float = 1.0
time as float
wait as float = 5.0
vertex as integer[2] = [1,19,20]

do
time = GetFrameTime()
RotateObjectLocalX(box,.1)
RotateObjectLocalY(box,.2)
RotateObjectLocalZ(box,.3)
for i = 0 to 2
SetMeshMemblockVertexPosition(meshmemblock,vertex[i],
GetMeshMemblockVertexX(meshmemblock,vertex[i])+direction*time,
GetMeshMemblockVertexY(meshmemblock,vertex[i])+direction*time,
GetMeshMemblockVertexZ(meshmemblock,vertex[i])+direction*time)

next
wait = wait - time
if wait <= 0.0
wait = 5.0
direction = -direction
endif
SetObjectMeshFromMemblock(box,1,meshmemblock)
sync()
loop


At: https://www.appgamekit.com/documentation/Reference/Memblock/SetMeshMemblockVertexPosition.htm
Currently waiting for approval..
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RemiD

@TomToad>>curious to see your code example...

I suppose that you can create custom functions to read write in memblocks (in AGK), similarly that what we do to read write in banks (in blitzbasic), it would simplify things greatly !

Naughty Alien

Quote from: RemiD on March 03, 2018, 11:07:31
@TomToad>>curious to see your code example...

I suppose that you can create custom functions to read write in memblocks (in AGK), similarly that what we do to read write in banks (in blitzbasic), it would simplify things greatly !

...yes..actually, you can write in C++ (AGK) and then export plugin for AGK to use and expand API on the way you like it..thats my work in progress right now (rewriting old Lotus particle system for B3D, for AGK, as a plugin)..

Rick Nasher

At Naughty Alien
Quote...yes..actually, you can write in C++ (AGK) and then export plugin for AGK to use and expand API on the way you like it..thats my work in progress right now (rewriting old Lotus particle system for B3D, for AGK, as a plugin)..

That's great used to love that. Had a demo of it long time ago, but can't remember all the features though. I take that it holds advantages over the AGK's build in particle system?
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

Naughty Alien

Quote from: Rick Nasher on March 03, 2018, 14:36:18
At Naughty Alien
Quote...yes..actually, you can write in C++ (AGK) and then export plugin for AGK to use and expand API on the way you like it..thats my work in progress right now (rewriting old Lotus particle system for B3D, for AGK, as a plugin)..

That's great used to love that. Had a demo of it long time ago, but can't remember all the features though. I take that it holds advantages over the AGK's build in particle system?

..in essence it is Lotus'ed AGK particle system..more a system which allows me to copy/paste some code i used before (i had Lotus rewritten for NF/C++/) , and added some neat features including physics particles, soft particles, etc..

Rick Nasher

_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

Rick Nasher

Got some feedback from janbo on the AGK forums about RemiD's question:

Quote
In the Minecraft clone thread for example I posted code to create separate faces for cubes from memblock it can also be used to generate all sorts of models.
This is the important part:

function CreateFace(CubeX,CubeY,CubeZ,Direction)
    if Cube[CubeX,CubeY,CubeZ].Face[Direction]=0
        Size#=0.5

        MemblockID=CreateMeshMemblock()

        select Direction
            case DUP:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX-Size#,CubeY+Size#,CubeZ+Size#)     // Vertex
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,0,1,0)     // Normals
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0)       // UV
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX-Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,0,1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX+Size#,CubeY+Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,0,1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX+Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,0,1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,1,1)
            endcase
            case DDOWN:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX-Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,0,-1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX-Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,0,-1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX+Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,0,-1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX+Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,0,-1,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,1,1)
            endcase
            case DRIGHT:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX+Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,1,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX+Size#,CubeY+Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX+Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX+Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,0,0)
            endcase
            case DLEFT:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX-Size#,CubeY+Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,-1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX-Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,-1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX-Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,-1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX-Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,-1,0,0)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,1,1)
            endcase
            case DFRONT:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX-Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,0,0,-1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX-Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,0,0,-1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX+Size#,CubeY+Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,0,0,-1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX+Size#,CubeY-Size#,CubeZ-Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,0,0,-1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,1,1)
            endcase
            case DBACK:
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,CubeX+Size#,CubeY+Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,0,0,1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+8*4,CubeX+Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+11*4,0,0,1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+14*4,0,1)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+16*4,CubeX-Size#,CubeY+Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+19*4,0,0,1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+22*4,1,0)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+24*4,CubeX-Size#,CubeY-Size#,CubeZ+Size#)
                SetMemblockVec3(MemblockID,VERTEX_OFFSET+27*4,0,0,1)
                SetMemblockVec2(MemblockID,VERTEX_OFFSET+30*4,1,1)
            endcase
        endselect

        //~ Indices
        SetMemblockInt(MemblockID,IndexOffset+0*4,0)
        SetMemblockInt(MemblockID,IndexOffset+1*4,1)
        SetMemblockInt(MemblockID,IndexOffset+2*4,2)
        SetMemblockInt(MemblockID,IndexOffset+3*4,2)
        SetMemblockInt(MemblockID,IndexOffset+4*4,1)
        SetMemblockInt(MemblockID,IndexOffset+5*4,3)

        Cube[CubeX,CubeY,CubeZ].Face[Direction]=BuildMeshMemblock(MemblockID)

        SetFaceTexture(CubeX,CubeY,CubeZ,Direction)
    endif
endfunction

// here starts the memblock manipulation functions
function CreateMeshMemblock()
    VertexCount=4
    IndexCount=6
    Attributes=3
    VertexSize=3*4+3*4+2*4
    IndexOffset=VERTEX_OFFSET+(VertexCount*VertexSize)

    MemblockID=Creatememblock(VERTEX_OFFSET+(VertexCount*VertexSize)+(IndexCount*4))
    SetMemblockInt(MemblockID,0,VertexCount)
    SetMemblockInt(MemblockID,4,IndexCount)
    SetMemblockInt(MemblockID,8,Attributes)
    SetMemblockInt(MemblockID,12,VertexSize)
    SetMemblockInt(MemblockID,16,VERTEX_OFFSET)
    SetMemblockInt(MemblockID,20,IndexOffset)

    AttributeOffset=24
    SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
    SetMemblockByte(MemblockID,AttributeOffset+1,3) // number of components
    SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
    SetMemblockByte(MemblockID,AttributeOffset+3,12) // string length
    SetMemblockString(MemblockID,AttributeOffset+4,"position"+chr(0)) // string

    inc AttributeOffset,16
    SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
    SetMemblockByte(MemblockID,AttributeOffset+1,3) // number of components
    SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
    SetMemblockByte(MemblockID,AttributeOffset+3,8) // string length
    SetMemblockString(MemblockID,AttributeOffset+4,"normal"+chr(0)) // string

    inc AttributeOffset,12
    SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
    SetMemblockByte(MemblockID,AttributeOffset+1,2) // number of components
    SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
    SetMemblockByte(MemblockID,AttributeOffset+3,4) // string length
    SetMemblockString(MemblockID,AttributeOffset+4,"uv"+chr(0)) // string
endfunction MemblockID

function BuildMeshMemblock(MemblockID)
    ObjectID=CreateObjectFromMeshMemblock(MemblockID)
    DeleteMemblock(MemblockID)
endfunction ObjectID

function SetMemblockVec3(MemblockID,Offset,x#,y#,z#)
    SetMemblockFloat(MemblockID,Offset,x#)
    SetMemblockFloat(MemblockID,Offset+4,y#)
    SetMemblockFloat(MemblockID,Offset+8,z#)
endfunction

function SetMemblockVec2(MemblockID,Offset,u#,v#)
    SetMemblockFloat(MemblockID,Offset,u#)
    SetMemblockFloat(MemblockID,Offset+4,v#)
endfunction

Quote
In the CreateFace() function I set the vertex position, normal an uv coordinate for every vertex of one side of the cube.

You need these steps:
1. MemblockID=CreateMeshMemblock() // generate the mesh
2.
- SetMemblockVec3(MemblockID,VERTEX_OFFSET+0,0,0,0) // set Vertex position (you can also use SetMeshMemblockVertexPosition() here)
- SetMemblockVec3(MemblockID,VERTEX_OFFSET+3*4,0,1,0) // Normals
- SetMemblockVec2(MemblockID,VERTEX_OFFSET+6*4,0,0) // UV
3. SetMemblockInt(MemblockID,IndexOffset+0*4,0) // (optional) set the indices
4. ObjectID=BuildMeshMemblock(MemblockID) // finish and return the object ID

[Edit] I wonder how we are supposed to remove a mesh from an object previously added with AddObjectMeshFromMemblock[/Edit]
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RemiD

I rather meant to code specific functions (for AGK) to help read / write in banks (memblocks) to simplify the code syntax... it is probably what the functions CreateMesh(), CreateSurface(Mesh), AddVertex(Surface,X,Y,Z), AddTriangle(Surface,V0I,V1I,V2I), and others surface / vertex / triangle related functions, in Blitzbasic, do...

TomToad

Ok, I now have my triangle appearing on the screen.

// Project: triangle
// Created: 2018-03-03

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "triangle" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

//first we will create a memblock to hold the mesh
memblock = CreateMemblock(160)

//Now we need to fill it with mesh data
SetMemblockInt(memblock,0,3) //3 vertices
SetMemblockInt(memblock,4,3) //3 indices, not necissary for simple triangle, but we do it here for completeness
SetMemblockint(memblock,8,3) //Our mesh has 3 attributes, position, normal, color
Setmemblockint(memblock,12,28) //number of bytes each vertext takes up. x,y,z,nx,ny,nz,color * 4
SetMemblockInt(memblock,16,64) //offset to vertex data
SetMemblockInt(memblock,20,148) //offset to index data

//Attribute information, I'm combining all bytes into a single int. 
//   Little endiness means order is string length, normal flag, component count, data type (data will
//   be written to the MemBlock in reverse order).
SetMemBlockInt(memblock,24,0x0C000300) //float, 3 components, no normalizing, position
SetMemblockString(memblock,28,"position")
SetMemblockInt(memblock,40,0x08000300) //same as position, but for normals
SetMemblockString(memblock,44,"normal")
SetMemblockInt(memblock,52,0x08010401) //For color we have byte, 4 components, normalize data
SetMemblockString(memblock,56,"color")

//Now we can enter vertex data

Vertex as float[8] = [5.0,-5.0,0.0,-5.0,-5.0,0.0,0.0,5.0,0.0]
Color as integer[2] = [0xFFFF0000,0xFF00FF00,0xFF0000FF]

for i = 0 to 2
SetMemblockFloat(memblock,64+i*28,Vertex[i*3]) //x
SetMemblockFloat(memblock,68+i*28,Vertex[i*3+1]) //y
SetMemblockFloat(memblock,72+i*28,Vertex[i*3+2]) //z
SetMemblockFloat(memblock,76+i*28,0.0) //nx
SetMemblockFloat(memblock,80+i*28,0.0) //ny
SetMemblockFloat(memblock,84+i*28,-1.0) //nz
SetMemblockInt(memblock,88+i*28,Color[i]) //color
next
// Now the index data
SetMemblockInt(memblock,148,0)
SetMemblockInt(memblock,152,2)
SetMemblockInt(memblock,156,1)

//Now to create the object
triangle = CreateObjectFromMeshMemblock(memblock)


do
   

    Print( ScreenFPS() )
    Sync()
loop

A few things to note.  I packed the attribute data (4 bytes) into one integer.  The order of the bytes are reversed since integers are little endian and the bytes will be reversed when written to memory.

AGK allows different attributes to be defined.  My example only defines position, normal, and color.  Just add the attributes you want and define them in the vertex information.  You can even define custom attributes as long as you write a shader that takes care of them.  A complete list of standard attributes are in the AGK command help for CreateObjectFromMeshMemblock().

I found trying to define the header the most complicated part of the code.  Won't be so difficult now that I know how to do it.  When I get the time, I'll write out a short tutorial explaining just what each of the fields are for.  Once the header is created, it can be copied to any mesh memblock that uses the same structure.

One negative that I found is that you need to be able to determine how big to create the memblock before you start adding the data.  There doesn't seem to be an easy way to expand memblock size without creating a new one and copying over the data.  That is only a problem if you don't know ahead of time how many vertices and indices your mesh will need. It might be easier to create the structure using a custom type and then creating the memblock when you are done with that.
------------------------------------------------
8 rabbits equals 1 rabbyte.