7670df25e5d2e844aefc6c99456c90e32912476c
[sdk] / ecere / src / gfx / 3D / meshes / Sphere.ec
1 namespace gfx3D::meshes;
2
3 import "Display"
4 import "Object" // TOFIX: If this is not here, Cube/Object gets registered as a 'class' rather than class 'struct'
5
6 public class Sphere : Object
7 {
8 private:
9    int numLat, numLon;
10    float flattenedBody;
11    numLat = 50;
12    numLon = 50;
13 public:
14
15    bool Create(DisplaySystem displaySystem)
16    {
17       bool result = false;
18       if(this)
19       {
20          InitializeMesh(displaySystem);
21          if(mesh)
22          {
23             int w = numLon;
24             if(mesh.Allocate({ vertices = true, normals = true, texCoords1 = true, tangents = true }, (numLat+1) * w, displaySystem))
25             {
26                Vector3Df *pVertices = mesh.vertices, *pNormals = mesh.normals, *pTangents = mesh.tangents;
27                Pointf *pTexCoords = mesh.texCoords;
28                int index;
29                int lat, lon;
30                PrimitiveGroup group = mesh.AddPrimitiveGroup({triangles, false},  numLat * w * 6);
31
32                index = 0;
33                for(lat = 0; lat <= numLat; lat++)
34                {
35                   Angle omega = 0.0001 + lat * (Pi - 0.0002) / (numLat) - Pi / 2;
36                   //Angle omega = lat * Pi / (numLat) - Pi / 2;
37                   float rounded = flattenedBody * numLat;
38                   double r = flattenedBody ? (lat < rounded ? (rounded-lat) / rounded : lat > numLat - rounded ? (lat - (numLat - rounded)) / rounded : 0) : 1;
39                   double cosOmega = cos(omega) * r + 1 * (1-r);
40                   double sinOmega = sin(omega);
41                   for(lon = 0; lon < w; lon++)
42                   {
43                      Angle theta = lon == w-1 ? 0 : lon * 2 * Pi / (w-1);
44                      double l = lon == w-1? lon - 0.0001 : lon;
45                      pVertices[index] =
46                      {
47                         (float) (sin(theta) * cosOmega);
48                         (float) sinOmega;
49                         (float) (cos(theta) * cosOmega);
50                      };
51
52                      pNormals[index] = pVertices[index];
53
54                      pTangents[index*2] =
55                      {
56                         (float) (sin(theta) * cos(omega - Pi/2));
57                         (float) sin(omega - Pi/2);
58                         (float) (cos(theta) * cos(omega - Pi/2));
59                      };
60                      pTangents[index*2+1] =
61                      {
62                         (float) (sin(theta - Pi/2) * cosOmega);
63                         (float) sin(omega);
64                         (float) (cos(theta - Pi/2) * cosOmega);
65                      };
66
67                      //pTangents[index*2 + 1].CrossProduct(pNormals[index], pTangents[index*2]);
68                      pTexCoords[index] = { (float)l / (w-1), (float)lat / (numLat) };
69                      index++;
70                   }
71                }
72
73                for(index = 0; index < group.nIndices; index++)
74                   group.indices[index] = 0;
75
76                // Strips
77                index = 0;
78
79                for(lat = 1; lat <= numLat; lat++)
80                   for(lon = 0; lon < w; lon++)
81                   {
82                      int n = (lon + 1) % w;
83                      group.indices[index++] = (uint16)((lat-1) * w + lon);
84                      group.indices[index++] = (uint16)((lat-1) * w + n);
85                      group.indices[index++] = (uint16)((lat) * w + n);
86
87                      group.indices[index++] = (uint16)((lat) * w + n);
88                      group.indices[index++] = (uint16)((lat) * w + lon);
89                      group.indices[index++] = (uint16)((lat-1) * w + lon);
90                   }
91
92                mesh.UnlockPrimitiveGroup(group);
93                result = true;
94
95                //mesh.ComputeNormals();
96             }
97
98             mesh.Unlock(0);
99             SetMinMaxRadius(true);
100          }
101       }
102       return result;
103    }
104
105    property int numLat { set { numLat = value; } }
106    property int numLon { set { numLon = value; } }
107    property float flattenedBody { set { flattenedBody = value; } }
108 }