I'm going to call this...
Chapter 1.3 - Making a Plain from Nothing
After digesting all of the suggestions and information about indexes (or
indices, both are acceptable),I have come to the conclusion that the standard AppGameKit Plain is not adequate for my needs.
1. It has no indices. The plain is made up of 12 vertices. That is one for every
corner of every triangle in the plain.
2. To move one corner of the Plain, I have to locate up to 4 vertices, and apply the same transformation to each
3. To change any other attribute of the plain, such as the normals or UV, the same process of finding up to 4 vertices must be followed
4. there is a large scope for error
5, I would assume that shaders and so forth will have the same laborious task as me, finding multiple vertices for one point on the plain.
The solution, therefore, seems to be to make my own. I tried making a Plain in Wings3D, which should theoretically be one of the simplest. It did not however prove to be a simplistic task, having to tessalate quads
after rotating one face to align the resulting triangles. It seemed rather messy and lacking control. So I will resolve my dilemma by coding the Plain. Along the way, I'll make sure I can reuse the functionality to make more complex shapes.
Dispelling the myth
Firstly, a misunderstanding has crept in. It
is possible to use indices in Memblock Meshes. The default AppGameKit plain does not have indices. But the memblocks facilitate the use of them.
Making a skeleton memblock mesh
To make the code reusable, I will tackle the challenge in 2 steps:
1. Create a function that builds a skeleton mesh memblock. This will accept parameters for the number of vertices and another for the number of indices. It will build a skeleton with 3 attributes: position, normals and UV coordinates
2.Create a function that makes a Plain mesh memblock. This will utilise the aforementioned function, and then finalise the mesh by setting the attribute values.
So the Plain configuration is like so, the numbers identifying the vertices
The Indices for the top are 3,1,0 and 3,2,1
The Indices for the bottom are 0,1,3 and 1,2,3
Here is the code. Firstly, the constants have been extended:
#constant cMESH_NUM_VERTICES = 0
#constant cMESH_NUM_INDICES = 4
#constant cMESH_NUM_ATTRIBUTES = 8
#constant cMESH_SIZE_VERTEX = 12
#constant cMESH_OFFSET_VERTEX = 16
#constant cMESH_OFFSET_INDEX = 20
#constant cMESH_OFFSET_ATTRIBUTES = 24
#constant cMESH_DATATYPE_FLOAT = 0
#constant cMESH_DATATYPE_BYTE = 1
#constant cMESH_VERTEX_POS_X = 0
#constant cMESH_VERTEX_POS_Y = 4
#constant cMESH_VERTEX_POS_Z = 8
#constant cMESH_VERTEX_NORM_X = 12
#constant cMESH_VERTEX_NORM_Y = 16
#constant cMESH_VERTEX_NORM_Z = 20
#constant cMESH_VERTEX_UV_U = 24
#constant cMESH_VERTEX_UV_V = 28
Next, the generic Function to create a skeleton mesh for any quantity of vertices and indices:
//***********************************************
//Creates a mesh with the basic 3 attributes (position, normal, UV)
//***********************************************
function MeshCreateMemblock(mb, numVertices, numIndices)
local numAttributes
local sizeVertex
local offsetVertex
local offsetIndex
numAttributes = 3
sizeVertex = 32
offsetVertex = 60
offsetIndex = offsetVertex + (sizeVertex * numVertices)
//Create element and references
gMesh.length = gMesh.length + 1
id = gMesh.length
gMesh[id].memblock = mb
//Delete Memblock and create at right size
DeleteMemblock(mb)
// Header
mbSize = 24
//Attribute descriptions (4 + string length to nearest 4 bytes)
//position = 12: normal = 8: UV = 4
inc mbSize, 36
// 12 for pos, 12 for normals, 8 for UV
inc mbSize, (numVertices * 32)
inc mbSize, (numIndices * 4)
CreateMemblock(mb, mbSize)
//Create header data
SetMemblockInt(mb, cMESH_NUM_VERTICES, numVertices)
SetMemblockInt(mb, cMESH_NUM_INDICES, numIndices)
SetMemblockInt(mb, cMESH_NUM_ATTRIBUTES, numAttributes)
SetMemblockInt(mb, cMESH_SIZE_VERTEX, sizeVertex)
SetMemblockInt(mb, cMESH_OFFSET_VERTEX, offsetVertex)
SetMemblockInt(mb, cMESH_OFFSET_INDEX, offsetIndex)
attStart = cMESH_OFFSET_ATTRIBUTES
setMemblockByte(mb,attStart , 0)
setMemblockByte(mb, attStart + 1, 3)
setMemblockByte(mb, attStart + 2, 0)
setMemblockByte(mb, attStart + 3, 12)
SetMemblockString(mb, attStart + 4, "position" + chr(0))
inc attStart, 16
setMemblockByte(mb,attStart , 0)
setMemblockByte(mb, attStart + 1, 3)
setMemblockByte(mb, attStart + 2, 0)
setMemblockByte(mb, attStart + 3, 8)
SetMemblockString(mb, attStart + 4, "normal" + chr(0))
inc attStart, 12
setMemblockByte(mb,attStart , 0)
setMemblockByte(mb, attStart + 1, 2)
setMemblockByte(mb, attStart + 2, 0)
setMemblockByte(mb, attStart + 3, 4)
SetMemblockString(mb, attStart + 4, "uv" + chr(0))
//Initialise all values to 0
vertStart = offsetVertex
for n = vertStart to (numVertices * sizeVertex) step 4
SetMemblockFloat(mb,n, 0.0)
next n
endfunction id
And finally the function to create a Plain mesh. this calls the previous function and then populates the required values:
//***********************************************
//Creates a mesh Plain
//***********************************************
function createMeshPlain(mb)
local numVertices
local numIndices
local numAttributes
local sizeVertex
local offsetVertex
local offsetIndex
numVertices = 4
numIndices = 12
numAttributes = 3
sizeVertex = 32
offsetVertex = 60
offsetIndex = offsetVertex + (sizeVertex * numVertices)
MeshCreateMemblock(mb, numVertices, numIndices)
// Write each vertex (start bottom left, anticlockwise)
//**************
// *** Vertex 0 ***
//**************
vertStart = offsetVertex
//Pos = 0,0,0
//Norms = 0,1,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_NORM_Y,1.0)
//UVs = 0,1
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_UV_V,1.0)
//**************
// *** Vertex 1 ***
//**************
inc vertStart, sizeVertex
//pos = 1,0,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_POS_X,1.0)
//Norms = 0,1,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_NORM_Y,1.0)
//UVs = 1,1
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_UV_U,1.0)
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_UV_V,1.0)
//**************
// *** Vertex 2 ***
//**************
inc vertStart, sizeVertex
//pos = 1,0,1
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_POS_X,1.0)
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_POS_Z,1.0)
//Norms = 0,1,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_NORM_Y,1.0)
//UVs = 1,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_UV_U,1.0)
//**************
// *** Vertex 3 ***
//**************
inc vertStart, sizeVertex
//pos = 0,0,1
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_POS_Z,1.0)
//Norms = 0,1,0
SetMemblockFloat(mb,vertStart + cMESH_VERTEX_NORM_Y,1.0)
//UVs = 0,0
//Write Indexes
indexStart = offSetIndex
SetMemblockInt(mb,indexStart, 0)
SetMemblockInt(mb,indexStart + 4, 1)
SetMemblockInt(mb,indexStart + 8, 3)
inc IndexStart, 12
SetMemblockInt(mb,indexStart, 1)
SetMemblockInt(mb,indexStart + 4, 2)
SetMemblockInt(mb,indexStart + 8, 3)
inc IndexStart, 12
SetMemblockInt(mb,indexStart, 3)
SetMemblockInt(mb,indexStart + 4, 1)
SetMemblockInt(mb,indexStart + 8, 0)
inc IndexStart, 12
SetMemblockInt(mb,indexStart, 3)
SetMemblockInt(mb,indexStart + 4, 2)
SetMemblockInt(mb,indexStart + 8, 1)
endfunction
The final note for this entry is that I have not yet tested of I only need one side of the Plain with culling disabled. I will look into this again later.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt