123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- //
- // The graphics engine GLScene
- //
- unit GLS.MeshBuilder;
- (*
- Build mesh objects.
- This unit is intended to create and draw some mesh objects using flexible functions
- with lots of options, including applying materials and textures for different facets.
- Started by Joen Joensen, who contributed procedures: BuildMeshCube, BuildMeshCylinder.
- *)
- interface
- uses
- System.SysUtils,
- System.Classes,
- Stage.VectorTypes,
- Stage.VectorGeometry,
- GLS.VectorLists,
- GLS.PersistentClasses,
- GLS.Scene,
- GLS.VectorFileObjects,
- GLS.MeshUtils;
- type
- (*
- Properties of a hexahedron with 6 quad parts
- *)
- TGLHexahedronProperties = record
- Normal3f: TVector3f;
- VertexCoords: array [0 .. 3] of TVector3f;
- TextureCoords: array [0 .. 3] of TVector2f;
- PartIndices: array [0 .. 5] of Integer;
- Material: string; // for 6 colors or cubic map from MaterialLibrary
- end;
- (*
- Properties of a sphere with two hemispheres
- using 5 points to make each hemisphere part
- *)
- TGLSphereProperties = record
- Normal3f: TVector3f;
- VertexCoords: array [0 .. 4] of TVector3f;
- TextureCoords: array [0 .. 4] of TVector2f;
- PartIndices: array [0 .. 1] of Integer;
- Material: string; // for 2 colors or textures
- end;
- (*
- Properties of a cylinder with 8 parts for 2 hemicylinders
- using 6 points to make each part for hemidisk caps and side surfaces
- *)
- TGLCylinderProperties = record
- Normal3f: TVector3f;
- VertexCoords: array [0 .. 5] of TVector3f;
- TextureCoords: array [0 .. 5] of TVector2f;
- PartIndices: array [0 .. 7] of Integer;
- Material: string; // for 8 colors or textures
- end;
- type
- TGLMeshOptimizerOption = (mooStandardize, mooVertexCache, mooSortByMaterials,
- mooMergeObjects);
- TGLMeshOptimizerOptions = set of TGLMeshOptimizerOption;
- // Hexahedron arrays for 6 parts
- const
- cMeshHexahedron: array [0 .. 5] of TGLHexahedronProperties = ((
- // Front Quad
- VertexCoords: ((X: - 1; Y: - 1; Z: 1), (X: 1; Y: - 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: - 1; Y: 1; Z: 1)); TextureCoords: ((X: 0; Y: 0), (X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1)); PartIndices: (0, 1, 2, 2, 3, 0);
- Material: 'Front';), (
- // Back Quad
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: - 1; Y: 1; Z: - 1), (X: 1; Y: 1;
- Z: - 1), (X: 1; Y: - 1; Z: - 1)); TextureCoords: ((X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1), (X: 0; Y: 0)); PartIndices: (4, 5, 6, 6, 7, 4);
- Material: 'Back';), (
- // Top Quad
- VertexCoords: ((X: - 1; Y: 1; Z: - 1), (X: - 1; Y: 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: 1; Y: 1; Z: - 1)); TextureCoords: ((X: 0; Y: 1), (X: 0; Y: 0), (X: 1;
- Y: 0), (X: 1; Y: 1)); PartIndices: (8, 9, 10, 10, 11, 8);
- Material: 'Top';), (
- // Bottom Quad
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: 1; Y: - 1; Z: - 1), (X: 1; Y: - 1;
- Z: 1), (X: - 1; Y: - 1; Z: 1)); TextureCoords: ((X: 1; Y: 1), (X: 0;
- Y: 1), (X: 0; Y: 0), (X: 1; Y: 0)); PartIndices: (12, 13, 14, 14, 15, 12);
- Material: 'Bottom';), (
- // Right Quad
- VertexCoords: ((X: 1; Y: - 1; Z: - 1), (X: 1; Y: 1; Z: - 1), (X: 1; Y: 1;
- Z: 1), (X: 1; Y: - 1; Z: 1)); TextureCoords: ((X: 1; Y: 0), (X: 1; Y: 1), (X: 0;
- Y: 1), (X: 0; Y: 0)); PartIndices: (16, 17, 18, 18, 19, 16);
- Material: 'Right';), (
- // Left Quad
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: - 1; Y: - 1; Z: 1), (X: - 1; Y: 1;
- Z: 1), (X: - 1; Y: 1; Z: - 1)); TextureCoords: ((X: 0; Y: 0), (X: 1;
- Y: 0), (X: 1; Y: 1), (X: 0; Y: 1)); PartIndices: (20, 21, 22, 22, 23, 20);
- Material: 'Left';));
- // Sphere arrays for parts with 2 hemispheres
- const
- cMeshSphere: array [0 .. 1] of TGLSphereProperties = ((
- // Top HemiSphere
- VertexCoords: ((X: - 1; Y: 1; Z: - 1), (X: - 1; Y: 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: 1; Y: 1; Z: - 1), (X: 0; Y: 1; Z: 0)); TextureCoords: ((X: 0; Y: 1), (X: 0; Y: 0), (X: 1;
- Y: 0), (X: 1; Y: 1), (X: 1; Y: 1)); PartIndices: (0, 1);
- Material: 'Top';), (
- // Bottom HemiSphere
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: 1; Y: - 1; Z: - 1), (X: 1; Y: - 1;
- Z: 1), (X: - 1; Y: - 1; Z: 1), (X: - 1; Y: - 1; Z: 1)); TextureCoords: ((X: 1; Y: 1), (X: 0;
- Y: 1), (X: 0; Y: 0), (X: 1; Y: 0), (X: 0; Y: 0)); PartIndices: (1, 2);
- Material: 'Bottom';));
- (*
- // Cylinder arrays
- const
- cMeshCylinder: array [0 .. 3] of TGLCylinderProperties = ((
- // Front Disk
- VertexCoords: ((X: - 1; Y: - 1; Z: 1), (X: 1; Y: - 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: - 1; Y: 1; Z: 1)); TextureCoords: ((X: 0; Y: 0), (X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1)); PartIndices: (0, 1, 2);
- Material: 'Front';), (
- // Back Disk
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: - 1; Y: 1; Z: - 1), (X: 1; Y: 1;
- Z: - 1), (X: 1; Y: - 1; Z: - 1)); TextureCoords: ((X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1), (X: 0; Y: 0)); PartIndices: (3, 4, 5);
- Material: 'Back';), (
- // Top Dome
- VertexCoords: ((X: - 1; Y: 1; Z: - 1), (X: - 1; Y: 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: 1; Y: 1; Z: - 1)); TextureCoords: ((X: 0; Y: 1), (X: 0; Y: 0), (X: 1;
- Y: 0), (X: 1; Y: 1)); PartIndices: (6, 7, 8);
- Material: 'Top';), (
- // Bottom Dome
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: 1; Y: - 1; Z: - 1), (X: 1; Y: - 1;
- Z: 1), (X: - 1; Y: - 1; Z: 1)); TextureCoords: ((X: 1; Y: 1), (X: 0;
- Y: 1), (X: 0; Y: 0), (X: 1; Y: 0)); PartIndices: (9, 10, 11);
- Material: 'Bottom';));
- // Tetrahedron part arrays
- const
- cMeshTetrahedron: array [0 .. 3] of TGLFacetProperties = ((
- // Front HemiDisk
- VertexCoords: ((X: - 1; Y: - 1; Z: 1), (X: 1; Y: - 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: - 1; Y: 1; Z: 1)); TextureCoords: ((X: 0; Y: 0), (X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1)); FacetIndex: (0, 1, 2, 2, 3, 0);
- Material: 'Front';), (
- // Back HemiDisk
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: - 1; Y: 1; Z: - 1), (X: 1; Y: 1;
- Z: - 1), (X: 1; Y: - 1; Z: - 1)); TextureCoords: ((X: 1; Y: 0), (X: 1;
- Y: 1), (X: 0; Y: 1), (X: 0; Y: 0)); FacetIndex: (4, 5, 6, 6, 7, 4);
- Material: 'Back';), (
- // Top HemiDome
- VertexCoords: ((X: - 1; Y: 1; Z: - 1), (X: - 1; Y: 1; Z: 1), (X: 1; Y: 1;
- Z: 1), (X: 1; Y: 1; Z: - 1)); TextureCoords: ((X: 0; Y: 1), (X: 0; Y: 0), (X: 1;
- Y: 0), (X: 1; Y: 1)); FacetIndex: (8, 9, 10, 10, 11, 8);
- Material: 'Top';), (
- // Bottom Square
- VertexCoords: ((X: - 1; Y: - 1; Z: - 1), (X: 1; Y: - 1; Z: - 1), (X: 1; Y: - 1;
- Z: 1), (X: - 1; Y: - 1; Z: 1)); TextureCoords: ((X: 1; Y: 1), (X: 0;
- Y: 1), (X: 0; Y: 0), (X: 1; Y: 0)); FacetIndex: (12, 13, 14, 14, 15, 12);
- Material: 'Bottom';));
- *)
- (* ---------------- Build Meshes ------------------- *)
- procedure BuildMeshCube(Mesh : TGLMeshObject; const Position, Scale : TAffineVector);
- procedure BuildMeshCylinder(Mesh : TGLMeshObject; const Position, Scale : TAffineVector; Slices : Integer);
- procedure BuildMeshCylinderAdv(Mesh: TGLMeshObject;
- const Position, Scale: TAffineVector; TopRadius, BottomRadius, Height: single;
- Slices: Integer);
- // Not implemented
- procedure BuildMeshHemiSphere(Mesh: TGLMeshObject; const Position, Scale: TAffineVector);
- procedure BuildMeshHemiCylinder(Mesh: TGLMeshObject; const Position, Scale: TAffineVector;
- Slices: Integer);
- (* ---------------- Make Meshes ------------------- *)
- procedure MakeMeshHexahedron(MeshObject: TGLMeshObject);
- // Not implemented
- procedure MakeMeshTetrahedron(MeshObject: TGLMeshObject);
- procedure MakeMeshSphere(MeshObject: TGLMeshObject);
- (* ------ -------- Mesh optimization --------------- *)
- // Optimize Mesh (list, default options)
- procedure OptimizeMesh(aList: TGLMeshObjectList; options: TGLMeshOptimizerOptions); overload;
- procedure OptimizeMesh(aList: TGLMeshObjectList); overload;
- // OptimizeMesh (object, with options)
- procedure OptimizeMesh(aMeshObject: TGLMeshObject; options: TGLMeshOptimizerOptions); overload;
- // OptimizeMesh (object, default options)
- procedure OptimizeMesh(aMeshObject: TGLMeshObject); overload;
- procedure FacesSmooth(aMeshObj: TGLMeshObject;
- aWeldDistance: Single = 0.0000001; aThreshold: Single = 35.0;
- InvertNormals: boolean = false);
- var
- vDefaultMeshOptimizerOptions: TGLMeshOptimizerOptions = [mooStandardize,
- mooVertexCache, mooSortByMaterials, mooMergeObjects];
- //------------------------------------------------------------------
- implementation
- //------------------------------------------------------------------
- function VectorCombineWeighted(const Position, Scale: TAffineVector; X, Y, Z: single)
- : TAffineVector;
- begin
- Result.X := Position.X + Scale.X * X;
- Result.Y := Position.Y + Scale.Y * Y;
- Result.Z := Position.Z + Scale.Z * Z;
- end;
- procedure BuildMeshCube(Mesh: TGLMeshObject; const Position, Scale: TAffineVector);
- var
- FGR : TFGVertexNormalTexIndexList;
- VertexOffset : Integer;
- NormalOffset : Integer;
- TextureOffset : Integer;
- begin
- // Vertexes
- VertexOffset :=
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5,0.5,0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,-0.5,0.5,0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5,-0.5,0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,-0.5,-0.5,0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5,0.5,-0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,-0.5,0.5,-0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5,-0.5,-0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,-0.5,-0.5,-0.5));
- // Normals
- NormalOffset :=
- Mesh.Normals.Add(AffineVectorMake(0,0,1));
- Mesh.Normals.Add(AffineVectorMake(0,0,-1));
- Mesh.Normals.Add(AffineVectorMake(1,0,0));
- Mesh.Normals.Add(AffineVectorMake(-1,0,0));
- Mesh.Normals.Add(AffineVectorMake(0,1,0));
- Mesh.Normals.Add(AffineVectorMake(0,-1,0));
- // Texture Coordinates
- TextureOffset :=
- Mesh.TexCoords.Add(AffineVectorMake(1,1,1));
- Mesh.TexCoords.Add(AffineVectorMake(0,1,1));
- Mesh.TexCoords.Add(AffineVectorMake(1,0,1));
- Mesh.TexCoords.Add(AffineVectorMake(0,0,1));
- Mesh.TexCoords.Add(AffineVectorMake(1,1,0));
- Mesh.TexCoords.Add(AffineVectorMake(0,1,0));
- Mesh.TexCoords.Add(AffineVectorMake(1,0,0));
- Mesh.TexCoords.Add(AffineVectorMake(0,0,0));
- FGR := TFGVertexNormalTexIndexList.CreateOwned(Mesh.FaceGroups);
- FGR.Mode := fgmmTriangles;
- // Front
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 1, VertexOffset + 3);
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 3, VertexOffset + 2);
- FGR.NormalIndices.Add(NormalOffset + 0, NormalOffset + 0, NormalOffset + 0);
- FGR.NormalIndices.Add(NormalOffset + 0, NormalOffset + 0, NormalOffset + 0);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 1, TextureOffset + 3);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 3, TextureOffset + 2);
- // Back
- FGR.VertexIndices.Add(VertexOffset + 4, VertexOffset + 6, VertexOffset + 7);
- FGR.VertexIndices.Add(VertexOffset + 4, VertexOffset + 7, VertexOffset + 5);
- FGR.NormalIndices.Add(NormalOffset + 1, NormalOffset + 1, NormalOffset + 1);
- FGR.NormalIndices.Add(NormalOffset + 1, NormalOffset + 1, NormalOffset + 1);
- FGR.TexCoordIndices.Add(TextureOffset + 4, TextureOffset + 6, TextureOffset + 7);
- FGR.TexCoordIndices.Add(TextureOffset + 4, TextureOffset + 7, TextureOffset + 5);
- // Right
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 2, VertexOffset + 6);
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 6, VertexOffset + 4);
- FGR.NormalIndices.Add(NormalOffset + 2, NormalOffset + 2, NormalOffset + 2);
- FGR.NormalIndices.Add(NormalOffset + 2, NormalOffset + 2, NormalOffset + 2);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 2, TextureOffset + 6);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 6, TextureOffset + 4);
- // Left
- FGR.VertexIndices.Add(VertexOffset + 1, VertexOffset + 5, VertexOffset + 7);
- FGR.VertexIndices.Add(VertexOffset + 1, VertexOffset + 7, VertexOffset + 3);
- FGR.NormalIndices.Add(NormalOffset + 3, NormalOffset + 3, NormalOffset + 3);
- FGR.NormalIndices.Add(NormalOffset + 3, NormalOffset + 3, NormalOffset + 3);
- FGR.TexCoordIndices.Add(TextureOffset + 1, TextureOffset + 5, TextureOffset + 7);
- FGR.TexCoordIndices.Add(TextureOffset + 1, TextureOffset + 7, TextureOffset + 3);
- // Top
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 4, VertexOffset + 5);
- FGR.VertexIndices.Add(VertexOffset + 0, VertexOffset + 5, VertexOffset + 1);
- FGR.NormalIndices.Add(NormalOffset + 4, NormalOffset + 4, NormalOffset + 4);
- FGR.NormalIndices.Add(NormalOffset + 4, NormalOffset + 4, NormalOffset + 4);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 4, TextureOffset + 5);
- FGR.TexCoordIndices.Add(TextureOffset + 0, TextureOffset + 5, TextureOffset + 1);
- // Bottom
- FGR.VertexIndices.Add(VertexOffset + 2, VertexOffset + 3, VertexOffset + 7);
- FGR.VertexIndices.Add(VertexOffset + 2, VertexOffset + 7, VertexOffset + 6);
- FGR.NormalIndices.Add(NormalOffset + 5, NormalOffset + 5, NormalOffset + 5);
- FGR.NormalIndices.Add(NormalOffset + 5, NormalOffset + 5, NormalOffset + 5);
- FGR.TexCoordIndices.Add(TextureOffset + 2, TextureOffset + 3, TextureOffset + 7);
- FGR.TexCoordIndices.Add(TextureOffset + 2, TextureOffset + 7, TextureOffset + 6);
- end;
- // Mesh cylinder
- //
- procedure BuildMeshCylinder(Mesh : TGLMeshObject; const Position, Scale : TAffineVector; Slices : Integer);
- var
- FGR : TFGVertexNormalTexIndexList;
- VertexOffset : Integer;
- NormalOffset : Integer;
- TextureOffset : Integer;
- Cosine,Sine : array of Single;
- xc,yc : Integer;
- begin
- if Slices < 3 then Exit;
- SetLength(Sine,Slices+1);
- SetLength(Cosine,Slices+1);
- PrepareSinCosCache(Sine,Cosine,0,360);
- VertexOffset := Mesh.Vertices.Count;
- NormalOffset := Mesh.Normals.Count;
- TextureOffset := Mesh.TexCoords.Count;
- for xc := 0 to Slices-1 do
- begin
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5*cosine[xc],0.5*sine[xc],0.5));
- Mesh.Vertices.Add(VectorCombineWeighted(Position,Scale,0.5*cosine[xc],0.5*sine[xc],-0.5));
- // Normals
- Mesh.Normals.add(AffineVectorMake(cosine[xc],sine[xc],0));
- // Texture Coordinates
- Mesh.TexCoords.add(VectorCombineWeighted(Position,XYZVector,0.5*cosine[xc],0.5*sine[xc],0.5));
- Mesh.TexCoords.add(VectorCombineWeighted(Position,XYZVector,0.5*cosine[xc],0.5*sine[xc],-0.5));
- end;
- Mesh.Normals.add(AffineVectorMake(0,0,1));
- Mesh.Normals.add(AffineVectorMake(0,0,-1));
- FGR := TFGVertexNormalTexIndexList.CreateOwned(Mesh.FaceGroups);
- FGR.Mode := fgmmTriangles;
- for xc := 0 to Slices - 1 do
- begin
- yc := xc + 1;
- if yc = slices then yc := 0;
- FGR.VertexIndices.Add(VertexOffset + xc * 2, VertexOffset + xc * 2 + 1, VertexOffset + yc * 2 + 1);
- FGR.VertexIndices.Add(VertexOffset + xc * 2, VertexOffset + yc * 2 + 1, VertexOffset + yc * 2);
- FGR.NormalIndices.Add(NormalOffset + xc, NormalOffset + xc, NormalOffset + yc);
- FGR.NormalIndices.Add(NormalOffset + xc, NormalOffset + yc, NormalOffset + yc);
- FGR.TexCoordIndices.Add(TextureOffset + xc * 2, TextureOffset + xc * 2 + 1, TextureOffset + yc * 2 + 1);
- FGR.TexCoordIndices.Add(TextureOffset + xc * 2, TextureOffset + yc * 2 + 1, TextureOffset + yc * 2);
- End;
- for xc := 1 to Slices - 2 do
- begin
- yc := xc + 1;
- FGR.VertexIndices.Add(VertexOffset, VertexOffset + xc * 2, VertexOffset + yc * 2);
- FGR.VertexIndices.Add(VertexOffset + 1, VertexOffset + yc * 2 + 1, VertexOffset + xc * 2 + 1);
- FGR.NormalIndices.Add(NormalOffset + Slices, NormalOffset + Slices, NormalOffset + Slices);
- FGR.NormalIndices.Add(NormalOffset + Slices + 1, NormalOffset + Slices + 1, NormalOffset + Slices + 1);
- FGR.TexCoordIndices.Add(TextureOffset, TextureOffset + xc * 2, TextureOffset + yc * 2);
- FGR.TexCoordIndices.Add(TextureOffset + 1, TextureOffset + yc * 2 + 1, TextureOffset + xc * 2 + 1);
- end;
- end;
- //
- // Mesh Cylinder with advanced options
- //
- procedure BuildMeshCylinderAdv(Mesh: TGLMeshObject;
- const Position, Scale: TAffineVector; TopRadius, BottomRadius, Height: single; Slices: Integer);
- var
- FGR: TFGVertexNormalTexIndexList;
- VertexOffset: Integer;
- NormalOffset: Integer;
- TextureOffset: Integer;
- Cosine, Sine: array of single;
- xc, yc: Integer;
- begin
- if Slices < 3 then
- Exit;
- SetLength(Sine, Slices + 1);
- SetLength(Cosine, Slices + 1);
- PrepareSinCosCache(Sine, Cosine, 0, 360);
- VertexOffset := Mesh.Vertices.Count;
- NormalOffset := Mesh.Normals.Count;
- TextureOffset := Mesh.TexCoords.Count;
- for xc := 0 to Slices - 1 do
- begin
- Mesh.Vertices.Add(VectorCombineWeighted(Position, Scale, TopRadius * 0.5 * Cosine[xc],
- TopRadius * 0.5 * Sine[xc], Height / 2));
- Mesh.Vertices.Add(VectorCombineWeighted(Position, Scale, BottomRadius * 0.5 * Cosine[xc],
- BottomRadius * 0.5 * Sine[xc], -Height / 2));
- // Normals
- Mesh.Normals.Add(AffineVectorMake(Cosine[xc], Sine[xc], 0));
- // Texture Coordinates
- Mesh.TexCoords.Add(VectorCombineWeighted(Position, XYZVector, TopRadius * 0.5 * Cosine[xc],
- TopRadius * 0.5 * Sine[xc], Height / 2));
- Mesh.TexCoords.Add(VectorCombineWeighted(Position, XYZVector, BottomRadius * 0.5 * Cosine[xc],
- BottomRadius * 0.5 * Sine[xc], -Height / 2));
- end;
- Mesh.Normals.Add(AffineVectorMake(0, 0, 1));
- Mesh.Normals.Add(AffineVectorMake(0, 0, -1));
- FGR := TFGVertexNormalTexIndexList.CreateOwned(Mesh.FaceGroups);
- FGR.Mode := fgmmTriangles;
- for xc := 0 to Slices - 1 do
- begin
- yc := xc + 1;
- if yc = Slices then
- yc := 0;
- FGR.VertexIndices.Add(VertexOffset + xc * 2, VertexOffset + xc * 2 + 1,
- VertexOffset + yc * 2 + 1);
- FGR.VertexIndices.Add(VertexOffset + xc * 2, VertexOffset + yc * 2 + 1, VertexOffset + yc * 2);
- FGR.NormalIndices.Add(NormalOffset + xc, NormalOffset + xc, NormalOffset + yc);
- FGR.NormalIndices.Add(NormalOffset + xc, NormalOffset + yc, NormalOffset + yc);
- FGR.TexCoordIndices.Add(TextureOffset + xc * 2, TextureOffset + xc * 2 + 1,
- TextureOffset + yc * 2 + 1);
- FGR.TexCoordIndices.Add(TextureOffset + xc * 2, TextureOffset + yc * 2 + 1,
- TextureOffset + yc * 2);
- end;
- for xc := 1 to Slices - 2 do
- begin
- yc := xc + 1;
- FGR.VertexIndices.Add(VertexOffset, VertexOffset + xc * 2, VertexOffset + yc * 2);
- FGR.VertexIndices.Add(VertexOffset + 1, VertexOffset + yc * 2 + 1, VertexOffset + xc * 2 + 1);
- FGR.NormalIndices.Add(NormalOffset + Slices, NormalOffset + Slices, NormalOffset + Slices);
- FGR.NormalIndices.Add(NormalOffset + Slices + 1, NormalOffset + Slices + 1,
- NormalOffset + Slices + 1);
- FGR.TexCoordIndices.Add(TextureOffset, TextureOffset + xc * 2, TextureOffset + yc * 2);
- FGR.TexCoordIndices.Add(TextureOffset + 1, TextureOffset + yc * 2 + 1,
- TextureOffset + xc * 2 + 1);
- end;
- end;
- // -----------------------------------------------------------
- // Make Mesh Hexahedron
- // -----------------------------------------------------------
- procedure MakeMeshHexahedron(MeshObject: TGLMeshObject);
- var
- FaceGroupList: TFGVertexIndexList;
- i, j: Integer;
- begin
- for i := Low(cMeshHexahedron) to High(cMeshHexahedron) do
- begin
- // Add vertex coordinates
- for j := Low(cMeshHexahedron[i].VertexCoords) to High(cMeshHexahedron[i].VertexCoords) do
- MeshObject.Vertices.Add(cMeshHexahedron[i].VertexCoords[j]);
- // Add texture coordinates
- for j := Low(cMeshHexahedron[i].TextureCoords) to High(cMeshHexahedron[i].TextureCoords) do
- MeshObject.TexCoords.Add(cMeshHexahedron[i].TextureCoords[j]);
- FaceGroupList := TFGVertexIndexList.CreateOwned(MeshObject.FaceGroups);
- for j := Low(cMeshHexahedron[i].PartIndices) to High(cMeshHexahedron[i].PartIndices) do
- FaceGroupList.Add(cMeshHexahedron[i].PartIndices[j]);
- FaceGroupList.MaterialName := cMeshHexahedron[i].Material;
- end;
- end;
- // --------------------------------------------------------------------------------------
- procedure BuildMeshHemiSphere(Mesh : TGLMeshObject; const Position, Scale : TAffineVector);
- begin
- //
- end;
- procedure BuildMeshHemiCylinder(Mesh : TGLMeshObject; const Position, Scale : TAffineVector; Slices : Integer);
- begin
- //
- end;
- // --------------------------------------------------------------------------------------
- procedure MakeMeshSphere(MeshObject : TGLMeshObject);
- begin
- //
- end;
- procedure MakeMeshTetrahedron(MeshObject: TGLMeshObject);
- begin
- //
- end;
- // --------------- Mesh Optimization ---------------
- procedure OptimizeMesh(aList: TGLMeshObjectList);
- begin
- OptimizeMesh(aList, vDefaultMeshOptimizerOptions);
- end;
- procedure OptimizeMesh(aList: TGLMeshObjectList;
- options: TGLMeshOptimizerOptions);
- var
- i, k: Integer;
- mob, mo: TGLMeshObject;
- fg: TGLFaceGroup;
- fgvi: TFGVertexIndexList;
- begin
- // optimize all mesh objects
- for i := 0 to aList.Count - 1 do
- begin
- OptimizeMesh(aList[i], options);
- end;
- if (mooStandardize in options) then
- begin
- // drop mesh objects that have become empty
- for i := aList.Count - 1 downto 0 do
- begin
- if (aList[i].Mode = momFaceGroups) and (aList[i].FaceGroups.Count = 0)
- then
- aList[i].Free;
- end;
- end;
- if (aList.Count > 0) and (mooMergeObjects in options) then
- begin
- mob := aList[0];
- Assert(mob.Mode = momFaceGroups);
- for i := 1 to aList.Count - 1 do
- begin
- mo := aList[i];
- Assert(mo.Mode = momFaceGroups);
- k := mob.Vertices.Count;
- mob.Vertices.Add(mo.Vertices);
- mob.Normals.Add(mo.Normals);
- mob.TexCoords.Add(mo.TexCoords);
- while mo.FaceGroups.Count > 0 do
- begin
- fg := mo.FaceGroups[0];
- fgvi := (fg as TFGVertexIndexList);
- fgvi.Owner := mob.FaceGroups;
- mob.FaceGroups.Add(fgvi);
- mo.FaceGroups.Delete(0);
- fgvi.VertexIndices.Offset(k);
- end;
- end;
- for i := aList.Count - 1 downto 1 do
- aList[i].Free;
- end;
- end;
- procedure OptimizeMesh(aMeshObject: TGLMeshObject);
- begin
- OptimizeMesh(aMeshObject, vDefaultMeshOptimizerOptions);
- end;
- procedure OptimizeMesh(aMeshObject: TGLMeshObject;
- options: TGLMeshOptimizerOptions);
- var
- i: Integer;
- fg: TGLFaceGroup;
- coords, TexCoords, Normals: TGLAffineVectorList;
- il: TGLIntegerList;
- materialName: String;
- begin
- if (mooMergeObjects in options) then
- begin
- if aMeshObject.Mode = momFaceGroups then
- begin
- // remove empty facegroups
- for i := aMeshObject.FaceGroups.Count - 1 downto 0 do
- begin
- fg := aMeshObject.FaceGroups[i];
- if fg.TriangleCount = 0 then
- fg.Free;
- end;
- end;
- end;
- if (mooStandardize in options) then
- begin
- if (aMeshObject.Mode <> momFaceGroups) or (aMeshObject.FaceGroups.Count <= 1)
- then
- begin
- if aMeshObject.FaceGroups.Count = 1 then
- materialName := aMeshObject.FaceGroups[0].materialName;
- TexCoords := TGLAffineVectorList.Create;
- Normals := TGLAffineVectorList.Create;
- coords := aMeshObject.ExtractTriangles(TexCoords, Normals);
- try
- il := BuildVectorCountOptimizedIndices(coords, Normals, TexCoords);
- try
- aMeshObject.Clear;
- if il.Count > 0 then
- begin
- RemapReferences(Normals, il);
- RemapReferences(TexCoords, il);
- RemapAndCleanupReferences(coords, il);
- aMeshObject.Vertices := coords;
- aMeshObject.Normals := Normals;
- aMeshObject.TexCoords := TexCoords;
- fg := TFGVertexIndexList.CreateOwned(aMeshObject.FaceGroups);
- fg.materialName := materialName;
- TFGVertexIndexList(fg).VertexIndices := il;
- end;
- finally
- il.Free;
- end;
- finally
- coords.Free;
- Normals.Free;
- TexCoords.Free;
- end;
- end
- else
- Assert(false,
- 'Standardization with multiple facegroups not supported... yet.');
- end;
- if (mooVertexCache in options) and (aMeshObject.Mode = momFaceGroups) then
- begin
- for i := 0 to aMeshObject.FaceGroups.Count - 1 do
- begin
- fg := aMeshObject.FaceGroups[i];
- if fg.ClassType = TFGVertexIndexList then
- with TFGVertexIndexList(fg) do
- begin
- if Mode in [fgmmTriangles, fgmmFlatTriangles] then
- IncreaseCoherency(VertexIndices, 12);
- end;
- end;
- end;
- if mooSortByMaterials in options then
- aMeshObject.FaceGroups.SortByMaterial;
- end;
- procedure FacesSmooth(aMeshObj: TGLMeshObject;
- aWeldDistance: Single = 0.0000001; aThreshold: Single = 35.0;
- InvertNormals: boolean = false);
- Var
- i, J, k, L: Integer;
- WeldedVertex: TGLAffineVectorList;
- TmpIntegerList: TGLIntegerList;
- IndexMap: TStringList;
- n: TAffineVector;
- indicesMap: TGLIntegerList;
- Index: Integer;
- FaceList: TGLIntegerList;
- NormalList: TGLAffineVectorList;
- FaceNormalList: TGLAffineVectorList;
- FaceGroup: TGLFaceGroup;
- fg, FG1: TFGVertexIndexList;
- Threshold: Single;
- Angle: Single;
- ReferenceMap: TGLIntegerList;
- ID1, ID2: Integer;
- Index1, Index2, Index3: Integer;
- function FindReferenceIndex(aID: Integer): Integer;
- begin
- Result := ReferenceMap[aID];
- end;
- function iMin(a, b: Integer): Integer;
- begin
- if a < b then
- Result := a
- else
- Result := b;
- end;
- function iMax(a, b: Integer): Integer;
- begin
- if a > b then
- Result := a
- else
- Result := b;
- end;
- begin
- Threshold := aThreshold * Pi / 180.0;
- // build the vectices reference map
- ReferenceMap := TGLIntegerList.Create;
- WeldedVertex := TGLAffineVectorList.Create;
- WeldedVertex.Assign(aMeshObj.Vertices);
- indicesMap := TGLIntegerList.Create;
- // first of all, weld the very closed vertices
- WeldVertices(WeldedVertex, indicesMap, aWeldDistance);
- // then, rebuild the map list
- IndexMap := TStringList.Create;
- for i := 0 to WeldedVertex.Count - 1 do
- begin
- ReferenceMap.Assign(indicesMap);
- TmpIntegerList := TGLIntegerList.Create;
- Index := ReferenceMap.IndexOf(i);
- while Index >= 0 do
- begin
- TmpIntegerList.Add(Index);
- ReferenceMap[Index] := -99999;
- Index := ReferenceMap.IndexOf(i);
- end;
- IndexMap.AddObject(IntToStr(i), TmpIntegerList);
- end;
- ReferenceMap.Assign(indicesMap);
- // never used these, free them all
- WeldedVertex.Free;
- indicesMap.Free;
- // creates a TexPoint list for save face infomation, where s=facegroup index, t=face index
- FaceList := TGLIntegerList.Create;
- NormalList := TGLAffineVectorList.Create;
- FaceNormalList := TGLAffineVectorList.Create;
- // NormalIndex := TGLIntegerList.Create;
- for i := 0 to aMeshObj.FaceGroups.Count - 1 do
- begin
- FaceGroup := aMeshObj.FaceGroups[i];
- TmpIntegerList := TFGVertexIndexList(FaceGroup).VertexIndices;
- for J := 0 to (TmpIntegerList.Count div 3) - 1 do
- begin
- FaceList.Add(i);
- FaceList.Add(J);
- CalcPlaneNormal(aMeshObj.Vertices[TmpIntegerList[J * 3 + 0]],
- aMeshObj.Vertices[TmpIntegerList[J * 3 + 1]],
- aMeshObj.Vertices[TmpIntegerList[J * 3 + 2]], n);
- // add three normals for one trangle
- FaceNormalList.Add(n);
- NormalList.Add(n);
- NormalList.Add(n);
- NormalList.Add(n);
- end;
- end;
- // do smooth
- for i := 0 to (FaceList.Count div 2) - 1 do
- begin
- Index := FaceList[i * 2 + 0];
- Index1 := FaceList[i * 2 + 1];
- fg := TFGVertexIndexList(aMeshObj.FaceGroups[Index]);
- for J := 0 to 2 do
- begin
- for k := 0 to (FaceList.Count div 2) - 1 do
- begin
- Index2 := FaceList[k * 2 + 0];
- Index3 := FaceList[k * 2 + 1];
- FG1 := TFGVertexIndexList(aMeshObj.FaceGroups[Index2]);
- if i <> k then
- begin
- for L := 0 to 2 do
- begin
- // two face contain the same vertex
- ID1 := FindReferenceIndex(fg.VertexIndices[Index1 * 3 + J]);
- ID2 := FindReferenceIndex(FG1.VertexIndices[Index3 * 3 + L]);
- if ID1 = ID2 then
- begin
- Angle := VectorDotProduct(FaceNormalList[i], FaceNormalList[k]);
- if Angle > Threshold then
- NormalList[i * 3 + J] := VectorAdd(NormalList[i * 3 + J],
- FaceNormalList[k]);
- end;
- end;
- end;
- end;
- n := NormalList[i * 3 + J];
- NormalizeVector(n);
- NormalList[i * 3 + J] := n;
- end;
- end;
- for i := 0 to (FaceList.Count div 2) - 1 do
- begin
- Index := FaceList[i * 2 + 0];
- fg := TFGVertexIndexList(aMeshObj.FaceGroups[Index]);
- Index := FaceList[i * 2 + 1];
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 0)]] :=
- NormalList[(i * 3 + 0)];
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 1)]] :=
- NormalList[(i * 3 + 1)];
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 2)]] :=
- NormalList[(i * 3 + 2)];
- if InvertNormals then
- begin
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 0)]] :=
- VectorNegate(aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 0)]]);
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 1)]] :=
- VectorNegate(aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 1)]]);
- aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 2)]] :=
- VectorNegate(aMeshObj.Normals[fg.VertexIndices[(Index * 3 + 2)]]);
- end;
- end;
- FaceList.Free;
- NormalList.Free;
- FaceNormalList.Free;
- ReferenceMap.Free;
- for i := 0 to IndexMap.Count - 1 do
- IndexMap.Objects[i].Free;
- IndexMap.Free;
- end;
- end.
|