// // This unit is part of the GLScene Engine, http://glscene.org // unit GLMeshBuilder; (* Build mesh objects. How often do you miss a BuildSphereMesh function for testing or editors? Well this unit is intended to solve that problem. We want fast, flexible functions with lots of options... Original Author: Joen Joensen. Contributed to the GLScene community. Features: BuildCube, BuildCylinder. *) interface uses System.SysUtils, System.Classes, GLScene, GLVectorFileObjects, GLVectorTypes, GLVectorGeometry, GLVectorLists; procedure BuildCube(Mesh : TMeshObject; const Position, Scale : TAffineVector); procedure BuildCylinder(Mesh : TMeshObject; const Position, Scale : TAffineVector; Slices : Integer); procedure BuildCylinder2(Mesh : TMeshObject; const Position, Scale : TAffineVector; TopRadius,BottomRadius,Height: single; Slices : Integer); //------------------------------------------------------------------ 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 BuildCube(Mesh : TMeshObject; 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; procedure BuildCylinder(Mesh : TMeshObject; 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; procedure BuildCylinder2(Mesh : TMeshObject; 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; end.