├── README.md ├── geometry_shader_explode ├── data │ ├── basicLight.frag │ ├── basicVertex.vert │ └── triangleExplode.geo ├── geometry_shader_explode.pde └── sphere.pde ├── geometry_shader_shrink ├── data │ ├── basicLight.frag │ ├── basicVertex.vert │ └── triangleShrinker.geo ├── geometry_shader_shrink.pde └── sphere.pde └── geometry_shader_tessellation ├── data ├── basicLight.frag ├── basicVertex.vert └── triangleDivider.geo ├── geometry_shader_tessellation.pde └── sphere.pde /README.md: -------------------------------------------------------------------------------- 1 | Geometry-shaders-Processing 2 | =========================== 3 | 4 | Examples of geometry shaders using Processing and GLGraphics 5 | 6 | More info at www.nachocossio.com/?p=214 7 | -------------------------------------------------------------------------------- /geometry_shader_explode/data/basicLight.frag: -------------------------------------------------------------------------------- 1 | varying vec4 vColor; 2 | varying vec3 posEye; 3 | varying vec3 normalEye; 4 | 5 | void main(void) 6 | { 7 | vec3 L = normalize(gl_LightSource[0].position.xyz - posEye); 8 | float Idiff = max(dot(normalEye,L), 0.0); 9 | gl_FragColor = vec4( vColor.rgb * Idiff, vColor.a); 10 | } 11 | -------------------------------------------------------------------------------- /geometry_shader_explode/data/basicVertex.vert: -------------------------------------------------------------------------------- 1 | varying vec3 Normal; 2 | varying vec4 v_Color; 3 | 4 | void main(void) 5 | { 6 | Normal = gl_Normal; 7 | v_Color = gl_Color; 8 | gl_Position = gl_Vertex; 9 | } -------------------------------------------------------------------------------- /geometry_shader_explode/data/triangleExplode.geo: -------------------------------------------------------------------------------- 1 | #version 120 2 | #extension GL_EXT_geometry_shader4: enable 3 | 4 | uniform float Explode; 5 | varying in vec3 Normal[3]; 6 | varying in vec4 v_Color[3]; 7 | varying out vec3 posEye; 8 | varying out vec3 normalEye; 9 | varying out vec4 vColor; 10 | 11 | vec4 V[3]; 12 | 13 | void ProduceVertex( int v ){ 14 | vec3 face_normal = normalize ( cross (V[2].xyz - V[0].xyz, V[1].xyz - V[0].xyz)); 15 | vec4 newPos = V[v] + vec4(Explode*face_normal,0.); 16 | 17 | normalEye = gl_NormalMatrix * face_normal; 18 | posEye = (gl_ModelViewMatrix * newPos ).xyz; 19 | vColor = v_Color[v]; 20 | gl_Position = gl_ModelViewProjectionMatrix *newPos ; 21 | EmitVertex(); 22 | } 23 | 24 | void main() 25 | { 26 | V[0] = gl_PositionIn[0]; 27 | V[1] = gl_PositionIn[1]; 28 | V[2] = gl_PositionIn[2]; 29 | ProduceVertex(0); 30 | ProduceVertex(1); 31 | ProduceVertex(2); 32 | EndPrimitive(); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /geometry_shader_explode/geometry_shader_explode.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Geometry shader explode by Nacho Cossio 3 | www.nachocossio.com 4 | https://github.com/kosowski 5 | 6 | This sketch illustrates how to calculate primitive’s normals and displace its vertices 7 | in this direction using GLSL geometry shaders. 8 | 9 | Mouse controls the light position. 10 | 11 | Built with Processing 1.5.1 and GLGraphics 1.0 12 | */ 13 | import codeanticode.glgraphics.*; 14 | import processing.opengl.PGraphicsOpenGL; 15 | 16 | GLModel sphere1; 17 | GLSLShader vertexShader; 18 | 19 | boolean useShader = true; 20 | 21 | void setup() { 22 | size(800, 800, GLConstants.GLGRAPHICS); 23 | vertexShader = new GLSLShader(this, "basicVertex.vert", "triangleExplode.geo", "basicLight.frag"); 24 | int n = vertexShader.getMaxOutVertCount(); 25 | println("max vertices "+n); 26 | // it is necessary to init the primitive used and the max number of 27 | //vertices that the geometry shader can output 28 | vertexShader.setupGeometryShader(TRIANGLES, TRIANGLES, 3); 29 | //If the sketch runs too slow, the number of polygons used for the sphere can be lowered (first parameter) 30 | sphere1 = createSphere(100, 200); 31 | sphere1.setTint(242,231, 105); 32 | } 33 | 34 | void draw() { 35 | background(0); 36 | GLGraphics renderer = (GLGraphics)g; 37 | renderer.beginGL(); 38 | vertexShader.start(); 39 | vertexShader.setFloatUniform("Explode", 60 * (1 + sin(millis() * 0.002))); 40 | 41 | noLights(); 42 | pointLight(255, 255, 255, mouseX, mouseY, 600); 43 | translate(width/2, height/2, 0); 44 | renderer.model(sphere1); 45 | 46 | vertexShader.stop(); 47 | renderer.endGL(); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /geometry_shader_explode/sphere.pde: -------------------------------------------------------------------------------- 1 | float SINCOS_PRECISION = 0.5; 2 | int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION); 3 | 4 | GLModel createSphere(int detail, float radius) 5 | { 6 | float[] cx, cz, sphereX, sphereY, sphereZ; 7 | float sinLUT[]; 8 | float cosLUT[]; 9 | float delta, angle_step, angle; 10 | int vertCount, currVert; 11 | float r; 12 | int v1, v11, v2, voff; 13 | ArrayList vertices; 14 | ArrayList normals; 15 | 16 | sinLUT = new float[SINCOS_LENGTH]; 17 | cosLUT = new float[SINCOS_LENGTH]; 18 | 19 | for (int i = 0; i < SINCOS_LENGTH; i++) 20 | { 21 | sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION); 22 | cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION); 23 | } 24 | 25 | delta = float(SINCOS_LENGTH / detail); 26 | cx = new float[detail]; 27 | cz = new float[detail]; 28 | 29 | // Calc unit circle in XZ plane 30 | for (int i = 0; i < detail; i++) 31 | { 32 | cx[i] = -cosLUT[(int) (i * delta) % SINCOS_LENGTH]; 33 | cz[i] = sinLUT[(int) (i * delta) % SINCOS_LENGTH]; 34 | } 35 | 36 | // Computing vertexlist vertexlist starts at south pole 37 | vertCount = detail * (detail - 1) + 2; 38 | currVert = 0; 39 | 40 | // Re-init arrays to store vertices 41 | sphereX = new float[vertCount]; 42 | sphereY = new float[vertCount]; 43 | sphereZ = new float[vertCount]; 44 | angle_step = (SINCOS_LENGTH * 0.5f) / detail; 45 | angle = angle_step; 46 | 47 | // Step along Y axis 48 | for (int i = 1; i < detail; i++) 49 | { 50 | float curradius = sinLUT[(int) angle % SINCOS_LENGTH]; 51 | float currY = -cosLUT[(int) angle % SINCOS_LENGTH]; 52 | for (int j = 0; j < detail; j++) 53 | { 54 | sphereX[currVert] = cx[j] * curradius; 55 | sphereY[currVert] = currY; 56 | sphereZ[currVert++] = cz[j] * curradius; 57 | } 58 | angle += angle_step; 59 | } 60 | 61 | vertices = new ArrayList(); 62 | normals = new ArrayList(); 63 | 64 | r = radius; 65 | 66 | // Add the southern cap 67 | for (int i = 0; i < detail; i++) 68 | { 69 | addVertex(vertices, normals, 0.0, -r, 0.0); 70 | addVertex(vertices, normals, sphereX[i] * r, sphereY[i] * r, sphereZ[i] * r); 71 | } 72 | addVertex(vertices, normals, 0.0, -r, 0.0); 73 | addVertex(vertices, normals, sphereX[0] * r, sphereY[0] * r, sphereZ[0] * r); 74 | 75 | // Middle rings 76 | voff = 0; 77 | for (int i = 2; i < detail; i++) 78 | { 79 | v1 = v11 = voff; 80 | voff += detail; 81 | v2 = voff; 82 | for (int j = 0; j < detail; j++) 83 | { 84 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1++] * r); 85 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2++] * r); 86 | } 87 | 88 | // Close each ring 89 | v1 = v11; 90 | v2 = voff; 91 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1] * r); 92 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 93 | } 94 | 95 | // Add the northern cap 96 | for (int i = 0; i < detail; i++) 97 | { 98 | v2 = voff + i; 99 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 100 | addVertex(vertices, normals, 0, r, 0); 101 | } 102 | addVertex(vertices, normals, sphereX[voff] * r, sphereY[voff] * r, sphereZ[voff] * r); 103 | 104 | 105 | GLModel model = new GLModel(this, vertices.size(), TRIANGLE_STRIP, GLModel.STATIC); 106 | 107 | // Sets the coordinates. 108 | model.updateVertices(vertices); 109 | 110 | // Sets the normals. 111 | model.initNormals(); 112 | model.updateNormals(normals); 113 | 114 | return model; 115 | } 116 | 117 | void addVertex(ArrayList vertices, ArrayList normals, float x, float y, float z) 118 | { 119 | PVector vert = new PVector(x, y, z); 120 | PVector vertNorm = PVector.div(vert, vert.mag()); 121 | vertices.add(vert); 122 | normals.add(vertNorm); 123 | } 124 | -------------------------------------------------------------------------------- /geometry_shader_shrink/data/basicLight.frag: -------------------------------------------------------------------------------- 1 | varying vec4 vColor; 2 | varying vec3 posEye; 3 | varying vec3 normalEye; 4 | 5 | void main(void) 6 | { 7 | vec3 L = normalize(gl_LightSource[0].position.xyz - posEye); 8 | float Idiff = max(dot(normalEye,L), 0.0); 9 | gl_FragColor = vec4( vColor.rgb * Idiff, vColor.a); 10 | } 11 | -------------------------------------------------------------------------------- /geometry_shader_shrink/data/basicVertex.vert: -------------------------------------------------------------------------------- 1 | varying vec3 Normal; 2 | varying vec4 v_Color; 3 | 4 | void main(void) 5 | { 6 | Normal = gl_Normal; 7 | v_Color = gl_Color; 8 | gl_Position = gl_Vertex; 9 | } -------------------------------------------------------------------------------- /geometry_shader_shrink/data/triangleShrinker.geo: -------------------------------------------------------------------------------- 1 | #version 120 2 | #extension GL_EXT_geometry_shader4: enable 3 | 4 | uniform float Shrink; 5 | varying in vec3 Normal[3]; 6 | varying in vec4 v_Color[3]; 7 | varying out vec3 posEye; 8 | varying out vec3 normalEye; 9 | varying out vec4 vColor; 10 | 11 | 12 | vec4 V[3]; 13 | vec4 CG; 14 | 15 | void ProduceVertex( int v ){ 16 | normalEye = gl_NormalMatrix * Normal[v]; 17 | posEye = (gl_ModelViewMatrix * ( CG + Shrink * (V[v] - CG) )).xyz; 18 | vColor = v_Color[v]; 19 | gl_Position = gl_ModelViewProjectionMatrix * ( CG + Shrink * (V[v] - CG) ); 20 | EmitVertex(); 21 | } 22 | 23 | void main(){ 24 | 25 | V[0] = gl_PositionIn[0]; 26 | V[1] = gl_PositionIn[1]; 27 | V[2] = gl_PositionIn[2]; 28 | CG = ( V[0] + V[1] + V[2] ) / 3.; 29 | ProduceVertex(0); 30 | ProduceVertex(1); 31 | ProduceVertex(2); 32 | EndPrimitive(); 33 | 34 | } -------------------------------------------------------------------------------- /geometry_shader_shrink/geometry_shader_shrink.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Geometry shader shrink by Nacho Cossio 3 | www.nachocossio.com 4 | https://github.com/kosowski 5 | 6 | This example shows how to manipulate primitives, triangles in this case, using a GLSL geometry shader. 7 | The centre point of the triangle is calculated and the vertices moved towards it, creating a shrink effect. 8 | 9 | Mouse controls the light position. 10 | 11 | Built with Processing 1.5.1 and GLGraphics 1.0 12 | */ 13 | 14 | import codeanticode.glgraphics.*; 15 | import processing.opengl.PGraphicsOpenGL; 16 | 17 | GLModel sphere1; 18 | GLSLShader vertexShader; 19 | 20 | void setup() { 21 | size(800, 800, GLConstants.GLGRAPHICS); 22 | vertexShader = new GLSLShader(this, "basicVertex.vert", "triangleShrinker.geo", "basicLight.frag"); 23 | int n = vertexShader.getMaxOutVertCount(); 24 | println("max vertices "+n); 25 | // it is necessary to init the primitive used and the max number of 26 | //vertices that the geometry shader can output 27 | vertexShader.setupGeometryShader(TRIANGLES, TRIANGLES, 3); 28 | sphere1 = createSphere(20, 200); 29 | sphere1.setTint(242,231, 105); 30 | } 31 | 32 | void draw() { 33 | background(0); 34 | GLGraphics renderer = (GLGraphics)g; 35 | renderer.beginGL(); 36 | 37 | vertexShader.start(); 38 | vertexShader.setFloatUniform("Shrink", 2 * (1 + sin(millis() * 0.001))); 39 | 40 | noLights(); 41 | pointLight(255, 255, 255, mouseX, mouseY, 600); 42 | translate(width/2, height/2, 0); 43 | renderer.model(sphere1); 44 | 45 | vertexShader.stop(); 46 | renderer.endGL(); 47 | } 48 | -------------------------------------------------------------------------------- /geometry_shader_shrink/sphere.pde: -------------------------------------------------------------------------------- 1 | float SINCOS_PRECISION = 0.5; 2 | int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION); 3 | 4 | GLModel createSphere(int detail, float radius) 5 | { 6 | float[] cx, cz, sphereX, sphereY, sphereZ; 7 | float sinLUT[]; 8 | float cosLUT[]; 9 | float delta, angle_step, angle; 10 | int vertCount, currVert; 11 | float r; 12 | int v1, v11, v2, voff; 13 | ArrayList vertices; 14 | ArrayList normals; 15 | 16 | sinLUT = new float[SINCOS_LENGTH]; 17 | cosLUT = new float[SINCOS_LENGTH]; 18 | 19 | for (int i = 0; i < SINCOS_LENGTH; i++) 20 | { 21 | sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION); 22 | cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION); 23 | } 24 | 25 | delta = float(SINCOS_LENGTH / detail); 26 | cx = new float[detail]; 27 | cz = new float[detail]; 28 | 29 | // Calc unit circle in XZ plane 30 | for (int i = 0; i < detail; i++) 31 | { 32 | cx[i] = -cosLUT[(int) (i * delta) % SINCOS_LENGTH]; 33 | cz[i] = sinLUT[(int) (i * delta) % SINCOS_LENGTH]; 34 | } 35 | 36 | // Computing vertexlist vertexlist starts at south pole 37 | vertCount = detail * (detail - 1) + 2; 38 | currVert = 0; 39 | 40 | // Re-init arrays to store vertices 41 | sphereX = new float[vertCount]; 42 | sphereY = new float[vertCount]; 43 | sphereZ = new float[vertCount]; 44 | angle_step = (SINCOS_LENGTH * 0.5f) / detail; 45 | angle = angle_step; 46 | 47 | // Step along Y axis 48 | for (int i = 1; i < detail; i++) 49 | { 50 | float curradius = sinLUT[(int) angle % SINCOS_LENGTH]; 51 | float currY = -cosLUT[(int) angle % SINCOS_LENGTH]; 52 | for (int j = 0; j < detail; j++) 53 | { 54 | sphereX[currVert] = cx[j] * curradius; 55 | sphereY[currVert] = currY; 56 | sphereZ[currVert++] = cz[j] * curradius; 57 | } 58 | angle += angle_step; 59 | } 60 | 61 | vertices = new ArrayList(); 62 | normals = new ArrayList(); 63 | 64 | r = radius; 65 | 66 | // Add the southern cap 67 | for (int i = 0; i < detail; i++) 68 | { 69 | addVertex(vertices, normals, 0.0, -r, 0.0); 70 | addVertex(vertices, normals, sphereX[i] * r, sphereY[i] * r, sphereZ[i] * r); 71 | } 72 | addVertex(vertices, normals, 0.0, -r, 0.0); 73 | addVertex(vertices, normals, sphereX[0] * r, sphereY[0] * r, sphereZ[0] * r); 74 | 75 | // Middle rings 76 | voff = 0; 77 | for (int i = 2; i < detail; i++) 78 | { 79 | v1 = v11 = voff; 80 | voff += detail; 81 | v2 = voff; 82 | for (int j = 0; j < detail; j++) 83 | { 84 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1++] * r); 85 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2++] * r); 86 | } 87 | 88 | // Close each ring 89 | v1 = v11; 90 | v2 = voff; 91 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1] * r); 92 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 93 | } 94 | 95 | // Add the northern cap 96 | for (int i = 0; i < detail; i++) 97 | { 98 | v2 = voff + i; 99 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 100 | addVertex(vertices, normals, 0, r, 0); 101 | } 102 | addVertex(vertices, normals, sphereX[voff] * r, sphereY[voff] * r, sphereZ[voff] * r); 103 | 104 | 105 | GLModel model = new GLModel(this, vertices.size(), TRIANGLE_STRIP, GLModel.STATIC); 106 | 107 | // Sets the coordinates. 108 | model.updateVertices(vertices); 109 | 110 | // Sets the normals. 111 | model.initNormals(); 112 | model.updateNormals(normals); 113 | 114 | return model; 115 | } 116 | 117 | void addVertex(ArrayList vertices, ArrayList normals, float x, float y, float z) 118 | { 119 | PVector vert = new PVector(x, y, z); 120 | PVector vertNorm = PVector.div(vert, vert.mag()); 121 | vertices.add(vert); 122 | normals.add(vertNorm); 123 | } 124 | -------------------------------------------------------------------------------- /geometry_shader_tessellation/data/basicLight.frag: -------------------------------------------------------------------------------- 1 | varying vec4 vColor; 2 | varying vec3 posEye; 3 | varying vec3 normalEye; 4 | 5 | void main(void) 6 | { 7 | vec3 L = normalize(gl_LightSource[0].position.xyz - posEye); 8 | float Idiff = max(dot(normalEye,L), 0.0); 9 | gl_FragColor = vec4( vColor.rgb * Idiff, vColor.a); 10 | } 11 | -------------------------------------------------------------------------------- /geometry_shader_tessellation/data/basicVertex.vert: -------------------------------------------------------------------------------- 1 | varying vec3 Normal; 2 | varying vec4 v_Color; 3 | 4 | void main(void) 5 | { 6 | Normal = gl_Normal; 7 | v_Color = gl_Color; 8 | gl_Position = gl_Vertex; 9 | } -------------------------------------------------------------------------------- /geometry_shader_tessellation/data/triangleDivider.geo: -------------------------------------------------------------------------------- 1 | #version 120 2 | #extension GL_EXT_geometry_shader4: enable 3 | 4 | 5 | varying in vec3 Normal[3]; 6 | varying in vec4 v_Color[3]; 7 | varying out vec3 posEye; 8 | varying out vec3 normalEye; 9 | varying out vec4 vColor; 10 | 11 | vec4 V[4]; 12 | 13 | void ProduceVertex( int v , vec3 n){ 14 | if(v==3){ 15 | vColor = v_Color[2];} 16 | else{ 17 | vColor = v_Color[v];} 18 | 19 | gl_Position = gl_ModelViewProjectionMatrix * V[v]; 20 | normalEye = gl_NormalMatrix * n; 21 | posEye = (gl_ModelViewMatrix * V[v]).xyz; 22 | 23 | EmitVertex(); 24 | } 25 | 26 | void main(){ 27 | 28 | V[0] = normalize(gl_PositionIn[0]); 29 | V[1] = normalize(gl_PositionIn[1]); 30 | V[2] = normalize(gl_PositionIn[2]); 31 | V[3] = normalize(V[1] + V[2]); 32 | 33 | vec3 normal = normalize ( cross (V[3].xyz - V[0].xyz, V[1].xyz - V[0].xyz)); 34 | ProduceVertex(0, normal); 35 | ProduceVertex(1, normal); 36 | ProduceVertex(3, normal); 37 | normal = normalize ( cross (V[2].xyz - V[0].xyz, V[3].xyz - V[0].xyz) ); 38 | ProduceVertex(0, normal); 39 | ProduceVertex(3, normal ); 40 | ProduceVertex(2, normal ); 41 | EndPrimitive(); 42 | } -------------------------------------------------------------------------------- /geometry_shader_tessellation/geometry_shader_tessellation.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Geometry shader tessellation by Nacho Cossio 3 | www.nachocossio.com 4 | https://github.com/kosowski 5 | 6 | This sketch shows how to add new vertices and primitives using GLLSL geometry shaders. 7 | Each triangle is tessellated by adding a new vertex and defining two triangles with these four points. 8 | 9 | Press any key to turn the shader on/off and see the difference. 10 | 11 | Mouse controls the light position. 12 | 13 | Built with Processing 1.5.1 and GLGraphics 1.0 14 | */ 15 | import codeanticode.glgraphics.*; 16 | import processing.opengl.PGraphicsOpenGL; 17 | import javax.media.opengl.GL; 18 | 19 | GLModel sphere1; 20 | GLSLShader vertexShader; 21 | 22 | boolean useShader = true; 23 | 24 | void setup() { 25 | size(800, 800, GLConstants.GLGRAPHICS); 26 | vertexShader = new GLSLShader(this, "basicVertex.vert", "triangleDivider.geo", "basicLight.frag"); 27 | int n = vertexShader.getMaxOutVertCount(); 28 | println("max vertices "+n); 29 | // it is necessary to init the primitive used and the max number of 30 | //vertices that the geometry shader can output 31 | vertexShader.setupGeometryShader(TRIANGLES, TRIANGLES, n); 32 | sphere1 = createSphere(30, 200); 33 | sphere1.setTint(242,231, 105); 34 | } 35 | 36 | void draw() { 37 | background(0); 38 | GLGraphics renderer = (GLGraphics)g; 39 | GL gl = renderer.beginGL(); 40 | if (useShader) 41 | vertexShader.start(); 42 | else 43 | // use per vertex lighting to see the difference 44 | gl.glShadeModel(GL.GL_FLAT); 45 | 46 | noLights(); 47 | pointLight(255,255,255,mouseX,mouseY,800); 48 | translate(width/2, height/2,0); 49 | renderer.model(sphere1); 50 | 51 | if (useShader)vertexShader.stop(); 52 | renderer.endGL(); 53 | } 54 | 55 | 56 | void keyPressed() { 57 | useShader = ! useShader; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /geometry_shader_tessellation/sphere.pde: -------------------------------------------------------------------------------- 1 | float SINCOS_PRECISION = 0.5; 2 | int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION); 3 | 4 | GLModel createSphere(int detail, float radius) 5 | { 6 | float[] cx, cz, sphereX, sphereY, sphereZ; 7 | float sinLUT[]; 8 | float cosLUT[]; 9 | float delta, angle_step, angle; 10 | int vertCount, currVert; 11 | float r; 12 | int v1, v11, v2, voff; 13 | ArrayList vertices; 14 | ArrayList normals; 15 | 16 | sinLUT = new float[SINCOS_LENGTH]; 17 | cosLUT = new float[SINCOS_LENGTH]; 18 | 19 | for (int i = 0; i < SINCOS_LENGTH; i++) 20 | { 21 | sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION); 22 | cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION); 23 | } 24 | 25 | delta = float(SINCOS_LENGTH / detail); 26 | cx = new float[detail]; 27 | cz = new float[detail]; 28 | 29 | // Calc unit circle in XZ plane 30 | for (int i = 0; i < detail; i++) 31 | { 32 | cx[i] = -cosLUT[(int) (i * delta) % SINCOS_LENGTH]; 33 | cz[i] = sinLUT[(int) (i * delta) % SINCOS_LENGTH]; 34 | } 35 | 36 | // Computing vertexlist vertexlist starts at south pole 37 | vertCount = detail * (detail - 1) + 2; 38 | currVert = 0; 39 | 40 | // Re-init arrays to store vertices 41 | sphereX = new float[vertCount]; 42 | sphereY = new float[vertCount]; 43 | sphereZ = new float[vertCount]; 44 | angle_step = (SINCOS_LENGTH * 0.5f) / detail; 45 | angle = angle_step; 46 | 47 | // Step along Y axis 48 | for (int i = 1; i < detail; i++) 49 | { 50 | float curradius = sinLUT[(int) angle % SINCOS_LENGTH]; 51 | float currY = -cosLUT[(int) angle % SINCOS_LENGTH]; 52 | for (int j = 0; j < detail; j++) 53 | { 54 | sphereX[currVert] = cx[j] * curradius; 55 | sphereY[currVert] = currY; 56 | sphereZ[currVert++] = cz[j] * curradius; 57 | } 58 | angle += angle_step; 59 | } 60 | 61 | vertices = new ArrayList(); 62 | normals = new ArrayList(); 63 | 64 | r = radius; 65 | 66 | // Add the southern cap 67 | for (int i = 0; i < detail; i++) 68 | { 69 | addVertex(vertices, normals, 0.0, -r, 0.0); 70 | addVertex(vertices, normals, sphereX[i] * r, sphereY[i] * r, sphereZ[i] * r); 71 | } 72 | addVertex(vertices, normals, 0.0, -r, 0.0); 73 | addVertex(vertices, normals, sphereX[0] * r, sphereY[0] * r, sphereZ[0] * r); 74 | 75 | // Middle rings 76 | voff = 0; 77 | for (int i = 2; i < detail; i++) 78 | { 79 | v1 = v11 = voff; 80 | voff += detail; 81 | v2 = voff; 82 | for (int j = 0; j < detail; j++) 83 | { 84 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1++] * r); 85 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2++] * r); 86 | } 87 | 88 | // Close each ring 89 | v1 = v11; 90 | v2 = voff; 91 | addVertex(vertices, normals, sphereX[v1] * r, sphereY[v1] * r, sphereZ[v1] * r); 92 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 93 | } 94 | 95 | // Add the northern cap 96 | for (int i = 0; i < detail; i++) 97 | { 98 | v2 = voff + i; 99 | addVertex(vertices, normals, sphereX[v2] * r, sphereY[v2] * r, sphereZ[v2] * r); 100 | addVertex(vertices, normals, 0, r, 0); 101 | } 102 | addVertex(vertices, normals, sphereX[voff] * r, sphereY[voff] * r, sphereZ[voff] * r); 103 | 104 | 105 | GLModel model = new GLModel(this, vertices.size(), TRIANGLE_STRIP, GLModel.STATIC); 106 | 107 | // Sets the coordinates. 108 | model.updateVertices(vertices); 109 | 110 | // Sets the normals. 111 | model.initNormals(); 112 | model.updateNormals(normals); 113 | 114 | return model; 115 | } 116 | 117 | void addVertex(ArrayList vertices, ArrayList normals, float x, float y, float z) 118 | { 119 | PVector vert = new PVector(x, y, z); 120 | PVector vertNorm = PVector.div(vert, vert.mag()); 121 | vertices.add(vert); 122 | normals.add(vertNorm); 123 | } 124 | --------------------------------------------------------------------------------