Drawing a Spherical Mesh - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: HP Prime (/forum-5.html) +--- Thread: Drawing a Spherical Mesh (/thread-480.html) Drawing a Spherical Mesh - jgreenb2 - 01-20-2014 08:07 PM 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  #include  #if !defined(__GLU_H__) #if defined(WIN32) #include  #include  #elif defined(__MACH__) #include  #else #include  #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? RE: Drawing a Spherical Mesh - Han - 01-20-2014 09:47 PM You can always insert a debug() statement into your program to determine if the HP Prime fails after a certain number of recursions. Code: `if div<4 then debug(); end;` You can also insert a debug() statement right after the triangle command and then abort the program. Then, at the command line, type: Code: `blit_p(G0,G1); freeze;` This will allow you to see if your code is drawing each triangle like you want. You can even skip debugging and just put: Code: `blit_p(G0,G1); WAIT(-1);` to see it draw each individual triangle (press a key to continue). RE: Drawing a Spherical Mesh - jgreenb2 - 01-20-2014 09:58 PM Han, Thanks. I've actually done most of those things. I'll try some of your other suggestions. However, the drawing isn't the issue (it may not be right) -- the recursion itself seems to get lost after a short while and the program hangs. Given the limited debugging environment on the Prime, I haven't been able to make much more progress. The real questions are these: Is there a known problem handling deep recursion on the Prime? What's the best way to implement something like a sphereical mesh? Simple tail recursion -- like a factorial -- appear to work without issue. But when div is large the Prime stack appears to lose its place and drawSphere won't terminate. RE: Drawing a Spherical Mesh - cyrille de brĂ©bisson - 01-20-2014 10:27 PM Hello, A couple of problems in your code... First, your coordinates are in cartesian coordinates, from -1 to 1... you should use triangle instead of triangle_p. Make sure that you set the xmin/xmax, ymin, ymax to -1, 1, -1, 1 if you want to see something... ndiv=12 correspond to a HUGE number of triangles. put it to 6 or so to get started and debug... it does work with 12, but takes a LOT of time... 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} }; 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,125,25);     if div <= 0 then         triangle({aa(1),aa(2),grey,aa(3)},{bb(1),bb(2),grey,bb(3)},{cc(1),cc(2),gre​y,cc(3)}); //kill;     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; export drawSphere() begin     local i,radius=50,ndiv=6;     local white;          white:=rgb(255,255,255);     dimgrob_p(G1,320,240,white); rect_p;     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;``` If it still does not work, it might be due to confusion on the triangle inputs with the other forms (for full 3D drawing). Since my version of the app is later than the one that you have, I do not remember exactly how it was before... you could try a form along the lines of: triangle(x1, y1, z2, x2, y2, z2, x3, y3, z3, c1, c2, c3); Cyrille RE: Drawing a Spherical Mesh - jgreenb2 - 01-21-2014 12:15 AM Cyrille, You're right on both counts...thanks. Also, I realized I wasn't scaling the vertices by the radius -- that didn't help either. The next step is to accumulate all the vertices into a matrix and execute a single TRIANGLE call with a transformation matrix, z-plane and perspective transform. We'll see how that goes BTW...TRIANGLE appears to always fill the triangles(?) I'd like to actually draw a mesh (edges, but no fill). Is this possible? RE: Drawing a Spherical Mesh - patrice - 01-21-2014 01:08 AM Quote:BTW...TRIANGLE appears to always fill the triangles(?) I'd like to actually draw a mesh (edges, but no fill). Is this possible? Draw each vertice using LINE. 3 LINEs for each TRIANGLE if you don't avoid duplicates. RE: Drawing a Spherical Mesh - patrice - 01-23-2014 10:11 PM Put this instead of your TRIANGLE command Code: ```    LINE(aa(1),aa(2),bb(1),bb(2),rgb(128+aa(1)*128,128+aa(2)*128,128+aa(3)*128)​);     LINE(bb(1),bb(2),cc(1),cc(2),rgb(128+bb(1)*128,128+bb(2)*128,128+bb(3)*128)​);     LINE(cc(1),cc(2),aa(1),aa(2),rgb(128+cc(1)*128,128+cc(2)*128,128+cc(3)*128)​);``` Note that the LINE command compute a color depending on coordinates. I did it because the TRIANCLE make a flat convex thing on screen. MY changed TRIANGLE Code: `triangle ({aa(1),aa(2),rgb(128+aa(1)*128,128+aa(2)*128,128+aa(3)*128),aa(3)},{bb(1),​bb(2),rgb(128+bb(1)*128,128+bb(2)*128,128+bb(3)*128),bb(3)},{cc(1),cc(2),rgb(128​+cc(1)*128,128+cc(2)*128,128+cc(3)*128),cc(3)});`