Author Topic: Creating a mesh during run time using a Vertex/Face Buffer  (Read 4095 times)

Exavior

  • 3Impact Veteran
  • *****
  • Posts: 1674
  • Who is General Failure and why is he reading my HD
    • Exavior Productions
Creating a mesh during run time using a Vertex/Face Buffer
« on: January 16, 2007, 08:09:39 AM »
This function will take a Vetex and Face buffer and use them to create a string that contains the same data that a .x file that used those buffer's data would have, it then loads the mesh using the iMeshFromMemoryCreate() function. Using this function you should be able to create meshes at runtime and have them be able to be used with the picking and other functions that use the orginal mesh data instead of the current mesh data.

Code: [Select]
MESH* CreateMeshFromBuffers(MESHVERTEX* Verts, int NumVerts, MESHFACE* Faces, int NumFaces)
{
// Puts the .x header in the begining of the string
std::string x_file = "xof 0303txt 0032\ntemplate VertexDuplicationIndices {\n <b8d65549-d7c9-4995-89cf-53a9a8b031e3>\n DWORD nIndices;\n DWORD nOriginalVertices;\n array DWORD indices[nIndices];\n}\n\ntemplate FVFData {\n <b6e70a0e-8ef9-4e83-94ad-ecc8b0c04897>\n DWORD dwFVF;\n DWORD nDWords;\n array DWORD data[nDWords];\n}\n\n\nMesh {\n";
// creates a temp char string for use in creating the main string
char tmp[1000];
// write the number of vertex to the file string
sprintf(tmp, "%d;\n",NumVerts);
x_file.append(tmp);
// loops through all vertex and write their positions to the list
for(int i = 0; i < NumVerts; i++)
{
sprintf(tmp, "%f;%f;%f;",Verts[i].p.x, Verts[i].p.y, Verts[i].p.z);
x_file.append(tmp);
(i < (NumVerts - 1))?x_file.append(",\n"):x_file.append(";\n");
}
//write the number of faces to the string
sprintf(tmp, "%d;\n",NumFaces);
x_file.append(tmp);
// loop through all the faces and write all the vertex that make up each face
for(int i = 0; i < NumFaces; i++)
{
sprintf(tmp, "3;%d,%d,%d;", Faces[i].v0, Faces[i].v1, Faces[i].v2);
x_file.append(tmp);
(i < (NumFaces - 1))?x_file.append(",\n"):x_file.append(";\n\n MeshNormals {\n");
}
// write the number of vertex again this time for normals
sprintf(tmp, "%d;\n",NumVerts);
x_file.append(tmp);
// loop through each vertex and write the normal vertor info for each one
for(int i = 0; i < NumVerts; i++)
{
sprintf(tmp, "%f;%f;%f;",Verts[i].n.x, Verts[i].n.y, Verts[i].n.z);
x_file.append(tmp);
(i < (NumVerts - 1))?x_file.append(",\n"):x_file.append(";\n");
}
// write the number of faces again this time again for normal vector data.
sprintf(tmp, "%d;\n",NumFaces);
x_file.append(tmp);
for(int i = 0; i < NumFaces; i++)
{
sprintf(tmp, "3;%d,%d,%d;", Faces[i].v0, Faces[i].v1, Faces[i].v2);
x_file.append(tmp);
(i < (NumFaces - 1))?x_file.append(",\n"):x_file.append(";\n}\n\nMeshTextureCoords {\n");
}
// write the number of vertex once again this time for texture coordinate info
sprintf(tmp, "%d;\n",NumVerts);
x_file.append(tmp);
// Loop through each vertex and write their texture coordinates
for(int i = 0; i < NumVerts; i++)
{
sprintf(tmp, "%f;%f;",Verts[i].u, Verts[i].v);
x_file.append(tmp);
(i < (NumVerts - 1))?x_file.append(",\n"):x_file.append(";\n }\n MeshMaterialList {\n  1;\n  1;\n  0;\n\n  Material {\n   1.000000;1.000000;1.000000;1.000000;;\n   128.000000;\n   0.000000;0.000000;0.000000;;\n   0.000000;0.000000;0.000000;;\n\n   TextureFilename {\n    \"Unassigned\";\n   }\n  }\n }\n}");
}
// using the string just created create a mesh from memory and return it
return iMeshCreateFromMemory((char*)x_file.c_str(), x_file.length() * 32, NULL,NULL,NULL);
}


This code loads the mesh without a texture so you will need to use one of the various methods to add a texture to the model after it is loaded.

Here is an example Vertex & Face buffer and a call to see how it would work.

Code: [Select]
   MESHVERTEX Verts[20];
   MESHFACE Faces[12];
   Verts[0].p.x = 0.5;
   Verts[0].p.y = -0.5;
   Verts[0].p.z = 0.5;
   Verts[0].n.x = 0.577350;
   Verts[0].n.y = -0.577350;
   Verts[0].n.z = 0.577350;
   Verts[0].u = 0;
   Verts[0].v = 0;
   Verts[1].p.x = 0.5;
   Verts[1].p.y = 0.5;
   Verts[1].p.z = 0.5;
   Verts[1].n.x = 0.577350;
   Verts[1].n.y = 0.577350;
   Verts[1].n.z = 0.577350;
   Verts[1].u = 0;
   Verts[1].v = 1;
   Verts[2].p.x = -0.5;
   Verts[2].p.y = -0.5;
   Verts[2].p.z = 0.5;
   Verts[2].n.x = -0.577350;
   Verts[2].n.y = -0.577350;
   Verts[2].n.z = 0.577350;
   Verts[2].u = 1;
   Verts[2].v = 0;
   Verts[3].p.x = -0.5;
   Verts[3].p.y = 0.5;
   Verts[3].p.z = 0.5;
   Verts[3].n.x = -0.577350;
   Verts[3].n.y = 0.577350;
   Verts[3].n.z = 0.577350;
   Verts[3].u = 1;
   Verts[3].v = 1;
   Verts[4].p.x = 0.5;
   Verts[4].p.y = -0.5;
   Verts[4].p.z = -0.5;
   Verts[4].n.x = 0.577350;
   Verts[4].n.y = -0.577350;
   Verts[4].n.z = -0.577350;
   Verts[4].u = 1;
   Verts[4].v = 1;
   Verts[5].p.x = -0.5;
   Verts[5].p.y = -0.5;
   Verts[5].p.z = -0.5;
   Verts[5].n.x = -0.577350;
   Verts[5].n.y = -0.577350;
   Verts[5].n.z = -0.577350;
   Verts[5].u = 0;
   Verts[5].v = 1;
   Verts[6].p.x = -0.5;
   Verts[6].p.y = 0.5;
   Verts[6].p.z = -0.5;
   Verts[6].n.x = -0.577350;
   Verts[6].n.y = 0.577350;
   Verts[6].n.z = -0.577350;
   Verts[6].u = 1;
   Verts[6].v = 1;
   Verts[7].p.x = 0.5;
   Verts[7].p.y = 0.5;
   Verts[7].p.z = -0.5;
   Verts[7].n.x = 0.577350;
   Verts[7].n.y = 0.577350;
   Verts[7].n.z = -0.577350;
   Verts[7].u = 1;
   Verts[7].v = 0;
   Verts[8].p.x = -0.5;
   Verts[8].p.y = -0.5;
   Verts[8].p.z = 0.5;
   Verts[8].n.x = -0.577350;
   Verts[8].n.y = -0.577350;
   Verts[8].n.z = 0.577350;
   Verts[8].u = 0;
   Verts[8].v = 0;
   Verts[9].p.x = 0.5;
   Verts[9].p.y = -0.5;
   Verts[9].p.z = 0.5;
   Verts[9].n.x = 0.577350;
   Verts[9].n.y = -0.577350;
   Verts[9].n.z = 0.577350;
   Verts[9].u = 1;
   Verts[9].v = 0;
   Verts[10].p.x = -0.5;
   Verts[10].p.y = 0.5;
   Verts[10].p.z = 0.5;
   Verts[10].n.x = -0.577350;
   Verts[10].n.y = 0.577350;
   Verts[10].n.z = 0.577350;
   Verts[10].u = 0;
   Verts[10].v = 1;
   Verts[11].p.x = -0.5;
   Verts[11].p.y = -0.5;
   Verts[11].p.z = -0.5;
   Verts[11].n.x = -0.577350;
   Verts[11].n.y = -0.577350;
   Verts[11].n.z = -0.577350;
   Verts[11].u = 1;
   Verts[11].v = 0;
   Verts[12].p.x = 0.5;
   Verts[12].p.y = 0.5;
   Verts[12].p.z = 0.5;
   Verts[12].n.x = 0.577350;
   Verts[12].n.y = 0.577350;
   Verts[12].n.z = 0.577350;
   Verts[12].u = 1;
   Verts[12].v = 1;
   Verts[13].p.x = -0.5;
   Verts[13].p.y = 0.5;
   Verts[13].p.z = -0.5;
   Verts[13].n.x = -0.577350;
   Verts[13].n.y = 0.577350;
   Verts[13].n.z = -0.577350;
   Verts[13].u = 0;
   Verts[13].v = 0;
   Verts[14].p.x = 0.5;
   Verts[14].p.y = -0.5;
   Verts[14].p.z = -0.5;
   Verts[14].n.x = 0.577350;
   Verts[14].n.y = -0.577350;
   Verts[14].n.z = -0.577350;
   Verts[14].u = 1;
   Verts[14].v = 0;
   Verts[15].p.x = -0.5;
   Verts[15].p.y = -0.5;
   Verts[15].p.z = -0.5;
   Verts[15].n.x = -0.577350;
   Verts[15].n.y = -0.577350;
   Verts[15].n.z = -0.577350;
   Verts[15].u = 0;
   Verts[15].v = 0;
   Verts[16].p.x = -0.5;
   Verts[16].p.y = 0.5;
   Verts[16].p.z = -0.5;
   Verts[16].n.x = -0.577350;
   Verts[16].n.y = 0.577350;
   Verts[16].n.z = -0.577350;
   Verts[16].u = 0;
   Verts[16].v = 1;
   Verts[17].p.x = 0.5;
   Verts[17].p.y = 0.5;
   Verts[17].p.z = -0.5;
   Verts[17].n.x = 0.577350;
   Verts[17].n.y = 0.577350;
   Verts[17].n.z = -0.577350;
   Verts[17].u = 1;
   Verts[17].v = 1;
   Verts[18].p.x = 0.5;
   Verts[18].p.y = -0.5;
   Verts[18].p.z = -0.5;
   Verts[18].n.x = 0.577350;
   Verts[18].n.y = -0.577350;
   Verts[18].n.z = -0.577350;
   Verts[18].u = 0;
   Verts[18].v = 0;
   Verts[19].p.x = 0.5;
   Verts[19].p.y = 0.5;
   Verts[19].p.z = -0.5;
   Verts[19].n.x = 0.577350;
   Verts[19].n.y = 0.577350;
   Verts[19].n.z = -0.577350;
   Verts[19].u = 0;
   Verts[19].v = 1;

    Faces[0].v0 = 1;
   Faces[0].v1 = 3;
   Faces[0].v2 = 2;
   Faces[1].v0 = 0;
   Faces[1].v1 = 1;
   Faces[1].v2 = 2;
   Faces[2].v0 = 8;
   Faces[2].v1 = 5;
   Faces[2].v2 = 4;
   Faces[3].v0 = 9;
   Faces[3].v1 = 8;
   Faces[3].v2 = 4;
   Faces[4].v0 = 8;
   Faces[4].v1 = 10;
   Faces[4].v2 = 6;
   Faces[5].v0 = 11;
   Faces[5].v1 = 8;
   Faces[5].v2 = 6;
   Faces[6].v0 = 12;
   Faces[6].v1 = 7;
   Faces[6].v2 = 13;
   Faces[7].v0 = 10;
   Faces[7].v1 = 12;
   Faces[7].v2 = 13;
   Faces[8].v0 = 14;
   Faces[8].v1 = 15;
   Faces[8].v2 = 16;
   Faces[9].v0 = 17;
   Faces[9].v1 = 14;
   Faces[9].v2 = 16;
   Faces[10].v0 = 18;
   Faces[10].v1 = 19;
   Faces[10].v2 = 12;
   Faces[11].v0 = 9;
   Faces[11].v1 = 18;
   Faces[11].v2 = 12;

   object = CreateMeshFromBuffers(Verts, 20, Faces, 11);


Later to come will be various functions to create cubes, cylinders and other primative objects with will take advantage of this function.
Exavior Productions forum w/ QMS worklog      

Athlon 64 X2 4200+, 2GB, Geforce FX 6800 256  |  Athlon XP 2500+ , 1.5 GB, BFG Geforce Fx 5200 256MB Special Edition

Zumwalt

  • 3Impact Veteran
  • *****
  • Posts: 1162
    • JBWWS
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #1 on: January 16, 2007, 08:47:48 AM »
Can you take the data in a current X file and just copy/paste it into this function?

Exavior

  • 3Impact Veteran
  • *****
  • Posts: 1674
  • Who is General Failure and why is he reading my HD
    • Exavior Productions
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #2 on: January 16, 2007, 09:46:12 AM »
Yes, you can paste the contains of a .x file's data itself into the fromMemory function call and load them that way. That is pretty much what this code does, only it has to create the .x file's data first.
Exavior Productions forum w/ QMS worklog      

Athlon 64 X2 4200+, 2GB, Geforce FX 6800 256  |  Athlon XP 2500+ , 1.5 GB, BFG Geforce Fx 5200 256MB Special Edition

craig

  • 3Impact Veteran
  • *****
  • Posts: 678
  • Lets get this party started!
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #3 on: January 16, 2007, 11:33:30 AM »
Heres a pdf on how to make icospheres. (a.k.a. geospheres)

I was going to generate them on the fly and then apply the code from my Terrasphere demo and then finally create a texture for it useing a slightly "modified" fractal method. (the textures change acording to what mineral is in the asteroid and how much of it is there) this would be used to form the asteroids in my game. because the asteroid "mesh" was generated on the fly, the user could fine tune the actual polygons used in asteroids to meet thier computers specifacations. this would solve the problems games like X3 has.

the problem? my game design went from useing 10 or so asteroids to needing around 500-1000 of them... I think it would take to long even if the generation code was programmed in assembly. But I'm still thinking about implimenting it anyway, just because asteroids are such a key part of my game.

but anyway, this doc is the best I could find on explaining the generation of geospheres. (icospheres)
craig

"Work It Harder Make It Better Do It Faster, Makes Us stronger More Than Ever Hour After Hour Work Is Never Over"

-Daft Punk

George Birbilis

  • 3Impact Jr. Member
  • **
  • Posts: 84
    • George Birbilis website
    • Email
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #4 on: January 17, 2007, 03:19:39 AM »
if you generate them in memory, it shouldn't take very much time to make clones of it using 3impact's create from memory functions (3impact does caching when loading from disk, but still not as fast as loading from memory)
Microsoft MVP Visual Developer - J# (2004-2010)
Borland "Spirit of Delphi"
QuickTime, QTVR, ActiveX, .NET, Delphi VCL, XML, IPC
http://www.zoomicon.com
http://birbilis.spaces.live.com
http://twitter.com/zoomicon

George Birbilis

  • 3Impact Jr. Member
  • **
  • Posts: 84
    • George Birbilis website
    • Email
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #5 on: January 17, 2007, 03:34:00 AM »
Here's some code from an old 3D engine of mine for Pascal to make some geometric shapes:

Quote
{-$DEFINE DEBUG}

Unit OFill3D; {Filled-Plane Objects in 3D space}

interface
 Uses View3D,ColorFn;

 type XYtoZ=function(x,y:Tcoord3D):Tcoord3D;

 {misc}
 procedure PointedAxis(miti,x1,y1,z1,x2,y2,z2:integer);
 {Simple 2D objects}
 procedure PointPlane(x1,y1,z1:Tcoord3D);
 procedure LinePlane(x1,y1,z1, x2,y2,z2:Tcoord3D);
 procedure TrianglePlane(x1,y1,z1, x2,y2,z2, x3,y3,z3:Tcoord3D);
 procedure RectanglePlane(x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4:Tcoord3D);
 {Simple 3D objects}
 procedure Rectangle(x1,y1,z1, x2,y2,z2:Tcoord3D);
 procedure sphere(cx,cy,cz:Tcoord3D; Radius:word);
 procedure cylinder(cx,cy,cz:Tcoord3D; Height:integer; BaseRadius,TopRadius:word);
     const CylinderTopOn:boolean=TRUE;  {set if the cylinder is closed on top}
           CylinderBaseOn:boolean=TRUE; {set if the cylinder is closed at base}
 {complex 3D objects}
 procedure multiCylinder(cx,cy,cz:Tcoord3D; Height:array of integer; Radius:array of word);
 procedure Grid(x1,y1, x2,y2, z:Tcoord3D; PointsX,PointsY:word; HeightFunc:XYtoZ; ColorFunc:ColorFunction);
 {Fill Colors}
 procedure Fill3DColors(d,f:word);
     const DrawingColor:word=1;
           FillingColor:word=2;

implementation
Uses Floating,Coords3D,Fill3D{$IFDEF DEBUG},CRT,View_F3D{$ENDIF};

{misc}

procedure PointedAxis;
begin
 linePlane(x1,0,0,x2,0,0);
 linePlane(0,y1,0,0,y2,0);
 linePlane(0,0,z1,0,0,z2);
 {assumes x2>x1,y2>y1,z2>z1}
 rectangle(x2-miti,-miti,-miti,x2,miti,miti);
 rectangle(-miti,y2-miti,-miti,miti,y2,miti);
 rectangle(-miti,-miti,z2-miti,miti,miti,z2);
end;

(*** 2D objects *************************************************************)

procedure PointPlane;
var p:PPlane3Dpoints;
begin
GetMem(p,sizeOf(pointXYZtype));
if (p=nil) then exit;
p^[1].x:=x1; p^[1].y:=y1; p^[1].z:=z1;
NewPolyPlane(1,p^,DrawingColor,FillingColor);
end;

procedure LinePlane;
var p:PPlane3Dpoints;
begin
GetMem(p,2*sizeOf(pointXYZtype));
if (p=nil) then exit;
p^[1].x:=x1; p^[1].y:=y1; p^[1].z:=z1;
p^[2].x:=x2; p^[2].y:=y2; p^[2].z:=z2;
NewPolyPlane(2,p^,DrawingColor,FillingColor);
end;

procedure TrianglePlane;
var p:PPlane3Dpoints;
begin
GetMem(p,3*sizeOf(pointXYZtype));
if (p=nil) then exit;
p^[1].x:=x1; p^[1].y:=y1; p^[1].z:=z1;
p^[2].x:=x2; p^[2].y:=y2; p^[2].z:=z2;
p^[3].x:=x3; p^[3].y:=y3; p^[3].z:=z3;
NewPolyPlane(3,p^,DrawingColor,FillingColor);
end;

procedure RectanglePlane;
var p:PPlane3Dpoints;
begin
GetMem(p,4*sizeOf(pointXYZtype));
if (p=nil) then exit;
p^[1].x:=x1; p^[1].y:=y1; p^[1].z:=z1;
p^[2].x:=x2; p^[2].y:=y2; p^[2].z:=z2;
p^[3].x:=x3; p^[3].y:=y3; p^[3].z:=z3;
p^[4].x:=x4; p^[4].y:=y4; p^[4].z:=z4;
NewPolyPlane(4,p^,DrawingColor,FillingColor);
end;

(*** 3D objects *************************************************************)

procedure Rectangle;
begin
RectanglePlane(x1,y1,z1, x2,y1,z1, x2,y2,z1, x1,y2,z1); {top}
RectanglePlane(x1,y1,z1, x2,y1,z1, x2,y1,z2, x1,y1,z2); {left}
RectanglePlane(x1,y1,z1, x1,y2,z1, x1,y2,z2, x1,y1,z2); {front}
RectanglePlane(x2,y2,z2, x2,y2,z1, x1,y2,z1, x1,y2,z2); {right}
RectanglePlane(x2,y2,z2, x2,y1,z2, x2,y1,z1, x2,y2,z1); {rear}
RectanglePlane(x2,y2,z2, x1,y2,z2, x1,y1,z2, x2,y1,z2); {bottom}
end;

(**)

procedure cylinder;

function max2(a,b:word):word;
begin
if a<b then max2:=b else max2:=a;
end;

procedure XYZpoint2pointXYZ(p:XYZpoint;var XYZ:pointXYZtype);
begin
with XYZ do
 begin
 x:=round(p.x)+cx;
 y:=round(p.y)+cy;
 z:=round(p.z)+cz;
 end;
end;

var XYZ1,lastXYZ1,
    XYZ2,lastXYZ2:XYZpoint;
    Cyl1,Cyl2:CylindricPoint;
    ang:float;
    R:word;
    j:longint;
    Base,Top:PPlane3DPoints;

begin
 if sides=0 then exit;
 R:=max2(BaseRadius,TopRadius); {in case one of them is too small (e.g. 1)}
 if R=0 then exit;
 ang:=2*pi/sides;
 with Cyl1 do
  begin
  z:=0;
  R:=BaseRadius;
  theta:=0;
  end;
 with Cyl2 do
  begin
  z:=height;
  R:=TopRadius;
  theta:=0;
  end;

 cylindric2XYZ(Cyl1,XYZ1);
 cylindric2XYZ(Cyl2,XYZ2);

if CylinderBaseOn then if BaseRadius<>0 then GetMem(Base,(sides+1)*sizeOf(pointXYZtype));
if CylinderTopOn then if TopRadius<>0 then GetMem(Top,(sides+1)*sizeOf(pointXYZtype));

  for j:=0 to sides-1 do {no need to close}
   begin
   lastXYZ1:=XYZ1;
   lastXYZ2:=XYZ2;

if CylinderBaseOn then if BaseRadius<>0 then XYZpoint2pointXYZ(lastXYZ1,Base^[j+1]);
if CylinderTopOn then if TopRadius<>0 then XYZpoint2pointXYZ(lastXYZ2,Top^[j+1]);

   with Cyl1 do theta:=theta+ang;
   with Cyl2 do theta:=theta+ang;

   Cylindric2XYZ(Cyl1,XYZ1);
   Cylindric2XYZ(Cyl2,XYZ2);

   RectanglePlane(cx+round(lastXYZ1.x),cy+round(lastXYZ1.y),cz+round(lastXYZ1.z),
                  cx+round(XYZ1.x),cy+round(XYZ1.y),cz+round(XYZ1.z),
                  cx+round(XYZ2.x),cy+round(XYZ2.y),cz+round(XYZ2.z),
                  cx+round(lastXYZ2.x),cy+round(lastXYZ2.y),cz+round(lastXYZ2.z));
   end;

if CylinderBaseOn then if BaseRadius<>0 then NewPolyPlane(sides,Base^,DrawingColor,FillingColor);
if CylinderTopOn then if TopRadius<>0 then NewPolyPlane(sides,Top^,DrawingColor,FillingColor);
end;

procedure sphere;

procedure XYZpoint2pointXYZ(p:XYZpoint;var XYZ:pointXYZtype);
begin
with XYZ do
 begin
 x:=round(p.x)+cx;
 y:=round(p.y)+cy;
 z:=round(p.z)+cz;
 end;
end;

type TPlane3DPoints3=array[1..3] of pointXYZtype;
     TPlane3DPoints4=array[1..4] of pointXYZtype;
var XYZ:XYZpoint;
    Spherical:SphericalPoint;
    i,j:longint;
    ang:float;
    lastVert:pointXYZtype;
    Buf:PPlane3DPoints;
    Square:^TPlane3DPoints4;
    Triangle:^TPlane3DPoints3;
begin
 if sides=0 then exit;
 ang:=2*pi/sides;
 GetMem(Buf,(sides+1)*SizeOf(PointXYZtype)); {Create buffer}

with Spherical do {VERTICALS}
 begin
 R:=Radius;
 theta:=0;
 for j:=0 to sides do {now sphere has "sides" sides in both directions}
  begin
  fi:=0; theta:=theta+ang; Spherical2XYZ(Spherical,XYZ);
  for i:=1 to sides+1 do
   begin
   (* Initialize *)
   lastVert:=Buf^; XYZpoint2pointXYZ(XYZ,Buf^);
   fi:=fi+ang/2; Spherical2XYZ(Spherical,XYZ);
   if (j=0) or (i=sides+1) then continue; {exit loop - only did initializing}
   (* Create 3 or 4 point plane *)
   if (i=1) or (i=sides) then
    begin                      {3 point Plane}
    New(Triangle);
    Triangle^[1]:=lastVert;
    Triangle^[2]:=Buf^[i+1];
    if (i=1)
     then XYZpoint2pointXYZ(XYZ,Triangle^[3]) {i=1}
     else Triangle^[3]:=Buf^;              {i=sides}
    NewPolyPlane(3,Triangle^,DrawingColor,FillingColor);
    {$IFDEF DEBUG}write(#7);{$ENDIF}
    end
   else
    begin {4 point Plane}
    New(Square); {allocate memory}
    Square^[1]:=lastVert;
    Square^[2]:=Buf^[i+1];
    XYZpoint2pointXYZ(XYZ,Square^[3]); {keep Vert^[i+2] as is for next loop}
    Square^[4]:=Buf^;
    NewPolyPlane(4,Square^,DrawingColor,FillingColor);
    end;
   {$IFDEF DEBUG}
   ViewFilled3D;
   {$ENDIF}
   end;
  end;
 end;
 FreeMem(Buf,(sides+1)*SizeOf(PointXYZtype)); {Free buffer}
end;

(*** Complex 3D Objects ***)

procedure multiCylinder;
var i,h:integer;
begin
h:=0;
for i:=Low(Height) to High(Height) do
 begin
 Cylinder(cx,cy,cz+h, Height, Radius, Radius[i+1]);
 inc(h,Height);
 end;
end;

procedure Grid;

 procedure swap(var a,b:Tcoord3D);
 var c:Tcoord3D;
 begin
 c:=a;
 a:=b;
 b:=c;
 end;

var x,stepX,stepY:Tcoord3D;
    _x,_y:word;
begin
if x1>x2 then swap(x1,x2);
if y1>y2 then swap(y1,y2);
stepX:=(x2-x1)/PointsX;
stepY:=(y2-y1)/PointsY;
_y:=0;
while (y1<y2) do
 begin
 x:=x1;
 _x:=0;
 while (x<x2) do
  begin
  if (@ColorFunc<>nil) then FillingColor:=ColorFunc(_x,_y);
  RectanglePlane( x  ,     y1      , z+HeightFunc(x,y1),
                  x+StepX, y1      , z+HeightFunc(x+StepX,y1),
                  x+StepX, y1+StepY, z+HeightFunc(x+StepX,y1+StepY),
                  x,       y1+StepY, z+HeightFunc(x,y1+StepY)        );
  x:=x+StepX;
  inc(_x);
  end;
 y1:=y1+StepY;
 inc(_y);
 end;
end;

(****************************************************************************)

procedure Fill3Dcolors;
begin
DrawingColor:=d;
FillingColor:=f;
end;

end.

Microsoft MVP Visual Developer - J# (2004-2010)
Borland "Spirit of Delphi"
QuickTime, QTVR, ActiveX, .NET, Delphi VCL, XML, IPC
http://www.zoomicon.com
http://birbilis.spaces.live.com
http://twitter.com/zoomicon

George Birbilis

  • 3Impact Jr. Member
  • **
  • Posts: 84
    • George Birbilis website
    • Email
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #6 on: January 17, 2007, 03:35:20 AM »
and here's the Coords3D unit that does the coordinate transformations (cylindrical to XYZ etc.). The idea is that we use the coordinate system that suits us most to keep the algorithms easy to read and transform to XYZ to make the mesh buffers

Quote
unit Coords3D;

interface
uses FLOATING;

type XYZPoint=record
      X,Y,Z:float;
      end;

     SphericalPoint=record
      R,fi,theta:float;
      end;

     CylindricPoint=record
      R,Z,theta:float;
      end;

procedure XYZ2Spherical(var XYZ:XYZpoint;var Spherical:SphericalPoint);
procedure Spherical2XYZ(var Spherical:SphericalPoint;var XYZ:XYZPoint);
procedure Cylindric2XYZ(var Cylindric:CylindricPoint;var XYZ:XYZPoint);
procedure Spherical2Cylindric(var Spherical:SphericalPoint;var Cylindric:CylindricPoint);

implementation

procedure XYZ2Spherical;
begin
 with XYZ,Spherical do
  begin
  R:=sqrt(sqr(x)+sqr(y)+sqr(z));
  {...}
  end;
end;

procedure Spherical2XYZ;
begin
 with XYZ,Spherical do
  begin
  x:=R*sin(fi)*cos(theta);
  y:=R*sin(fi)*sin(theta);
  z:=R*cos(fi);
  end;
end;

procedure Cylindric2XYZ;
begin
 with XYZ,Cylindric do
  begin
  x:=R*cos(theta);
  y:=R*sin(theta);
  XYZ.z:=z;       {check this -> maybe use Cylindric.z}
  end;
end;

procedure Spherical2Cylindric;
begin
 with Cylindric,Spherical do
  begin
  Cylindric.R:=R*sin(fi);       {check again}
  z:=R*cos(fi);                 {and here for R}
  Cylindric.theta:=theta;
  end;                   {check if ; adds a nop}
end;

end.

Microsoft MVP Visual Developer - J# (2004-2010)
Borland "Spirit of Delphi"
QuickTime, QTVR, ActiveX, .NET, Delphi VCL, XML, IPC
http://www.zoomicon.com
http://birbilis.spaces.live.com
http://twitter.com/zoomicon

Micha

  • 3Impact Veteran
  • *****
  • Posts: 2344
  • Network Powered! ;)
    • 3impact dump dir
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #7 on: January 18, 2007, 10:13:58 AM »
Create a icosahedron (low-poly sphere) directly into the buffers (just like craig mentioned)

Code: [Select]
        //vertexBuffer size is 60
        //faceBuffer size is 20
        float a,b,phi;
        phi=(1+sqrtf(5))/2;
        a = 0.5f; b = 1 / (2 * phi);

        vertexBuffer[0].p=D3DXVECTOR3(0, b, -a);  vertexBuffer[1].p=D3DXVECTOR3(b, a, 0);   vertexBuffer[2].p=D3DXVECTOR3(-b, a, 0);
        vertexBuffer[3].p=D3DXVECTOR3(0, b, a);   vertexBuffer[4].p=D3DXVECTOR3(-b, a, 0);  vertexBuffer[5].p=D3DXVECTOR3(b, a, 0);
        vertexBuffer[6].p=D3DXVECTOR3(0, b, a);   vertexBuffer[7].p=D3DXVECTOR3(0, -b, a);  vertexBuffer[8].p=D3DXVECTOR3(-a, 0, b);
        vertexBuffer[9].p=D3DXVECTOR3(0, b, a);   vertexBuffer[10].p=D3DXVECTOR3(a, 0, b);  vertexBuffer[11].p=D3DXVECTOR3(0, -b, a);
        vertexBuffer[12].p=D3DXVECTOR3(0, b, -a); vertexBuffer[13].p=D3DXVECTOR3(0,-b, -a); vertexBuffer[14].p=D3DXVECTOR3(a, 0, -b);
        vertexBuffer[15].p=D3DXVECTOR3(0, b, -a); vertexBuffer[16].p=D3DXVECTOR3(-a, 0,-b); vertexBuffer[17].p=D3DXVECTOR3(0, -b,-a);
        vertexBuffer[18].p=D3DXVECTOR3(0, -b, a); vertexBuffer[19].p=D3DXVECTOR3(b,-a, 0);  vertexBuffer[20].p=D3DXVECTOR3(-b,-a, 0);
        vertexBuffer[21].p=D3DXVECTOR3(0, -b,-a); vertexBuffer[22].p=D3DXVECTOR3(-b,-a, 0); vertexBuffer[23].p=D3DXVECTOR3(b,-a, 0);
        vertexBuffer[24].p=D3DXVECTOR3(-b, a, 0); vertexBuffer[25].p=D3DXVECTOR3(-a, 0, b); vertexBuffer[26].p=D3DXVECTOR3(-a, 0, -b);
        vertexBuffer[27].p=D3DXVECTOR3(-b,-a, 0); vertexBuffer[28].p=D3DXVECTOR3(-a, 0,-b); vertexBuffer[29].p=D3DXVECTOR3(-a, 0, b);
        vertexBuffer[30].p=D3DXVECTOR3(b, a, 0);  vertexBuffer[31].p=D3DXVECTOR3(a, 0,-b);  vertexBuffer[32].p=D3DXVECTOR3(a, 0, b);
        vertexBuffer[33].p=D3DXVECTOR3(b, -a,0);  vertexBuffer[34].p=D3DXVECTOR3(a, 0, b);  vertexBuffer[35].p=D3DXVECTOR3(a, 0,-b);
        vertexBuffer[36].p=D3DXVECTOR3(0, b, a);  vertexBuffer[37].p=D3DXVECTOR3(-a, 0, b); vertexBuffer[38].p=D3DXVECTOR3(-b, a, 0);
        vertexBuffer[39].p=D3DXVECTOR3(0, b, a);  vertexBuffer[40].p=D3DXVECTOR3(b, a, 0);  vertexBuffer[41].p=D3DXVECTOR3(a, 0, b);
        vertexBuffer[42].p=D3DXVECTOR3(0, b,-a);  vertexBuffer[43].p=D3DXVECTOR3(-b, a, 0); vertexBuffer[44].p=D3DXVECTOR3(-a, 0,-b);
        vertexBuffer[45].p=D3DXVECTOR3(0, b,-a);  vertexBuffer[46].p=D3DXVECTOR3(a, 0,-b);  vertexBuffer[47].p=D3DXVECTOR3(b, a, 0);
        vertexBuffer[48].p=D3DXVECTOR3(0, -b,-a); vertexBuffer[49].p=D3DXVECTOR3(-a, 0,-b); vertexBuffer[50].p=D3DXVECTOR3(-b,-a, 0);
        vertexBuffer[51].p=D3DXVECTOR3(0, -b,-a); vertexBuffer[52].p=D3DXVECTOR3(b,-a, 0);  vertexBuffer[53].p=D3DXVECTOR3(a, 0,-b);
        vertexBuffer[54].p=D3DXVECTOR3(0, -b, a); vertexBuffer[55].p=D3DXVECTOR3(-b,-a, 0); vertexBuffer[56].p=D3DXVECTOR3(-a, 0, b);
        vertexBuffer[57].p=D3DXVECTOR3(0, -b, a); vertexBuffer[58].p=D3DXVECTOR3(a, 0, b);  vertexBuffer[59].p=D3DXVECTOR3(b,-a, 0);

        int  n=0;
        for(int k=0; k<totalPolygons; k++) {
            faceBuffer[k].v0=n;
            faceBuffer[k].v1=n+2;
            faceBuffer[k].v2=n+1;

            n=n+3;
        }

Micha

  • 3Impact Veteran
  • *****
  • Posts: 2344
  • Network Powered! ;)
    • 3impact dump dir
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #8 on: January 18, 2007, 10:21:31 AM »
For a high polygon version, you need to tesselate the icosahedron

Code: [Select]
        int ntotalVertices = totalVertices;
        int ntotalPolygons = totalPolygons;

        //at this point you need to open and resize the buffers
        //totalVertices becomes ntotalVertices+ntotalPolygons*3
        //totalPolygons becomes ntotalPolygons*4

        for(int v=ntotalVertices,k=0; k<ntotalPolygons; k++) {
            vertexBuffer[v+0].p=(vertexBuffer[faceBuffer[k].v0].p+vertexBuffer[faceBuffer[k].v1].p)/2;
            vertexBuffer[v+1].p=(vertexBuffer[faceBuffer[k].v1].p+vertexBuffer[faceBuffer[k].v2].p)/2;
            vertexBuffer[v+2].p=(vertexBuffer[faceBuffer[k].v2].p+vertexBuffer[faceBuffer[k].v0].p)/2;

            faceBuffer[ntotalPolygons+(k*3)+0].v0=v+0;
            faceBuffer[ntotalPolygons+(k*3)+0].v1=faceBuffer[k].v1;
            faceBuffer[ntotalPolygons+(k*3)+0].v2=v+1;

            faceBuffer[ntotalPolygons+(k*3)+1].v0=v+2;
            faceBuffer[ntotalPolygons+(k*3)+1].v1=v+1;
            faceBuffer[ntotalPolygons+(k*3)+1].v2=faceBuffer[k].v2;

            faceBuffer[ntotalPolygons+(k*3)+2].v0=v+0;
            faceBuffer[ntotalPolygons+(k*3)+2].v1=v+1;
            faceBuffer[ntotalPolygons+(k*3)+2].v2=v+2;

            faceBuffer[k].v1=v+0;
            faceBuffer[k].v2=v+2;
            v=v+3;
        }

repeat this a numerous times until desired resolution has been achieved. After that, you need to reset the radius, to make it round.

Code: [Select]
        for(int k=0; k<totalVertices; k++) {
            iVectorLengthSet(&vertexBuffer[k].p,&vertexBuffer[k].p,radius);
            iVectorLengthSet(&vertexBuffer[k].n,&vertexBuffer[k].p,1);  //while we're at it, reset the normals too..
        }

shadmar

  • 3Impact Newbie
  • *
  • Posts: 17
Re: Creating a mesh during run time using a Vertex/Face Buffer
« Reply #9 on: January 23, 2010, 03:51:19 PM »
Why didn't read the 3impact forums before ?
Thanks for this :)