// Creates and returns a supershape object. // Based on Paul Bourke's POV-Ray implementation. // http://astronomy.swin.edu.au/~pbourke/povray/supershape/ static GLOBJECT * createSuperShape(const float *params) { const int resol1 = (int)params[SUPERSHAPE_PARAMS - 3]; const int resol2 = (int)params[SUPERSHAPE_PARAMS - 2]; // latitude 0 to pi/2 for no mirrored bottom // (latitudeBegin==0 for -pi/2 to pi/2 originally) const int latitudeBegin = resol2 / 4; const int latitudeEnd = resol2 / 2; // non-inclusive const int longitudeCount = resol1; const int latitudeCount = latitudeEnd - latitudeBegin; const long triangleCount = longitudeCount * latitudeCount * 2; const long vertices = triangleCount * 3; GLOBJECT *result; float baseColor[3]; int a, longitude, latitude; long currentVertex, currentQuad; result = newGLObject(vertices, 3, 1); if (result == NULL) return NULL; for (a = 0; a < 3; ++a) baseColor[a] = ((randomUInt() % 155) + 100) / 255.f; currentQuad = 0; currentVertex = 0; // longitude -pi to pi for (longitude = 0; longitude < longitudeCount; ++longitude) { // latitude 0 to pi/2 for (latitude = latitudeBegin; latitude < latitudeEnd; ++latitude) { float t1 = -PI + longitude * 2 * PI / resol1; float t2 = -PI + (longitude + 1) * 2 * PI / resol1; float p1 = -PI / 2 + latitude * 2 * PI / resol2; float p2 = -PI / 2 + (latitude + 1) * 2 * PI / resol2; float r0, r1, r2, r3; r0 = ssFunc(t1, params); r1 = ssFunc(p1, ¶ms[6]); r2 = ssFunc(t2, params); r3 = ssFunc(p2, ¶ms[6]); if (r0 != 0 && r1 != 0 && r2 != 0 && r3 != 0) { VECTOR3 pa, pb, pc, pd; VECTOR3 v1, v2, n; float ca; int i; //float lenSq, invLenSq; superShapeMap(&pa, r0, r1, t1, p1); superShapeMap(&pb, r2, r1, t2, p1); superShapeMap(&pc, r2, r3, t2, p2); superShapeMap(&pd, r0, r3, t1, p2); // kludge to set lower edge of the object to fixed level if (latitude == latitudeBegin + 1) pa.z = pb.z = 0; vector3Sub(&v1, &pb, &pa); vector3Sub(&v2, &pd, &pa); // Calculate normal with cross product. /* i j k i j * v1.x v1.y v1.z | v1.x v1.y * v2.x v2.y v2.z | v2.x v2.y */ n.x = v1.y * v2.z - v1.z * v2.y; n.y = v1.z * v2.x - v1.x * v2.z; n.z = v1.x * v2.y - v1.y * v2.x; /* Pre-normalization of the normals is disabled here because * they will be normalized anyway later due to automatic * normalization (GL_NORMALIZE). It is enabled because the * objects are scaled with glScale. */ /* lenSq = n.x * n.x + n.y * n.y + n.z * n.z; invLenSq = (float)(1 / sqrt(lenSq)); n.x *= invLenSq; n.y *= invLenSq; n.z *= invLenSq; */ ca = pa.z + 0.5f; for (i = currentVertex * 3; i < (currentVertex + 6) * 3; i += 3) { result->normalArray[i] = FIXED(n.x); result->normalArray[i + 1] = FIXED(n.y); result->normalArray[i + 2] = FIXED(n.z); } for (i = currentVertex * 4; i < (currentVertex + 6) * 4; i += 4) { int a, color[3]; for (a = 0; a < 3; ++a) { color[a] = (int)(ca * baseColor[a] * 255); if (color[a] > 255) color[a] = 255; } result->colorArray[i] = (GLubyte)color[0]; result->colorArray[i + 1] = (GLubyte)color[1]; result->colorArray[i + 2] = (GLubyte)color[2]; result->colorArray[i + 3] = 0; } result->vertexArray[currentVertex * 3] = FIXED(pa.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pa.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pa.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pb.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pd.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pb.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pc.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pc.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pc.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pd.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z); ++currentVertex; } // r0 && r1 && r2 && r3 ++currentQuad; } // latitude } // longitude // Set number of vertices in object to the actual amount created. result->count = currentVertex; return result; }
static GLOBJECT * createSuperShape(const float *params) { const int resol1 = (int)params[SUPERSHAPE_PARAMS - 3]; const int resol2 = (int)params[SUPERSHAPE_PARAMS - 2]; const int latitudeBegin = resol2 / 4; const int latitudeEnd = resol2 / 2; const int longitudeCount = resol1; const int latitudeCount = latitudeEnd - latitudeBegin; const long triangleCount = longitudeCount * latitudeCount * 2; const long vertices = triangleCount * 3; GLOBJECT *result; float baseColor[3]; int a, longitude, latitude; long currentVertex, currentQuad; result = newGLObject(vertices, 3, 1); if (result == NULL) return NULL; for (a = 0; a < 3; ++a) baseColor[a] = ((randomUInt() % 155) + 100) / 255.f; currentQuad = 0; currentVertex = 0; for (longitude = 0; longitude < longitudeCount; ++longitude) { for (latitude = latitudeBegin; latitude < latitudeEnd; ++latitude) { float t1 = -PI + longitude * 2 * PI / resol1; float t2 = -PI + (longitude + 1) * 2 * PI / resol1; float p1 = -PI / 2 + latitude * 2 * PI / resol2; float p2 = -PI / 2 + (latitude + 1) * 2 * PI / resol2; float r0, r1, r2, r3; r0 = ssFunc(t1, params); r1 = ssFunc(p1, ¶ms[6]); r2 = ssFunc(t2, params); r3 = ssFunc(p2, ¶ms[6]); if (r0 != 0 && r1 != 0 && r2 != 0 && r3 != 0) { VECTOR3 pa, pb, pc, pd; VECTOR3 v1, v2, n; float ca; int i; superShapeMap(&pa, r0, r1, t1, p1); superShapeMap(&pb, r2, r1, t2, p1); superShapeMap(&pc, r2, r3, t2, p2); superShapeMap(&pd, r0, r3, t1, p2); if (latitude == latitudeBegin + 1) pa.z = pb.z = 0; vector3Sub(&v1, &pb, &pa); vector3Sub(&v2, &pd, &pa); n.x = v1.y * v2.z - v1.z * v2.y; n.y = v1.z * v2.x - v1.x * v2.z; n.z = v1.x * v2.y - v1.y * v2.x; ca = pa.z + 0.5f; for (i = currentVertex * 3; i < (currentVertex + 6) * 3; i += 3) { result->normalArray[i] = FIXED(n.x); result->normalArray[i + 1] = FIXED(n.y); result->normalArray[i + 2] = FIXED(n.z); } for (i = currentVertex * 4; i < (currentVertex + 6) * 4; i += 4) { int a, color[3]; for (a = 0; a < 3; ++a) { color[a] = (int)(ca * baseColor[a] * 255); if (color[a] > 255) color[a] = 255; } result->colorArray[i] = (GLubyte)color[0]; result->colorArray[i + 1] = (GLubyte)color[1]; result->colorArray[i + 2] = (GLubyte)color[2]; result->colorArray[i + 3] = 0; } result->vertexArray[currentVertex * 3] = FIXED(pa.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pa.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pa.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pb.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pd.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pb.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pc.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pc.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pc.z); ++currentVertex; result->vertexArray[currentVertex * 3] = FIXED(pd.x); result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y); result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z); ++currentVertex; } ++currentQuad; } } result->count = currentVertex; return result; }