Example Cube Mesh Generator

About Truespace Archives

These pages are a copy of the official truespace forums prior to their removal somewhere around 2011.

They are retained here for archive purposes only.

Example Cube Mesh Generator // Scriptorium

1  |  

Post by ProfessorKhaos // Mar 12, 2007, 8:55pm

ProfessorKhaos
Total Posts: 622
pic
Hi all,


Per other conversations I've had, I think it would be useful to develop an example "mesh generator" to show folks how to make their own primitives using scripts. The cone script object that came with the Script Objects library is functional but an incomplete example for more advanced scripting needs.


About the simplest of objects around for this task is our friend the cube. It has surface normals which point in cardinal directions and is easy enough for most folks to follow in terms of vertex locations and triangle/face definitions.


Since I don't have all the answers, this is not quite yet ready to be "tutorial fodder" or "scriptlet contribution" but perhaps through online collaboration between us scriptwriters and occasional input from caligari's staff we may grow this example to the point where it is more useful for advanced projects.


Anyway, I've created an initial mesh generating brick which I've nested inside of another object and used it's output to modify the shape brick, which in turn allows us to see our mesh visualized.


The current version illustrates in a deliberately brute force way the assignment of vertices, triangles, and material indices (which aren't really necessary as implemented, but does serve a purpose for example's sake). Faces aren't used but future meshes should probably implement that too.


Please feel free to hack, bludgeon, and murder the attached script and post your findings/lessons learned, etc.


I, for one, would like to add UV mapping to support direct texturing, and normal definitions to the object to make it appear appropiately faceted (sp?) on the player side. Face definitions (so that you can group triangles together) would be good too.


Anyway, here's my script so far... saved as a .rcd file so you'll have to use the record toolbar to import. I've added a few extra objects to the scene to help you get your bearings (labels for +X, +Y, and +Z). Please note that coordinates on the player side are not the same as the modeller side. Player side is a left handed coordinate system whereas modeller is right handed. The scripts act against the player side of the house.


Owing to the fact that the script object is centered at 0,0,0 you may wish to turn off the ground plane in player to view it.


Glen

Post by ProfessorKhaos // Mar 12, 2007, 9:24pm

ProfessorKhaos
Total Posts: 622
pic
For convenience, here's the guts of the mesh generator script.



// OnComputeOutputs

// Called to compute values of all output connectors

function OnComputeOutputs(params)

{


// TODO: put your computation here


// create vertices (8 total)

//

// note: To keep things simple, we're defining the corner points of a cube of 2x2x2

// units (-1 to +1 for each dimension). You can use scripts or whatever to

// define these points if you so wish.

//

// I assume the BeginWrite and EndWrite items lock down the VertexList such

// that other internals are not updated until the list editing is complete but

// I'm not quite sure why that is.


VertexList = System.CreateDO('Space 3D Package/Vertex Stream Data');


VertexList.SetNumVertices(8);

VertexList.BeginWrite();


VertexList.x(0) = 1.0; VertexList.y(0) = 1.0; VertexList.z(0) = 1.0;

VertexList.x(1) = 1.0; VertexList.y(1) = -1.0; VertexList.z(1) = 1.0;

VertexList.x(2) = 1.0; VertexList.y(2) = -1.0; VertexList.z(2) = -1.0;

VertexList.x(3) = 1.0; VertexList.y(3) = 1.0; VertexList.z(3) = -1.0;

VertexList.x(4) = -1.0; VertexList.y(4) = 1.0; VertexList.z(4) = 1.0;

VertexList.x(5) = -1.0; VertexList.y(5) = -1.0; VertexList.z(5) = 1.0;

VertexList.x(6) = -1.0; VertexList.y(6) = -1.0; VertexList.z(6) = -1.0;

VertexList.x(7) = -1.0; VertexList.y(7) = 1.0; VertexList.z(7) = -1.0;


VertexList.EndWrite();


// create triangles from vertices (12 total)

//

// note: All triangle vertices defined clockwise from top (showing) face.

// If you get them backwards, the triangle will only be visible from

// the back side (unless double sided rendering is also turned on).

//

// Same issue applies here with regards to BeginWrite and EndWrite as with

// the VertexList stuff above. I don't know exactly what it does but it's

// in all the other examples I've seen.


TriangleList = System.CreateDO('Space 3D Package/Triangle Vertices Stream Data');


TriangleList.SetNumTripleIndices(12);

TriangleList.BeginWrite();



TriangleList.i(0) = 0; TriangleList.j(0) = 1; TriangleList.k(0) = 3; // +x face triangles

TriangleList.i(1) = 2; TriangleList.j(1) = 3; TriangleList.k(1) = 1;

TriangleList.i(2) = 1; TriangleList.j(2) = 5; TriangleList.k(2) = 2; // -y face triangles

TriangleList.i(3) = 6; TriangleList.j(3) = 2; TriangleList.k(3) = 5;

TriangleList.i(4) = 5; TriangleList.j(4) = 4; TriangleList.k(4) = 6; // -x face triangles

TriangleList.i(5) = 7; TriangleList.j(5) = 6; TriangleList.k(5) = 4;

TriangleList.i(6) = 4; TriangleList.j(6) = 0; TriangleList.k(6) = 7; // +y face triangles

TriangleList.i(7) = 3; TriangleList.j(7) = 7; TriangleList.k(7) = 0;

TriangleList.i(8) = 2; TriangleList.j(8) = 6; TriangleList.k(8) = 3; // -z face triangles

TriangleList.i(9) = 7; TriangleList.j(9) = 3; TriangleList.k(9) = 6;

TriangleList.i(10) = 1; TriangleList.j(10) = 0; TriangleList.k(10) = 5; // +z face triangles

TriangleList.i(11) = 4; TriangleList.j(11) = 5; TriangleList.k(11) = 0;


TriangleList.EndWrite();


// create material indices for triangles

//

// note: In our case this doesn't do much since I'm assigning the default material

// (count starts at 0, not 1) but you could control which material used on a per

// triangle basis. Index points to material in order that they are defined in the

// material list brick.


MaterialList = System.CreateDO('Space 3D Package/Material Index Stream Data');

MaterialList.SetNumMaterialIndices(12);


MaterialList.index(0) = 0; MaterialList.index(1) = 0; // +x face materials

MaterialList.index(2) = 0; MaterialList.index(3) = 0; // -y face materials

MaterialList.index(4) = 0; MaterialList.index(5) = 0; // -x face materials

MaterialList.index(6) = 0; MaterialList.index(7) = 0; // +y face materials

MaterialList.index(8) = 0; MaterialList.index(9) = 0; // -z face materials

MaterialList.index(10) = 0; MaterialList.index(11) = 0; // +z face materials


// create faces from triangles (associates & hides internal edges of triangles)

//

// note: Haven't done this before myself. Doesn't appear necessary unless you wish

// to work with faces that have more than 3 vertices (probably true in most

// mesh editing scenarios (i.e. quads are often preferred once initial mesh

// is generated).







// create normals for each face/triangle(?)

//

// note: Haven't ever done this before but it's necessary if you want faceted objects.

// Otherwise normals represent the averaged normal of each face/triangle(?) using

// the associated vertex.

//

// Most likely consists of a NormalVectorList (much akin to vertex list) and

// a NormalIndexList corresponding to the normals used by each vertex

// within the respective TriangleList

//

// This is all speculation though. More research required






// create output mesh from above defined items (vertices, triangles, materials, etc.)


outMesh = System.CreateDO('Space 3D Package/Mesh Data');


outMesh.AttachVerticesStream(VertexList);

outMesh.AttachTrianglesStream(TriangleList);

outMesh.AttachTrianglesStream(MaterialList);


// send data to output connector


params.conValue("outMesh") = outMesh;

}

Post by ProfessorKhaos // Mar 12, 2007, 9:34pm

ProfessorKhaos
Total Posts: 622
pic
A good reference thread... should help to crack the 'normals' code, thanks in large part to tomasb's inputs. :)


http://forums1.caligari.com/truespace/showthread.php?t=1628


Also will be useful when discussion of normals calculation becomes more significant (follow on example scripts since cube normals are easy).


I think some of this is starting to slowly sink in so maybe I'll have faces defined and hopefully normals defined by next go round.

Post by Emma // Mar 13, 2007, 11:11am

Emma
Total Posts: 344
pic
I understand mechanism similar to following


.....System.CreateDO(.....


- initiates a function for a special purpose

- BeginWrite, initializes internal variables, reserves a buffer for Data stream

- EndWrite, does some caclulations with above Data stream so the result fits into internal trueSpace Mesh structure


Think this internal structure is secret as it will represent power of trueSpace. What we do with those Data streams is feeding this mechanism with corresponding data that depends on each other.


So first define the vertices: Begin - Data - End

- This gets put now into the mesh structure, maby there is transformation of coordinates, filling an internal database, error checks, and/or other


Next define the edges to build the faces

- This depends on an already existing data structure containing the vertices but also gets put into the internal mesh data structure


Defining the normals now - and here I 'm still guessing- is an additional info belonging to each one of defined faces. If it is not there trueSpace shows now sharp edges if you have a corner folding between two faces. Setting the normals would set kind of a 90 degree pointer for the whole face area thus building sharp edges. This pointer or whatever you call it must also fit into the internal mesh structure as it on one side is a reference for faces but on the opposite needs the information stored already in vertex face data.


Easy thought, take a face number and associate a normal value like ON or OFF to it. But as much as I could understand from what tomasb said it's not that easy, you rather have to do some kind of calculation for the edges belonging to a face, math behind is some kind of matrix manipulation. This matrix again is a "collection matrix" of coordinates ? which again leaves the question what coordinate system are we talking about in that moment.


Have the feeling I'm talking about nonsense here as nothing leads me to an answer. Perhaps wrong question at all, so ok, what is one of those normals ? can we say it is a pointer that is pointing in a 90 degree angle away from the surface of a given face ? Hmmm, is there a math that I can grab this with ?

Still questions over questions for me.


tomasb said:


- "Normals are defined very similar to vertices, you define indices to normals... to get faceted appearing, set all normal indices to equal value "


Ok, that sounds logically, if Normal-Pointers ( as I will call them now) are pointing different direction, an effect like Material-shading is different from pointer to pointer and thus the surface will not look evenly plane

Setting same value for pointers of the whole plane to an equal value means it appearas all the same all over,theoretically if you have two faces with a sharp edge but equal normals than they should appear like one single large evenly plane, is that right ?


Ok, next one, we want a sharp edge. so define a "room circle" of 360 degree. One face is pointing with it's normals to let's say 10 degree of our defined room while the other one is pointig into 170 degree direction. Is there some kind of matrix calculation doing this ?


Back to what tomasb said, want sharp corners, so equal value for your indices !


for (i = 0; i<triangle_count;i++)

{

normal_index[i].i = i;

normal_index[i].j = i;

normal_index[i].k = i;


- Ok, so which CreateDO function has to be called so we can work with that index assignments ?

- can we say we use the same index number (above sample i) for the normal and the face, such face #1 = normal[1] ?


Next comes my headache, I would have expected something like


normal_vector = (triangle_vertices[ triangle_indices[i].i ]

[I]

but no, that would be to simple , it follows a subtraction of the second vector


- triangle_vertices[ triangle_indices.j ])


[I]and to make it only understandable for the experts we have to do some cross mathematics


cross (triangle_vertices[ triangle_indices[i].j ] - triangle_vertices[ triangle_indices[i].k ]);


Wonder if this secret will get discovered....

Post by ProfessorKhaos // Mar 13, 2007, 3:07pm

ProfessorKhaos
Total Posts: 622
pic
Almost forgot to answer your question... Yep. If same normal is assigned to all vertices in a triangle, then that surface will appear uniformly flat. Ligthworks appears to calculate it's own normals based on material settings but I think directX uses these normals directly


Actually, that last part about normals calculation I followed pretty well. Let's take an easy example.


Let's say you have a triangle composed of the following 3 vertices


v1 = (2,4,3)

V2 = (4,4,3)

V3 = (4,6,3)


This gives you a horizontal triangle face about 3 units up from the ground and offset a bit from center. It also has an area of 2 square units (1/2 of a 2x2 square, irrelevant to the problem at hand though)


The subtraction of one vertex from the others is basically a technique to shift the vertices such that one of the vertices at the origin and the other two turn into direction vectors. Thus, let's pick v1 to subtract from our vertices as a whole.


new_v1 = v1 - v1 = (2,4,3) - (2,4,3) = (0,0,0) <------doesn't have to be calculated. This will always come up (0,0,0) and has no further use in our discussion except as reference.

new_v2 = v2 - v1 = (4,4,3) - (2,4,3) = (2,0,0)

new_v3 = v3 - v1 = (4,6,3) - (2,4,3) = (2,2,0)


Now comes the tricky part. We know from observation that the above is still a horizontally oriented triangle and that the normal should be defined in the +Z direction (we're assuming left handed coord system. Curl fingers on left hand from x to y and thumb points in +z direction)


So, we need a vector that essentially is 1 unit long and vertical... in other words, (0,0,1).


Cross product is a fancy math tool used for obtaining a vector which just happens to be perpendicular to the two other vectors. Only drawback is that it's length varies such that it's also twice the area of our triangle.


Length of any vector can easily be found using the following equation


length = sqrt(delta_x^2 + delta_y^2 + delta_z^2)


So, if we divide the cross product vector by the length we get a unit vector (length = 1)


One catch though... if the cross product vector has a length of 0 this breaks down. It also kinda becomes irrelevant because your triangle's area ceases to exist as the angle between the vectors goes to zero or the length of one of the vectors goes to zero. It's still something that may have to be tracked.


Since cross product is defined as


(a,b,c) = (d,e,f) x (g,h,i)


where x indicates cross product,


a = (e*i - f*h)

b = (f*g -d*i)

c = (d*h-e*g)


In our example,


Vn = (a,b,c)

new_v2 = (d,e,f) = (2,0,0)

new_v3 = (g,h,i) = (2,2,0)


Thus:


a = (0*0 - 0*2) = 0

b = (0*2 - 2*0) = 0

c = (2*2 - 0*2) = 4


and Vn = (0,0,4) which is most definately up, but too long to be the right vector (and is magically twice the area of our triangle...)


The length of Vn can be derived as


L = sqrt(a^2 + b^2 + c^2) = sqrt(0 + 0 + 4*4) = sqrt(16) = 4


So dividing Vn by L you get


N = Vn/L = (0,0,4) / 4 = (0,0,1).


This method also works for any 3 vertices so long as they don't all lie on the same line. If they do, then you may as well just define a unit normal of any direction since there's not going to be any significant area of the triangle to plot anyway.


==================================================


Face edge streams I think I'm catching on to the concept of.


Basically, for a triangle, the vertices v1, v2, and v3 are assigned in order such that the edges become


Edge 1 = v1->v2

Edge 2 = v2->v3

Edge 3 = v3->v1


Now, to make an edge visible or hidden you do the following (psuedo code)


For( i = 0; i < numTriangles; i++)

{

Temp_Sum = 0


if (Edge1 == on) Temp_Sum = Temp_Sum + 1;

if (Edge2 == on) Temp_Sum = Temp_Sum + 2;

if (Edge3 == on) Temp_Sum = Temp_Sum + 4; // note these increase by powers of 2. 0 indicates all edges off. 7 indicates all edges on.


Face_Edge[i] = Temp_Sum

}

Post by ProfessorKhaos // Mar 13, 2007, 3:37pm

ProfessorKhaos
Total Posts: 622
pic
Revised cube object... with face edge definitions... seems to work...



// OnComputeOutputs

// Called to compute values of all output connectors

function OnComputeOutputs(params)

{


// TODO: put your computation here


// create vertices (8 total)

//

// note: To keep things simple, we're defining the corner points of a cube of 2x2x2

// units (-1 to +1 for each dimension). You can use scripts or whatever to

// define these points if you so wish.

//

// I assume the BeginWrite and EndWrite items lock down the VertexList such

// that other internals are not updated until the list editing is complete but

// I'm not quite sure why that is.


VertexList = System.CreateDO('Space 3D Package/Vertex Stream Data');


VertexList.SetNumVertices(8);

VertexList.BeginWrite();


VertexList.x(0) = 1.0; VertexList.y(0) = 1.0; VertexList.z(0) = 1.0;

VertexList.x(1) = 1.0; VertexList.y(1) = -1.0; VertexList.z(1) = 1.0;

VertexList.x(2) = 1.0; VertexList.y(2) = -1.0; VertexList.z(2) = -1.0;

VertexList.x(3) = 1.0; VertexList.y(3) = 1.0; VertexList.z(3) = -1.0;

VertexList.x(4) = -1.0; VertexList.y(4) = 1.0; VertexList.z(4) = 1.0;

VertexList.x(5) = -1.0; VertexList.y(5) = -1.0; VertexList.z(5) = 1.0;

VertexList.x(6) = -1.0; VertexList.y(6) = -1.0; VertexList.z(6) = -1.0;

VertexList.x(7) = -1.0; VertexList.y(7) = 1.0; VertexList.z(7) = -1.0;


VertexList.EndWrite();


// create triangles from vertices (12 total)

//

// note: All triangle vertices defined clockwise from top (showing) face.

// If you get them backwards, the triangle will only be visible from

// the back side (unless double sided rendering is also turned on).

//

// Same issue applies here with regards to BeginWrite and EndWrite as with

// the VertexList stuff above. I don't know exactly what it does but it's

// in all the other examples I've seen.


TriangleList = System.CreateDO('Space 3D Package/Triangle Vertices Stream Data');


TriangleList.SetNumTripleIndices(12);

TriangleList.BeginWrite();



TriangleList.i(0) = 0; TriangleList.j(0) = 1; TriangleList.k(0) = 3; // +x face triangles

TriangleList.i(1) = 2; TriangleList.j(1) = 3; TriangleList.k(1) = 1;

TriangleList.i(2) = 1; TriangleList.j(2) = 5; TriangleList.k(2) = 2; // -y face triangles

TriangleList.i(3) = 6; TriangleList.j(3) = 2; TriangleList.k(3) = 5;

TriangleList.i(4) = 5; TriangleList.j(4) = 4; TriangleList.k(4) = 6; // -x face triangles

TriangleList.i(5) = 7; TriangleList.j(5) = 6; TriangleList.k(5) = 4;

TriangleList.i(6) = 4; TriangleList.j(6) = 0; TriangleList.k(6) = 7; // +y face triangles

TriangleList.i(7) = 3; TriangleList.j(7) = 7; TriangleList.k(7) = 0;

TriangleList.i(8) = 2; TriangleList.j(8) = 6; TriangleList.k(8) = 3; // -z face triangles

TriangleList.i(9) = 7; TriangleList.j(9) = 3; TriangleList.k(9) = 6;

TriangleList.i(10) = 1; TriangleList.j(10) = 0; TriangleList.k(10) = 5; // +z face triangles

TriangleList.i(11) = 4; TriangleList.j(11) = 5; TriangleList.k(11) = 0;


TriangleList.EndWrite();


// create material indices for triangles

//

// note: In our case this doesn't do much since I'm assigning the default material

// (count starts at 0, not 1) but you could control which material used on a per

// triangle basis. Index points to material in order that they are defined in the

// material list brick.


MaterialList = System.CreateDO('Space 3D Package/Material Index Stream Data');

MaterialList.SetNumMaterialIndices(12);


MaterialList.index(0) = 0; MaterialList.index(1) = 0; // +x face materials

MaterialList.index(2) = 0; MaterialList.index(3) = 0; // -y face materials

MaterialList.index(4) = 0; MaterialList.index(5) = 0; // -x face materials

MaterialList.index(6) = 0; MaterialList.index(7) = 0; // +y face materials

MaterialList.index(8) = 0; MaterialList.index(9) = 0; // -z face materials

MaterialList.index(10) = 0; MaterialList.index(11) = 0; // +z face materials


// create faces from triangles (associates & hides internal edges of triangles)

//

// note: Haven't done this before myself. Doesn't appear necessary unless you wish

// to work with faces that have more than 3 vertices (probably true in most

// mesh editing scenarios (i.e. quads are often preferred once initial mesh

// is generated).


FaceList = System.CreateDO('Space 3D Package/Face Edges Stream Data');

FaceList.SetNumTriangleEdges(12);


FaceList.edges(0) = 5; FaceList.edges(1) = 5; // +x face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)

FaceList.edges(2) = 5; FaceList.edges(3) = 5; // -y face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)

FaceList.edges(4) = 5; FaceList.edges(5) = 5; // -x face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)

FaceList.edges(6) = 5; FaceList.edges(7) = 5; // +y face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)

FaceList.edges(8) = 5; FaceList.edges(9) = 5; // -z face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)

FaceList.edges(10) = 5; FaceList.edges(11) = 5; // +z face edges, 5 = 1st and 3rd edge on (1*1 + 0*2 + 1*4)


// create normals for each face/triangle(?)

//

// note: Haven't ever done this before but it's necessary if you want faceted objects.

// Otherwise normals represent the averaged normal of each face/triangle(?) using

// the associated vertex.

//

// Most likely consists of a NormalVectorList (much akin to vertex list) and

// a NormalIndexList corresponding to the normals used by each vertex

// within the respective TriangleList

//

// This is all speculation though. More research required






// create output mesh from above defined items (vertices, triangles, materials, etc.)


outMesh = System.CreateDO('Space 3D Package/Mesh Data');


outMesh.AttachVerticesStream(VertexList);

outMesh.AttachTrianglesStream(TriangleList);

outMesh.AttachTrianglesStream(MaterialList);

outMesh.AttachTrianglesStream(FaceList);



// send data to output connector


params.conValue("outMesh") = outMesh;

}

Post by ProfessorKhaos // Mar 13, 2007, 8:43pm

ProfessorKhaos
Total Posts: 622
pic
Ok... having some difficulties but not where I would have expected.


Got the Vertex Normal Stream Data defined.


Can't seem to get the Triangles Normals Stream Data defined. System complains when I try.


Here's the code to date. Triangles Normals Stream Data has been commented out to allow script to be loaded.


Part 1 of 2 (had to split code to fit in a message)



// OnComputeOutputs

// Called to compute values of all output connectors

function OnComputeOutputs(params)

{


// TODO: put your computation here


// create vertices (8 total)

//

// note: To keep things simple, we're defining the corner points of a cube of 2x2x2

// units (-1 to +1 for each dimension). You can use scripts or whatever to

// define these points if you so wish.

//

// I assume the BeginWrite and EndWrite items lock down the VertexList such

// that other internals are not updated until the list editing is complete but

// I'm not quite sure why that is.


VertexList = System.CreateDO('Space 3D Package/Vertex Stream Data');


VertexList.SetNumVertices(8);

VertexList.BeginWrite();


VertexList.x(0) = 1.0; VertexList.y(0) = 1.0; VertexList.z(0) = 1.0;

VertexList.x(1) = 1.0; VertexList.y(1) = -1.0; VertexList.z(1) = 1.0;

VertexList.x(2) = 1.0; VertexList.y(2) = -1.0; VertexList.z(2) = -1.0;

VertexList.x(3) = 1.0; VertexList.y(3) = 1.0; VertexList.z(3) = -1.0;

VertexList.x(4) = -1.0; VertexList.y(4) = 1.0; VertexList.z(4) = 1.0;

VertexList.x(5) = -1.0; VertexList.y(5) = -1.0; VertexList.z(5) = 1.0;

VertexList.x(6) = -1.0; VertexList.y(6) = -1.0; VertexList.z(6) = -1.0;

VertexList.x(7) = -1.0; VertexList.y(7) = 1.0; VertexList.z(7) = -1.0;


VertexList.EndWrite();


// create triangles from vertices (12 total)

//

// note: All triangle vertices defined clockwise from top (showing) face.

// If you get them backwards, the triangle will only be visible from

// the back side (unless double sided rendering is also turned on).

//

// Same issue applies here with regards to BeginWrite and EndWrite as with

// the VertexList stuff above. I don't know exactly what it does but it's

// in all the other examples I've seen.


TriangleList = System.CreateDO('Space 3D Package/Triangle Vertices Stream Data');


TriangleList.SetNumTripleIndices(12);

TriangleList.BeginWrite();



TriangleList.i(0) = 0; TriangleList.j(0) = 1; TriangleList.k(0) = 3; // +x face triangles

TriangleList.i(1) = 2; TriangleList.j(1) = 3; TriangleList.k(1) = 1;

TriangleList.i(2) = 1; TriangleList.j(2) = 5; TriangleList.k(2) = 2; // -y face triangles

TriangleList.i(3) = 6; TriangleList.j(3) = 2; TriangleList.k(3) = 5;

TriangleList.i(4) = 5; TriangleList.j(4) = 4; TriangleList.k(4) = 6; // -x face triangles

TriangleList.i(5) = 7; TriangleList.j(5) = 6; TriangleList.k(5) = 4;

TriangleList.i(6) = 4; TriangleList.j(6) = 0; TriangleList.k(6) = 7; // +y face triangles

TriangleList.i(7) = 3; TriangleList.j(7) = 7; TriangleList.k(7) = 0;

TriangleList.i(8) = 2; TriangleList.j(8) = 6; TriangleList.k(8) = 3; // -z face triangles

TriangleList.i(9) = 7; TriangleList.j(9) = 3; TriangleList.k(9) = 6;

TriangleList.i(10) = 1; TriangleList.j(10) = 0; TriangleList.k(10) = 5; // +z face triangles

TriangleList.i(11) = 4; TriangleList.j(11) = 5; TriangleList.k(11) = 0;


TriangleList.EndWrite();


// create material indices for triangles

//

// note: In our case this doesn't do much since I'm assigning the default material

// (count starts at 0, not 1) but you could control which material used on a per

// triangle basis. Index points to material in order that they are defined in the

// material list brick.


MaterialList = System.CreateDO('Space 3D Package/Material Index Stream Data');

MaterialList.SetNumMaterialIndices(12);


MaterialList.index(0) = 0; MaterialList.index(1) = 0; // +x face materials

MaterialList.index(2) = 0; MaterialList.index(3) = 0; // -y face materials

MaterialList.index(4) = 0; MaterialList.index(5) = 0; // -x face materials

MaterialList.index(6) = 0; MaterialList.index(7) = 0; // +y face materials

MaterialList.index(8) = 0; MaterialList.index(9) = 0; // -z face materials

MaterialList.index(10) = 0; MaterialList.index(11) = 0; // +z face materials

Post by ProfessorKhaos // Mar 13, 2007, 8:44pm

ProfessorKhaos
Total Posts: 622
pic
Part 2 of 2


// create faces from triangles (associates & hides internal edges of triangles)

//

// note: Each entry in the FaceList controls the appearance of edges corresponding to the

// triangle with the same index in the TriangleList

//

// The number assigned to FaceList.edges(index) ranges from 0 to 7 and represents the

// on off status of the 3 triangle edges. The first edge is from the 1st to 2nd triangle

// vertex. The second edge is from the 2nd to 3rd triangle vertex. The third edge is

// from the 3rd to the 1st triangle vertex.

//

// The breakdown of values is as follows.

//

// 3rd 2nd 1st Binary decimal

// edge edge edge pattern value

// =====================================

// off off off 000 0

// off off on 001 1

// off on off 010 2

// off on on 011 3

// on off off 100 4

// on off on 101 5

// on on off 110 6

// on on on 111 7

//

// *3rd edge listed first to keep the on/off order the same as the MSB->LSB binary pattern

// If you don't know what this means, don't worry. Just use the decimal value that matches

// the case you want.

//

// Association of triangles into faces by virtue of common edge settings appears to be

// automatic


FaceList = System.CreateDO('Space 3D Package/Face Edges Stream Data');

FaceList.SetNumTriangleEdges(12);


FaceList.edges(0) = 5; FaceList.edges(1) = 5; // +x face edges, 5 = 1st and 3rd edge "on" (1*1 + 0*2 + 1*4)

FaceList.edges(2) = 5; FaceList.edges(3) = 5; // -y face edges

FaceList.edges(4) = 5; FaceList.edges(5) = 5; // -x face edges

FaceList.edges(6) = 5; FaceList.edges(7) = 5; // +y face edges

FaceList.edges(8) = 5; FaceList.edges(9) = 5; // -z face edges

FaceList.edges(10) = 5; FaceList.edges(11) = 5; // +z face edges


// create normals for each face/triangle(?)

//

// note: Haven't ever done this before but it's necessary if you want faceted objects.

// Otherwise normals represent the averaged normal of each face/triangle(?) using

// the associated vertex.

//


NormalVectorList = System.CreateDO('Space 3D Package/Vertex Normal Stream Data');

NormalVectorList.SetNumVertexNormals(6);


NormalVectorList.x(0) = 1.0 ; NormalVectorList.y(0) = 0.0; NormalVectorList.z(0) = 0.0; // +x normal

NormalVectorList.x(1) = 0.0 ; NormalVectorList.y(1) = -1.0; NormalVectorList.z(1) = 0.0; // -y normal

NormalVectorList.x(2) = -1.0 ; NormalVectorList.y(2) = 0.0; NormalVectorList.z(2) = 0.0; // -x normal

NormalVectorList.x(3) = 0.0 ; NormalVectorList.y(3) = 1.0; NormalVectorList.z(3) = 0.0; // +y normal

NormalVectorList.x(4) = 0.0 ; NormalVectorList.y(4) = 0.0; NormalVectorList.z(4) = -1.0; // -z normal

NormalVectorList.x(5) = 0.0 ; NormalVectorList.y(5) = 0.0; NormalVectorList.z(5) = 1.0; // +z normal


// create triangle vertex indices to the normal vectors defined above (0-5)

//

// Note: Each i,j,k term refers to the 1st, 2nd, and 3rd vertex of the assocaited triangle.

//


TriangleNormalsList = System.CreateDO('Space 3D Package/Triangle Normals Stream Data');

TriangleNormalsList.SetNumTripleIndices(12);


//************************************************** *********

// DON'T KNOW WHY THE FOLLOWING COMMENTED OUT CODE WON'T TAKE

//

// DOES IT HAVE ANYTHING TO DO WITH BEGINWRITE/ENDWRITE ON

// THE PRIMARY TRIANGLES STREAM?

//************************************************** *********


// TriangleNormalsList.i(0) = 0; TriangleNormalsList.j(0) = 0; TriangleNormalsList.k(0) = 0; // +x normals (x2 triangles)

// TriangleNormalsList.i(1) = 0; TriangleNormalsList.j(1) = 0; TriangleNormalsList.k(1) = 0;

// TriangleNormalsList.i(2) = 1; TriangleNormalsList.j(2) = 1; TriangleNormalsList.k(2) = 1; // -y normals (x2 triangles)

// TriangleNormalsList.i(3) = 1; TriangleNormalsList.j(3) = 1; TriangleNormalsList.k(3) = 1;

// TriangleNormalsList.i(4) = 2; TriangleNormalsList.j(4) = 2; TriangleNormalsList.k(4) = 2; // -x normals (x2 triangles)

// TriangleNormalsList.i(5) = 2; TriangleNormalsList.j(5) = 2; TriangleNormalsList.k(5) = 2;

// TriangleNormalsList.i(6) = 3; TriangleNormalsList.j(6) = 3; TriangleNormalsList.k(6) = 3; // +y normals (x2 triangles)

// TriangleNormalsList.i(7) = 3; TriangleNormalsList.j(7) = 3; TriangleNormalsList.k(7) = 3;

// TriangleNormalsList.i(8) = 4; TriangleNormalsList.j(8) = 4; TriangleNormalsList.k(8) = 4; // -z normals (x2 triangles)

// TriangleNormalsList.i(9) = 4; TriangleNormalsList.j(9) = 4; TriangleNormalsList.k(9) = 4;

// TriangleNormalsList.i(10) = 5; TriangleNormalsList.j(10) = 5; TriangleNormalsList.k(10) = 5; // +z normals (x2 triangles)

// TriangleNormalsList.i(11) = 5; TriangleNormalsList.j(11) = 5; TriangleNormalsList.k(11) = 5;


//********************************

// END OF NON-WORKING CODE SECTION

//********************************


// create output mesh from above defined items (vertices, triangles, materials, etc.)


outMesh = System.CreateDO('Space 3D Package/Mesh Data');


outMesh.AttachVerticesStream(VertexList);

outMesh.AttachTrianglesStream(TriangleList);

outMesh.AttachTrianglesStream(MaterialList);

outMesh.AttachTrianglesStream(FaceList);

outMesh.AttachCustStream(NormalVectorList); // note this is a custom stream, not a true vertex stream

// outMesh.AttachTrianglesStream(TriangleNormalsList) ; // line commented out because we were unable to define a proper stream.


// send data to output connector


params.conValue("outMesh") = outMesh;

}



Haven't got the foggiest clue why lines commented out above in the TriangleNormalsList section wouldn't work when uncommented. Gives me the following message when I try:




ERROR EVENT

--------------------------------------------------------------------------

Source object: /Project/Mesh Cube 003/My Mesh Cube/Unit Cube Mesh Maker

Error: Unspecified script error

Line: 155, Char: 1

Script text: TriangleNormalsList.i(0) = 0; TriangleNormalsList.j(0) = 0; TrinagleNormalsList.k(0) = 0; // +x normals (x2 triangles)


[ ok ] <--- button



Any suggestions anyone? The .rcd version is included below. Might be easier to troubleshoot that way.

Post by tomasb // Mar 13, 2007, 11:17pm

tomasb
Total Posts: 261
beginwrite/endwrite is not required; it was an optimization when we used old version of stream management; the change was made in 7.11 so before 7.11 it is needed.... and for compatibility of older scripts it was kept there.


to normals triangle stream problem: i've checked source code and it returns only E_INVALIDARG in 2 cases; so don't know what the problem may be. need to check it further but currently have no time left for it... at the end of the week i'll check it.

Post by ProfessorKhaos // Mar 14, 2007, 4:51am

ProfessorKhaos
Total Posts: 622
pic
Thanks Tomas. Good info to know. :banana: Already know how busy you guys are right now with the 7.5 Beta so no problems here with waiting a bit. ;)


As an experiment, I tried adding the following line before the trouble lines to see what the original contents were (null perhaps or just zeros?):



testvar = TriangleNormalsList.i(0);



This gave me a similar error. Also tried the following, thinking it was an issue indexing with a constant...



testindex = 0;

testvar = TriangleNormalsList.i(testindex);



Same error message, again against line with TriangleNormalsList.i(testindex) in it.


Haven't tried to redo this example in VBScript yet (alas, I'm more comfortable with jscript). Wouldn't imagine it'd change things but maybe I'll try a quick test to be sure.

Post by Emma // Mar 14, 2007, 11:44am

Emma
Total Posts: 344
pic
Attached is the VBScript version, get errro on the same point


Translate from German, yours may be different as I know translations from Windows differ quite a lot sometimes. But perhaps this could be an advantage here:


- Runtime Error in Microsoft VBScript

- object necessary: 'TriangleNormalsList.i'

- Error code: 0x800a01a8 - (null)


Error code is similar an invalid pointer to something


As TriangleNormalsList has been set a few lines above, also assigning of SetNumTripleIndices works and the error appears when assigning .i

I'm questioning myself could this be perhaps a bug ?


***

Another strange idea, there is a difference between object and command scripts when using code. Checked that also and put the code into VBScript command. Difference is as expeceted, error doesn't already appear when click on Check code icon, it comes up when click on Start


***

Comenting out all Normals settings but leaving outMesh.AttachTrianglesStream(TriangleNormalsList) gives an error message saying that it is the wrong type

Sounds like TrianglesStream <--> TriangleNormalsList don't fit together

Could it be necessary to first finish already some of the outMesh stuff before starting the Normals settings ?

Post by ProfessorKhaos // Mar 14, 2007, 3:23pm

ProfessorKhaos
Total Posts: 622
pic
Thanks for the VBScript translation Emma! Saves me a good amount of time :)



I'm questioning myself could this be perhaps a bug ?



I find myself asking the same thing. Seems like it should be relatively benign to create a Triangle Normals Data Stream object, set the size of the object and assign values to the i, j, and k components (all integer, all positive).


The error occurs before the Triangle Normal Data Stream is tied to the mesh and essentially is still a stand alone object in and of itself.


It's possible I may be doing something wrong though. My code represents a best guess at the way that normals should get defined but I would have thought that the line with the error would have executed fine even if my overall approach was off.


Anyway, it should still be possible to look into UV assignments next so that's what I'll work on while waiting for an answer with respect to assignment of normals.


Glen

Post by ProfessorKhaos // Mar 15, 2007, 8:59pm

ProfessorKhaos
Total Posts: 622
pic
Hi all,


Reworked the code with better comments and a more logical order for vertex, triangle, normals, and face assignment. Removed unnecessary BeginWrite() and EndWrite() statements. See below for new format (unwrapped box).




layout:


vertices triangles UV points


0-----3 +-----+ 10-----11

| +Z | | 8/9 | | / |

| | |/ | |/ |

0-----1-----2-----3-----0 +-----+-----+-----+-----+ 0-----1-----2-----3-----4

| +Y | +X | -Y | -X | | 0/1 | 2/3 | 4/5 | 6/7 | | / | / | / | / |

| | | | | |/ |/ |/ |/ | |/ |/ |/ |/ |

4-----5-----6-----7-----4 +-----+-----+-----+-----+ 5-----6-----7-----8-----9

| -Z | |10/11| | / |

| | |/ | |/ |

4-----7 +-----+ 12-----13



Normals are still non-functional in this version and are partially commented out. You can see the effect of not having normals defined in the odd face shading that would be more appropriate for a rounded object.


Added UV mapping. Top and botton of cube are wrapped from the +X side. Appears functional. On a side note, there appears to be 2 families of UV mapping streams. I just used the 1st one for both UV coords and triangle UV indices. Not sure if the 2nd is considered better or not, or if the format's even the same. May have to check it out.


Not including the code this time as it's too long to be posted in a code block. You'll have to download the .rcd object and import it to see current version. BTW, I'm doing this as .rcd files so that folks may preview the object itself in truePlay should they wish to do so. Right click on the download link and use the 'save target as' feature for later opening in trueSpace (via the record toolbar).


Enjoy!


Glen

Post by Emma // Mar 16, 2007, 5:19am

Emma
Total Posts: 344
pic
Just put the settings for outMesh before you call CreateDO(".....Normals Stream Data")


- then I deletet in that settings block the // in the Normals line


no complains, even if no Normals have been set the program doesn't mind


- now inserted

..........

----------outMesh settings including Normals

.........

aaa = outMesh.GetNormals();

System.Alert(aaa);

TriangleNormalsList = System.CreateDO('Space 3D Package/Triangle Normals Stream Data');

.........



now complaints for aaa = ... so some kind of data or stream data must have been returned, but the System.Alert gives a "wrong type" error.

Usually if aaa was set to empty then there simply should be no output. System Alert can handle numbers, strings, arrays and results in empty output for most non conversionable stuff from what I experienced so far.


.......

outMesh.AttachCustStream(UVCoordsList);

outMesh.AttachTrianglesStream(TriangleUVList);


aaa = outMesh.GetNormals();


TriangleNormalsList = System.CreateDO('Space 3D Package/Triangle Normals Stream Data');

TriangleNormalsList.SetNumTripleIndices(12);

.......


- This order we should have the Normals stream in aaa, no complaints but is it really there ?

- if it is there it must be empty, I would guess, but how to fill that empty stream with data then ?

-

Post by tomasb // Mar 16, 2007, 9:41am

tomasb
Total Posts: 261
I checked it and I have 2 news for you....


It is a bug... so you cannot access normals streams from script.


I have fixed it so code works as expected in 7.5.


Here is how it looks with normals...

Post by ProfessorKhaos // Mar 16, 2007, 1:22pm

ProfessorKhaos
Total Posts: 622
pic
This is actually good news then! :)


Not only will bug be squashed but it means I'm likely on the right path for my cube mesh generator after all.


Thank you Tomas!

Post by Jack Edwards // Apr 4, 2007, 8:05pm

Jack Edwards
Total Posts: 4062
pic
Very cool thread! I've been wondering if there was a way to access the UV's of existing objects to do automated mapping or UV patch sorting/scaling.


An example might be:


A script that recursively auto planar maps groupings of similarly angled contiguous faces.


And a second script that arranges and scales those patches to have unique space within the 0.0-1.0 UV space but still maintaining uniform pixel distribution.


It looks like this thread is pretty close to unraveling the details of how the data is stored...


BTW, just in case you guys were wondering about the reason that the edges are given values of 1, 2, and 4. My guess would be that its so that they can be combined into one value with the binary or operation.


For example:


#define EDGE1_ON 1

#define EDGE2_ON 2

#define EDGE3_ON 4


FaceList.edges(0) = EDGE1_ON | EDGE3_ON;


It makes the code more readable and implements faster because less parameters are passed to the stack during the function call for that object's assignment operator.


Not sure how you'd make use of that in script though since I'm not sure the | operator is supported....


-Jack.
Awportals.com is a privately held community resource website dedicated to Active Worlds.
Copyright (c) Mark Randall 2006 - 2024. All Rights Reserved.
Awportals.com   ·   ProLibraries Live   ·   Twitter   ·   LinkedIn