21 #include "TorusModel.h"
24 #include "Mathematics.h"
32 unsigned int normalSize = 3;
33 unsigned int index = 0;
35 for (
unsigned int horizontalIndex = 0; horizontalIndex < circlesCount; ++horizontalIndex)
38 float phi = (
float) horizontalIndex * 2.0
f *
M_PI / circlesCount;
40 Vec3f horizontalTangent = {-sinf(phi), 0.0f, cosf(phi)};
42 for (
unsigned int verticalIndex = 0; verticalIndex < pointsPerCircleCount; ++verticalIndex)
45 float theta = (
float) verticalIndex * 2.0
f *
M_PI / pointsPerCircleCount;
47 Vec3f verticalTangent = {-cosf(phi) * sinf(theta), cosf(theta), -sinf(phi) * sinf(theta)};
49 assert(index < circlesCount * pointsPerCircleCount * normalSize);
51 normals[index++] = horizontalTangent.
z * verticalTangent.
y - horizontalTangent.
y * verticalTangent.
z;
52 normals[index++] = horizontalTangent.
x * verticalTangent.
z - horizontalTangent.
z * verticalTangent.
x;
53 normals[index++] = horizontalTangent.
y * verticalTangent.
x - horizontalTangent.
x * verticalTangent.
y;
60 if (controlPointsIndices == NULL)
62 LOGE(
"Cannot use null pointer while calculating control points indices.");
68 const unsigned int pointsPerCircleCount = 12;
69 const unsigned int circlesCount = 12;
70 const unsigned int torusVerticesCount = pointsPerCircleCount * circlesCount;
73 unsigned int startIndex = 0;
75 unsigned int currentCircle = 0;
78 unsigned int index = 0;
81 for (
unsigned int instanceIndex = 0; instanceIndex < patchInstancesCount; ++instanceIndex)
84 for (
unsigned int x = 0;
x < patchDimension; ++
x)
87 currentCircle = startIndex / pointsPerCircleCount;
90 for (
unsigned int y = 0;
y < patchDimension; ++
y)
92 unsigned int currentIndex = startIndex +
y;
95 if (currentIndex >= pointsPerCircleCount * (currentCircle + 1))
97 currentIndex -= pointsPerCircleCount;
100 controlPointsIndices[index++] = currentIndex;
102 assert(index <= controlPointsIndicesCount);
106 startIndex += pointsPerCircleCount;
109 if (startIndex >= torusVerticesCount)
111 startIndex -= torusVerticesCount;
116 startIndex -= pointsPerCircleCount;
119 if (currentCircle == 0)
121 startIndex += patchDimension - 1;
127 if (patchVertices == NULL || patchTriangleIndices == NULL)
129 LOGE(
"Cannot use null pointers while calculating patch data.");
135 const unsigned int patchComponentsCount = patchDensity * patchDensity * 2;
137 const unsigned int patchTriangleIndicesCount = (patchDensity - 1) * (patchDensity - 1) * 6;
140 const unsigned int uvComponentsCount = 2;
142 const unsigned int verticesPerQuadCount = 6;
145 unsigned int uvIndex = 0;
147 unsigned int triangleVertexIndex = 0;
149 for (
unsigned int x = 0;
x < patchDensity; ++
x)
152 float u = (
float)
x / (patchDensity - 1);
154 for (
unsigned int y = 0;
y < patchDensity; ++
y)
157 float v = (
float)
y / (patchDensity - 1);
159 patchVertices[uvIndex++] = u;
160 patchVertices[uvIndex++] =
v;
162 assert(uvIndex <= patchComponentsCount);
179 for (
unsigned int x = 0;
x < patchDensity - 1; ++
x)
181 for (
unsigned int y = 0;
y < patchDensity - 1; ++
y)
183 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x +
y;
184 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x + y + 1;
185 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y;
187 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y;
188 patchTriangleIndices[triangleVertexIndex++] = patchDensity *
x + y + 1;
189 patchTriangleIndices[triangleVertexIndex++] = patchDensity * (
x + 1) + y + 1;
191 assert(triangleVertexIndex <= patchTriangleIndicesCount);
198 const unsigned int torusVerticesCount = circlesCount * pointsPerCircleCount;
200 for (
unsigned int i = 0; i < circlesCount; ++i)
202 for (
unsigned int j = 0; j < pointsPerCircleCount; ++j)
205 unsigned int lineStart = i * pointsPerCircleCount + j;
207 unsigned int horizontalEnd = (i + 1) * pointsPerCircleCount + j;
209 unsigned int verticalEnd = i * pointsPerCircleCount + j + 1;
212 if (horizontalEnd >= torusVerticesCount)
214 horizontalEnd -= torusVerticesCount;
218 if (verticalEnd >= (i + 1) * pointsPerCircleCount)
220 verticalEnd -= pointsPerCircleCount;
224 indices[(i * pointsPerCircleCount + j) * 4 ] = lineStart;
225 indices[(i * pointsPerCircleCount + j) * 4 + 1] = horizontalEnd;
228 indices[(i * pointsPerCircleCount + j) * 4 + 2] = lineStart;
229 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;
270 const unsigned int torusVerticesCount = circlesCount * pointsPerCircleCount;
271 const unsigned int torusIndicesCount = (2 * circlesCount + 1) * pointsPerCircleCount + 1;
274 unsigned int currentIndex = 0;
276 indices[counter++] = currentIndex;
278 bool isLastStrip =
false;
280 for (
unsigned int stripIndex = 0; stripIndex < pointsPerCircleCount; ++stripIndex)
282 assert(currentIndex == stripIndex);
287 isLastStrip = currentIndex >= pointsPerCircleCount;
289 assert(counter < torusIndicesCount);
291 indices[counter++] = isLastStrip ? (currentIndex - pointsPerCircleCount) : currentIndex;
293 for (
unsigned int circleIndex = 0; circleIndex < circlesCount; ++circleIndex)
295 currentIndex = currentIndex + pointsPerCircleCount - 1;
297 if (currentIndex >= torusVerticesCount)
299 currentIndex -= torusVerticesCount;
302 assert(counter < torusIndicesCount);
304 indices[counter++] = currentIndex;
308 assert(counter < torusIndicesCount);
310 indices[counter++] = isLastStrip ? currentIndex - pointsPerCircleCount : currentIndex;
317 if (vertices == NULL)
319 LOGE(
"Cannot use null pointer while calculating torus vertices.");
325 const float kappa = 4.0f * (sqrtf(2.0
f) - 1.0f) / 3.0
f;
327 const float alpha = atanf(kappa);
329 const float distortedCircleRadius = circleRadius * sqrt(1.0
f + kappa * kappa);
331 const float distortedTorusRadius = torusRadius * sqrt(1.0
f + kappa * kappa);
333 const int quadrantsCount = 4;
335 const int circlesCount = 12;
337 const int pointsPerCircleCount = 12;
345 unsigned int componentIndex = 0;
348 for (
int horizontalIndex = 0; horizontalIndex < circlesCount; ++horizontalIndex)
351 const int currentCircleModulo = horizontalIndex % (quadrantsCount - 1);
354 float currentTorusRadius;
355 float currentCircleRadius;
359 switch (currentCircleModulo)
363 currentTorusRadius = torusRadius;
368 currentTorusRadius = distortedTorusRadius;
369 currentPhi = phi + alpha;
373 phi = (
float) (horizontalIndex + 1) *
M_PI / (2 * (quadrantsCount - 1));
374 currentTorusRadius = distortedTorusRadius;
375 currentPhi = phi - alpha;
379 for (
int verticalIndex = 0; verticalIndex < pointsPerCircleCount; ++verticalIndex)
382 const int currentPointModulo = verticalIndex % (quadrantsCount - 1);
384 switch (currentPointModulo)
388 currentCircleRadius = circleRadius;
389 currentTheta = theta;
393 currentCircleRadius = distortedCircleRadius;
394 currentTheta = theta + alpha;
398 theta = (
float) (verticalIndex + 1) *
M_PI / (2 * (quadrantsCount - 1));
399 currentCircleRadius = distortedCircleRadius;
400 currentTheta = theta - alpha;
404 vertices[componentIndex++] = (currentTorusRadius + currentCircleRadius * cosf(currentTheta)) * cosf(currentPhi);
405 vertices[componentIndex++] = currentCircleRadius * sinf(currentTheta);
406 vertices[componentIndex++] = (currentTorusRadius + currentCircleRadius * cosf(currentTheta)) * sinf(currentPhi);
407 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.
A 3D floating point vector.
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.