31 unsigned int normalSize = 3;
32 unsigned int index = 0;
34 for (
unsigned int horizontalIndex = 0; horizontalIndex < circlesCount; ++horizontalIndex)
37 float phi = (
float) horizontalIndex * 2.0
f *
M_PI / circlesCount;
39 Vec3f horizontalTangent = {-sinf(phi), 0.0f, cosf(phi)};
41 for (
unsigned int verticalIndex = 0; verticalIndex < pointsPerCircleCount; ++verticalIndex)
44 float theta = (
float) verticalIndex * 2.0
f *
M_PI / pointsPerCircleCount;
46 Vec3f verticalTangent = {-cosf(phi) * sinf(theta), cosf(theta), -sinf(phi) * sinf(theta)};
48 assert(index < circlesCount * pointsPerCircleCount * normalSize);
50 normals[index++] = horizontalTangent.z * verticalTangent.y - horizontalTangent.y * verticalTangent.z;
51 normals[index++] = horizontalTangent.x * verticalTangent.z - horizontalTangent.z * verticalTangent.x;
52 normals[index++] = horizontalTangent.y * verticalTangent.x - horizontalTangent.x * verticalTangent.y;
59 if (controlPointsIndices == NULL)
61 LOGE(
"Cannot use null pointer while calculating control points indices.");
67 const unsigned int pointsPerCircleCount = 12;
68 const unsigned int circlesCount = 12;
69 const unsigned int torusVerticesCount = pointsPerCircleCount * circlesCount;
72 unsigned int startIndex = 0;
74 unsigned int currentCircle = 0;
77 unsigned int index = 0;
80 for (
unsigned int instanceIndex = 0; instanceIndex < patchInstancesCount; ++instanceIndex)
83 for (
unsigned int x = 0;
x < patchDimension; ++
x)
86 currentCircle = startIndex / pointsPerCircleCount;
89 for (
unsigned int y = 0;
y < patchDimension; ++
y)
91 unsigned int currentIndex = startIndex +
y;
94 if (currentIndex >= pointsPerCircleCount * (currentCircle + 1))
96 currentIndex -= pointsPerCircleCount;
99 controlPointsIndices[index++] = currentIndex;
101 assert(index <= controlPointsIndicesCount);
105 startIndex += pointsPerCircleCount;
108 if (startIndex >= torusVerticesCount)
110 startIndex -= torusVerticesCount;
115 startIndex -= pointsPerCircleCount;
118 if (currentCircle == 0)
120 startIndex += patchDimension - 1;
126 if (patchVertices == NULL || patchTriangleIndices == NULL)
128 LOGE(
"Cannot use null pointers while calculating patch data.");
134 const unsigned int patchComponentsCount = patchDensity * patchDensity * 2;
136 const unsigned int patchTriangleIndicesCount = (patchDensity - 1) * (patchDensity - 1) * 6;
139 const unsigned int uvComponentsCount = 2;
141 const unsigned int verticesPerQuadCount = 6;
144 unsigned int uvIndex = 0;
146 unsigned int triangleVertexIndex = 0;
148 for (
unsigned int x = 0;
x < patchDensity; ++
x)
151 float u = (
float)
x / (patchDensity - 1);
153 for (
unsigned int y = 0; y < patchDensity; ++
y)
156 float v = (
float) y / (patchDensity - 1);
158 patchVertices[uvIndex++] = u;
159 patchVertices[uvIndex++] =
v;
161 assert(uvIndex <= patchComponentsCount);
178 for (
unsigned int x = 0;
x < patchDensity - 1; ++
x)
180 for (
unsigned int y = 0; y < patchDensity - 1; ++
y)
182 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x +
y;
183 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x + y + 1;
184 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y;
186 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y;
187 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x + y + 1;
188 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y + 1;
190 assert(triangleVertexIndex <= patchTriangleIndicesCount);
197 const unsigned int torusVerticesCount = circlesCount * pointsPerCircleCount;
199 for (
unsigned int i = 0; i < circlesCount; ++i)
201 for (
unsigned int j = 0; j < pointsPerCircleCount; ++j)
204 unsigned int lineStart = i * pointsPerCircleCount + j;
206 unsigned int horizontalEnd = (i + 1) * pointsPerCircleCount + j;
208 unsigned int verticalEnd = i * pointsPerCircleCount + j + 1;
211 if (horizontalEnd >= torusVerticesCount)
213 horizontalEnd -= torusVerticesCount;
217 if (verticalEnd >= (i + 1) * pointsPerCircleCount)
219 verticalEnd -= pointsPerCircleCount;
223 indices[(i * pointsPerCircleCount + j) * 4 ] = lineStart;
224 indices[(i * pointsPerCircleCount + j) * 4 + 1] = horizontalEnd;
227 indices[(i * pointsPerCircleCount + j) * 4 + 2] = lineStart;
228 indices[(i * pointsPerCircleCount + j) * 4 + 3] = verticalEnd;
236 if (vertices == NULL)
238 LOGE(
"Cannot use null pointer while calculating torus vertices.");
244 unsigned int componentIndex = 0;
246 for (
unsigned int horizontalIndex = 0; horizontalIndex < circlesCount; ++horizontalIndex)
249 float xyAngle = (
float) horizontalIndex * 2.0
f *
M_PI / circlesCount;
251 for (
unsigned int verticalIndex = 0; verticalIndex < pointsPerCircleCount; ++verticalIndex)
254 float theta = (
float) verticalIndex * 2.0
f *
M_PI / pointsPerCircleCount;
257 vertices[componentIndex++] = (torusRadius + circleRadius * cosf(theta)) * cosf(xyAngle);
259 vertices[componentIndex++] = circleRadius * sinf(theta);
261 vertices[componentIndex++] = (torusRadius + circleRadius * cosf(theta)) * sinf(xyAngle);
263 vertices[componentIndex++] = 1.0f;
271 const unsigned int torusVerticesCount = circlesCount * pointsPerCircleCount;
272 const unsigned int torusIndicesCount = (2 * circlesCount + 1) * pointsPerCircleCount + 1;
275 unsigned int currentIndex = 0;
277 indices[counter++] = currentIndex;
279 bool isLastStrip =
false;
281 for (
unsigned int stripIndex = 0; stripIndex < pointsPerCircleCount; ++stripIndex)
283 assert(currentIndex == stripIndex);
288 isLastStrip = currentIndex >= pointsPerCircleCount;
290 assert(counter < torusIndicesCount);
292 indices[counter++] = isLastStrip ? (currentIndex - pointsPerCircleCount) : currentIndex;
294 for (
unsigned int circleIndex = 0; circleIndex < circlesCount; ++circleIndex)
296 currentIndex = currentIndex + pointsPerCircleCount - 1;
298 if (currentIndex >= torusVerticesCount)
300 currentIndex -= torusVerticesCount;
303 assert(counter < torusIndicesCount);
305 indices[counter++] = currentIndex;
309 assert(counter < torusIndicesCount);
311 indices[counter++] = isLastStrip ? currentIndex - pointsPerCircleCount : currentIndex;
318 if (vertices == NULL)
320 LOGE(
"Cannot use null pointer while calculating torus vertices.");
326 const float kappa = 4.0f * (sqrtf(2.0
f) - 1.0f) / 3.0
f;
328 const float alpha = atanf(kappa);
330 const float distortedCircleRadius = circleRadius * sqrt(1.0
f + kappa * kappa);
332 const float distortedTorusRadius = torusRadius * sqrt(1.0
f + kappa * kappa);
334 const int quadrantsCount = 4;
336 const int circlesCount = 12;
338 const int pointsPerCircleCount = 12;
346 unsigned int componentIndex = 0;
349 for (
int horizontalIndex = 0; horizontalIndex < circlesCount; ++horizontalIndex)
352 const int currentCircleModulo = horizontalIndex % (quadrantsCount - 1);
355 float currentTorusRadius;
356 float currentCircleRadius;
360 switch (currentCircleModulo)
364 currentTorusRadius = torusRadius;
369 currentTorusRadius = distortedTorusRadius;
370 currentPhi = phi + alpha;
374 phi = (
float) (horizontalIndex + 1) *
M_PI / (2 * (quadrantsCount - 1));
375 currentTorusRadius = distortedTorusRadius;
376 currentPhi = phi - alpha;
380 for (
int verticalIndex = 0; verticalIndex < pointsPerCircleCount; ++verticalIndex)
383 const int currentPointModulo = verticalIndex % (quadrantsCount - 1);
385 switch (currentPointModulo)
390 currentCircleRadius = circleRadius;
391 currentTheta = theta;
397 currentCircleRadius = distortedCircleRadius;
398 currentTheta = theta + alpha;
404 theta = (
float) (verticalIndex + 1) *
M_PI / (2 * (quadrantsCount - 1));
405 currentCircleRadius = distortedCircleRadius;
406 currentTheta = theta - alpha;
412 vertices[componentIndex++] = (currentTorusRadius + currentCircleRadius * cosf(currentTheta)) * cosf(currentPhi);
413 vertices[componentIndex++] = currentCircleRadius * sinf(currentTheta);
414 vertices[componentIndex++] = (currentTorusRadius + currentCircleRadius * cosf(currentTheta)) * sinf(currentPhi);
415 vertices[componentIndex++] = 1.0f;
static void calculateControlPointsIndices(unsigned int patchDimension, unsigned int patchInstancesCount, unsigned int controlPointsIndicesCount, unsigned int *controlPointsIndices)
Determines an array of indices defining a mesh of control points for instanced torus patches...
static void calculateTriangleStripIndices(unsigned int circlesCount, unsigned int pointsPerCircleCount, unsigned int *indices)
Determines indices for DrawElements() call for shaded torus drawn in triangle strip mode...
static void generateNormals(unsigned int circlesCount, unsigned int pointsPerCircleCount, float *normals)
Generates torus's normal vectors.
static void generateBezierVertices(float torusRadius, float circleRadius, float *vertices)
Generate torus vertices applying distortions to some of them.
static void calculateWireframeIndices(unsigned int circlesCount, unsigned int pointsPerCircleCount, unsigned int *indices)
Determines indices for glDrawElements() call for wireframed torus.
static void generateVertices(float torusRadius, float circleRadius, unsigned int circlesCount, unsigned int pointsPerCircleCount, float *vertices)
Generate vertices of the torus model.
GLsizei GLenum const void * indices
#define M_PI
The value of pi.
GLint GLint GLint GLint GLint x
static void calculatePatchData(unsigned int patchDensity, float *patchVertices, unsigned int *patchTriangleIndices)
Determines patch data for an instanced torus model.