GLUSAPI GLUSvoid GLUSAPIENTRY glusQuaternionRotateRzRyRxf(GLUSfloat quaternion[4], const GLUSfloat anglez, const GLUSfloat angley, const GLUSfloat anglex) { GLUSfloat rotZ[4]; GLUSfloat rotY[4]; GLUSfloat rotX[4]; glusQuaternionRotateRzf(rotZ, anglez); glusQuaternionRotateRyf(rotY, angley); glusQuaternionRotateRxf(rotX, anglex); glusQuaternionMultiplyQuaternionf(quaternion, rotZ, rotY); glusQuaternionMultiplyQuaternionf(quaternion, quaternion, rotX); }
/* * @author Pablo Alonso-Villaverde Roza * @author Norbert Nopper */ GLUSboolean GLUSAPIENTRY glusCreateTorusf(GLUSshape* shape, const GLUSfloat innerRadius, const GLUSfloat outerRadius, const GLUSushort numberSlices, const GLUSushort numberStacks) { // s, t = parametric values of the equations, in the range [0,1] GLUSfloat s = 0; GLUSfloat t = 0; // sIncr, tIncr are increment values aplied to s and t on each loop iteration to generate the torus GLUSfloat sIncr; GLUSfloat tIncr; // to store precomputed sin and cos values GLUSfloat cos2PIs, sin2PIs, cos2PIt, sin2PIt; GLUSuint numberVertices; GLUSuint numberIndices; // used later to help us calculating tangents vectors GLUSfloat helpVector[3] = { 0.0f, 1.0f, 0.0f }; GLUSfloat helpQuaternion[4]; GLUSfloat helpMatrix[16]; // indices for each type of buffer (of vertices, indices, normals...) GLUSuint indexVertices, indexNormals, indexTangents, indexTexCoords; GLUSuint indexIndices; // loop counters GLUSuint sideCount, faceCount; // used to generate the indices GLUSuint v0, v1, v2, v3; GLUSfloat torusRadius = (outerRadius - innerRadius) / 2.0f; GLUSfloat centerRadius = outerRadius - torusRadius; numberVertices = (numberStacks + 1) * (numberSlices + 1); numberIndices = numberStacks * numberSlices * 2 * 3; // 2 triangles per face * 3 indices per triangle if (numberSlices < 3 || numberStacks < 3 || numberVertices > GLUS_MAX_VERTICES || numberIndices > GLUS_MAX_INDICES) { return GLUS_FALSE; } if (!shape) { return GLUS_FALSE; } glusInitShapef(shape); shape->numberVertices = numberVertices; shape->numberIndices = numberIndices; shape->vertices = (GLUSfloat*) malloc(4 * numberVertices * sizeof(GLUSfloat)); shape->normals = (GLUSfloat*) malloc(3 * numberVertices * sizeof(GLUSfloat)); shape->tangents = (GLUSfloat*) malloc(3 * numberVertices * sizeof(GLUSfloat)); shape->texCoords = (GLUSfloat*) malloc(2 * numberVertices * sizeof(GLUSfloat)); shape->indices = (GLUSushort*) malloc(numberIndices * sizeof(GLUSushort)); if (!glusCheckShapef(shape)) { glusDestroyShapef(shape); return GLUS_FALSE; } sIncr = 1.0f / (GLUSfloat) numberSlices; tIncr = 1.0f / (GLUSfloat) numberStacks; // generate vertices and its attributes for (sideCount = 0; sideCount <= numberSlices; ++sideCount, s += sIncr) { // precompute some values cos2PIs = (GLUSfloat) cosf(2.0f * GLUS_PI * s); sin2PIs = (GLUSfloat) sinf(2.0f * GLUS_PI * s); t = 0.0f; for (faceCount = 0; faceCount <= numberStacks; ++faceCount, t += tIncr) { // precompute some values cos2PIt = (GLUSfloat) cosf(2.0f * GLUS_PI * t); sin2PIt = (GLUSfloat) sinf(2.0f * GLUS_PI * t); // generate vertex and stores it in the right position indexVertices = ((sideCount * (numberStacks + 1)) + faceCount) * 4; shape->vertices[indexVertices + 0] = (centerRadius + torusRadius * cos2PIt) * cos2PIs; shape->vertices[indexVertices + 1] = (centerRadius + torusRadius * cos2PIt) * sin2PIs; shape->vertices[indexVertices + 2] = torusRadius * sin2PIt; shape->vertices[indexVertices + 3] = 1.0f; // generate normal and stores it in the right position // NOTE: cos (2PIx) = cos (x) and sin (2PIx) = sin (x) so, we can use this formula // normal = {cos(2PIs)cos(2PIt) , sin(2PIs)cos(2PIt) ,sin(2PIt)} indexNormals = ((sideCount * (numberStacks + 1)) + faceCount) * 3; shape->normals[indexNormals + 0] = cos2PIs * cos2PIt; shape->normals[indexNormals + 1] = sin2PIs * cos2PIt; shape->normals[indexNormals + 2] = sin2PIt; // generate texture coordinates and stores it in the right position indexTexCoords = ((sideCount * (numberStacks + 1)) + faceCount) * 2; shape->texCoords[indexTexCoords + 0] = s; shape->texCoords[indexTexCoords + 1] = t; // use quaternion to get the tangent vector glusQuaternionRotateRzf(helpQuaternion, 360.0f * s); glusQuaternionGetMatrix4x4f(helpMatrix, helpQuaternion); indexTangents = ((sideCount * (numberStacks + 1)) + faceCount) * 3; glusMatrix4x4MultiplyVector3f(&shape->tangents[indexTangents], helpMatrix, helpVector); } } // generate indices indexIndices = 0; for (sideCount = 0; sideCount < numberSlices; ++sideCount) { for (faceCount = 0; faceCount < numberStacks; ++faceCount) { // get the number of the vertices for a face of the torus. They must be < numVertices v0 = ((sideCount * (numberStacks + 1)) + faceCount); v1 = (((sideCount + 1) * (numberStacks + 1)) + faceCount); v2 = (((sideCount + 1) * (numberStacks + 1)) + (faceCount + 1)); v3 = ((sideCount * (numberStacks + 1)) + (faceCount + 1)); // first triangle of the face, counter clock wise winding shape->indices[indexIndices++] = v0; shape->indices[indexIndices++] = v1; shape->indices[indexIndices++] = v2; // second triangle of the face, counter clock wise winding shape->indices[indexIndices++] = v0; shape->indices[indexIndices++] = v2; shape->indices[indexIndices++] = v3; } } if (!glusFinalizeShapef(shape)) { glusDestroyShapef(shape); return GLUS_FALSE; } return GLUS_TRUE; }