Drawing a Spherical Mesh
Wondering if any of you who are graphics whizzes on the Prime know how to implement a spherical mesh generator?
I tried to make a PPL version of the classical icosahedron mesh but the depth of recursion appears to flummox the prime. Here's the original OpenGL/C version that can be found in the redbook and other places:
Code:
//
// sphereMesh.c
//
// draws a sphercial mesh
//
#include <stdio.h>
#include <math.h>
#if !defined(__GLU_H__)
#if defined(WIN32)
#include <windows.h>
#include <GL/glu.h>
#elif defined(__MACH__)
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif
#endif // !__GL_H__
#define X .525731112119133606
#define Z .850650808352039932
static GLfloat vdata[12][3] = {
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
};
static GLuint tindices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
void normalize(GLfloat *a) {
GLfloat d=sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
a[0]/=d; a[1]/=d; a[2]/=d;
}
void drawtri(GLfloat *a, GLfloat *b, GLfloat *c, int div, float r) {
if (div<=0) {
glNormal3fv(a); glVertex3f(a[0]*r, a[1]*r, a[2]*r);
glNormal3fv(b); glVertex3f(b[0]*r, b[1]*r, b[2]*r);
glNormal3fv(c); glVertex3f(c[0]*r, c[1]*r, c[2]*r);
} else {
GLfloat ab[3], ac[3], bc[3];
for (int i=0;i<3;i++) {
ab[i]=(a[i]+b[i])/2;
ac[i]=(a[i]+c[i])/2;
bc[i]=(b[i]+c[i])/2;
}
normalize(ab); normalize(ac); normalize(bc);
drawtri(a, ab, ac, div-1, r);
drawtri(b, bc, ab, div-1, r);
drawtri(c, ac, bc, div-1, r);
drawtri(ab, bc, ac, div-1, r); //<--Comment this line and sphere looks really cool!
}
}
void drawsphere(int ndiv, float radius) {
glBegin(GL_TRIANGLES);
for (int i=0;i<20;i++)
drawtri(vdata[tindices[i][0]], vdata[tindices[i][1]], vdata[tindices[i][2]], ndiv, radius);
glEnd();
}
I'm assuming that the glNormal3fv calls can be converted to TRIANGLE calls on the Prime (although shading doesn't appear to be supported). But the program never gets that far -- it hangs somewhere in the drawtri recursion for values of "div" > 2 or 3.
Converted to PPL the equivalent of the above code would be
Code:
XX=.525731112119133606;
ZZ=.850650808352039932;
vdata={
{-XX, 0.0, ZZ}, {XX, 0.0, ZZ}, {-XX, 0.0, -ZZ}, {XX, 0.0, -ZZ},
{0.0, ZZ, XX}, {0.0, ZZ, -XX}, {0.0, -ZZ, XX}, {0.0, -ZZ, -XX},
{ZZ, XX, 0.0}, {-ZZ, XX, 0.0}, {ZZ, -XX, 0.0}, {-ZZ, -XX, 0.0}
};
tindices = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
drawSphere()
begin
local i,radius=50,ndiv=12;
local white;
white:=rgb(255,255,255);
dimgrob_p(G1,320,240,white);
for i from 1 to 20 do
drawtri(vdata(tindices(i,1)+1),
vdata(tindices(i,2)+1),
vdata(tindices(i,3)+1),ndiv,radius);
end;
blit_p(G0,G1);
end;
normalize(aa)
begin
local dd;
dd:=sqrt(aa(1)*aa(1)+aa(2)*aa(2)+aa(3)*aa(3));
aa(1):=aa(1)/dd; aa(2):=aa(2)/dd; aa(3):=aa(3)/dd;
return aa;
end;
drawtri(aa,bb,cc,div,r)
begin
local ab={},ac={},bc={};
local grey,i;
grey:=rgb(25,25,25);
if div <= 0 then
triangle_p(G1,{aa(1),aa(2),grey,aa(3)},{bb(1),bb(2),grey,bb(3)},{cc(1),cc(2),grey,cc(3)});
else
for i from 1 to 3 do
ab(i):=(aa(i)+bb(i))/2;
ac(i):=(aa(i)+cc(i))/2;
bc(i):=(bb(i)+cc(i))/2;
end;
ab:=normalize(ab);
ac:=normalize(ac);
bc:=normalize(bc);
drawtri(aa,ab,ac,div-1,r);
drawtri(bb,bc,ab,div-1,r);
drawtri(cc,ac,bc,div-1,r);
drawtri(ab,bc,ac,div-1,r);
end;
end;
It seems likely that I've botched the TRIANGLE command since I've never used it but, again, things seem to go bad before that point. BTW, the above is only a fragment. If you want to try it you'll need to embed it in a more complete program like Han's Graph3D.
Suggestions welcome. Or is this just beyond what we can expect the Prime to do at this point?
|