diff options
Diffstat (limited to 'js/lib/geom/shape-primitive.js')
-rw-r--r-- | js/lib/geom/shape-primitive.js | 463 |
1 files changed, 321 insertions, 142 deletions
diff --git a/js/lib/geom/shape-primitive.js b/js/lib/geom/shape-primitive.js index 34db60e8..e3ff9c06 100644 --- a/js/lib/geom/shape-primitive.js +++ b/js/lib/geom/shape-primitive.js | |||
@@ -32,106 +32,319 @@ POSSIBILITY OF SUCH DAMAGE. | |||
32 | var ShapePrimitive = {}; | 32 | var ShapePrimitive = {}; |
33 | 33 | ||
34 | ShapePrimitive.create = function(coords, normals, uvs, indices, primType, vertexCount) { | 34 | ShapePrimitive.create = function(coords, normals, uvs, indices, primType, vertexCount) { |
35 | var renderer = RDGE.globals.engine.getContext().renderer; | 35 | var renderer = RDGE.globals.engine.getContext().renderer; |
36 | 36 | ||
37 | // to setup a primitive you must define it | 37 | // to setup a primitive you must define it |
38 | // create a new primitive definition here to then fill out | 38 | // create a new primitive definition here to then fill out |
39 | var prim = new RDGE.rdgePrimitiveDefinition(); | 39 | var prim = new RDGE.rdgePrimitiveDefinition(); |
40 | 40 | ||
41 | // the vertex definition declares how the data will be delivered to the shader | 41 | // the vertex definition declares how the data will be delivered to the shader |
42 | // the position of an element in array determines which attribute in a shader the | 42 | // the position of an element in array determines which attribute in a shader the |
43 | // data is bound to | 43 | // data is bound to |
44 | prim.vertexDefinition = { | 44 | prim.vertexDefinition = { |
45 | // this shows two ways to map this data to an attribute | 45 | // this shows two ways to map this data to an attribute |
46 | "vert":{'type':renderer.VS_ELEMENT_POS, 'bufferIndex':0, 'bufferUsage': renderer.BUFFER_STATIC}, | 46 | "vert":{'type':renderer.VS_ELEMENT_POS, 'bufferIndex':0, 'bufferUsage': renderer.BUFFER_STATIC}, |
47 | "a_pos":{'type':renderer.VS_ELEMENT_POS, 'bufferIndex':0, 'bufferUsage': renderer.BUFFER_STATIC}, | 47 | "a_pos":{'type':renderer.VS_ELEMENT_POS, 'bufferIndex':0, 'bufferUsage': renderer.BUFFER_STATIC}, |
48 | 48 | ||
49 | "normal":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, | 49 | "normal":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, |
50 | "a_nrm":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, | 50 | "a_nrm":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, |
51 | "a_normal":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, | 51 | "a_normal":{'type':renderer.VS_ELEMENT_FLOAT3, 'bufferIndex':1, 'bufferUsage': renderer.BUFFER_STATIC}, |
52 | 52 | ||
53 | "texcoord":{'type':renderer.VS_ELEMENT_FLOAT2, 'bufferIndex':2, 'bufferUsage': renderer.BUFFER_STATIC}, | 53 | "texcoord":{'type':renderer.VS_ELEMENT_FLOAT2, 'bufferIndex':2, 'bufferUsage': renderer.BUFFER_STATIC}, |
54 | "a_texcoord":{'type':renderer.VS_ELEMENT_FLOAT2, 'bufferIndex':2, 'bufferUsage': renderer.BUFFER_STATIC} | 54 | "a_texcoord":{'type':renderer.VS_ELEMENT_FLOAT2, 'bufferIndex':2, 'bufferUsage': renderer.BUFFER_STATIC} |
55 | }; | 55 | }; |
56 | 56 | ||
57 | // the actual data that correlates to the vertex definition | 57 | // the actual data that correlates to the vertex definition |
58 | prim.bufferStreams = [ coords, normals, uvs ]; | 58 | prim.bufferStreams = [ coords, normals, uvs ]; |
59 | 59 | ||
60 | // what type of buffers the data resides in, static is the most common case | 60 | // what type of buffers the data resides in, static is the most common case |
61 | prim.streamUsage = [ renderer.BUFFER_STATIC, renderer.BUFFER_STATIC, renderer.BUFFER_STATIC ]; | 61 | prim.streamUsage = [ renderer.BUFFER_STATIC, renderer.BUFFER_STATIC, renderer.BUFFER_STATIC ]; |
62 | 62 | ||
63 | // this tells the renderer to draw the primitive as a list of triangles | 63 | // this tells the renderer to draw the primitive as a list of triangles |
64 | prim.type = primType; | 64 | prim.type = primType; |
65 | 65 | ||
66 | prim.indexUsage = renderer.BUFFER_STREAM; | 66 | prim.indexUsage = renderer.BUFFER_STREAM; |
67 | prim.indexBuffer = indices; | 67 | prim.indexBuffer = indices; |
68 | 68 | ||
69 | // finally the primitive is created, buffers are generated and the system determines | 69 | // finally the primitive is created, buffers are generated and the system determines |
70 | // the data it needs to draw this primitive according to the previous definition | 70 | // the data it needs to draw this primitive according to the previous definition |
71 | renderer.createPrimitive(prim, vertexCount); | 71 | renderer.createPrimitive(prim, vertexCount); |
72 | 72 | ||
73 | return prim; | 73 | return prim; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | ShapePrimitive.getMeshBounds = function( verts, nVerts ) | 76 | ShapePrimitive.getMeshBounds = function( verts, nVerts ) |
77 | { | 77 | { |
78 | if (!verts || (nVerts <= 0)) return null; | 78 | if (!verts || (nVerts <= 0)) return null; |
79 | |||
80 | var bounds = [verts[0], verts[1], verts[2], verts[0], verts[1], verts[2]]; | ||
81 | var index = 3; | ||
82 | for (var i=1; i<nVerts; i++) | ||
83 | { | ||
84 | var x = verts[index], y = verts[index+1], z = verts[index+2]; | ||
85 | index += 3; | ||
86 | |||
87 | if (x < bounds[0]) bounds[0] = x; | ||
88 | else if (x > bounds[3]) bounds[3] = x; | ||
89 | if (y < bounds[1]) bounds[1] = y; | ||
90 | else if (y > bounds[4]) bounds[4] = y; | ||
91 | if (z < bounds[2]) bounds[2] = z; | ||
92 | else if (z > bounds[5]) bounds[5] = z; | ||
93 | } | ||
94 | |||
95 | return bounds; | ||
96 | }; | ||
79 | 97 | ||
80 | var bounds = [verts[0], verts[1], verts[2], verts[0], verts[1], verts[2]]; | 98 | ShapePrimitive.getBounds = function( prim ) |
81 | var index = 3; | 99 | { |
82 | for (var i=1; i<nVerts; i++) | 100 | var verts = prim.bufferStreams[0]; |
83 | { | 101 | var nVerts = verts.length; |
84 | var x = verts[index], y = verts[index+1], z = verts[index+2]; | 102 | var xMin = verts[0], xMax = verts[0], |
85 | index += 3; | 103 | yMin = verts[1], yMax = verts[1], |
104 | zMin = verts[2], zMax = verts[2]; | ||
105 | |||
106 | for (var index=3; index<verts.length; ) | ||
107 | { | ||
108 | if (verts[index] < xMin) xMin = verts[index]; | ||
109 | else if (verts[index] > xMax) xMax = verts[index]; | ||
110 | |||
111 | index++; | ||
112 | if (verts[index] < yMin) yMin = verts[index]; | ||
113 | else if (verts[index] > yMax) yMax = verts[index]; | ||
114 | |||
115 | index++; | ||
116 | if (verts[index] < zMin) zMin = verts[index]; | ||
117 | else if (verts[index] > zMax) zMax = verts[index]; | ||
118 | |||
119 | index++; | ||
120 | } | ||
121 | |||
122 | return [xMin, yMin, zMin, xMax, yMax, zMax]; | ||
123 | }; | ||
124 | |||
125 | ShapePrimitive.refineMesh = function( verts, norms, uvs, indices, nVertices, paramRange, tolerance ) | ||
126 | { | ||
127 | var oldVrtCount = nVertices; | ||
128 | |||
129 | // get the param range | ||
130 | var pUMin = paramRange[0], pVMin = paramRange[1], | ||
131 | pUMax = paramRange[2], pVMax = paramRange[3]; | ||
132 | var iTriangle = 0; | ||
133 | var nTriangles = indices.length/3; | ||
134 | var index = 0; | ||
135 | while (iTriangle < nTriangles) | ||
136 | { | ||
137 | // get the indices of the 3 vertices | ||
138 | var i0 = indices[index], | ||
139 | i1 = indices[index+1], | ||
140 | i2 = indices[index+2]; | ||
141 | |||
142 | // get the uv values | ||
143 | //var vrtIndex = 3*iTriangle; | ||
144 | var iuv0 = 2 * i0, | ||
145 | iuv1 = 2 * i1, | ||
146 | iuv2 = 2 * i2; | ||
147 | var u0 = uvs[iuv0], v0 = uvs[iuv0+1], | ||
148 | u1 = uvs[iuv1], v1 = uvs[iuv1+1], | ||
149 | u2 = uvs[iuv2], v2 = uvs[iuv2+1]; | ||
150 | |||
151 | // find the u and v range | ||
152 | var uMin = u0, vMin = v0; | ||
153 | if (u1 < uMin) uMin = u1; if (v1 < vMin) vMin = v1; | ||
154 | if (u2 < uMin) uMin = u2; if (v2 < vMin) vMin = v2; | ||
155 | var uMax = u0, vMax = v0; | ||
156 | if (u1 > uMax) uMax = u1; if (v1 > vMax) vMax = v1; | ||
157 | if (u2 > uMax) uMax = u2; if (v2 > vMax) vMax = v2; | ||
158 | |||
159 | // if the parameter range of the triangle is outside the | ||
160 | // desired parameter range, advance to the next polygon and continue | ||
161 | if ((uMin > pUMax) || (uMax < pUMin) || (vMin > pVMax) || (vMax < pVMin)) | ||
162 | { | ||
163 | // go to the next triangle | ||
164 | iTriangle++; | ||
165 | index += 3; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | // check thesize of the triangle in uv space. If small enough, advance | ||
170 | // to the next triangle. If not small enough, split the triangle into 3; | ||
171 | var du = Math.abs(uMax) - uMin, dv = Math.abs(vMax - vMin); | ||
172 | if ((du < tolerance) && (dv < tolerance)) | ||
173 | { | ||
174 | iTriangle++; | ||
175 | index += 3; | ||
176 | } | ||
177 | else // split the triangle into 4 parts | ||
178 | { | ||
179 | //calculate the position of the new vertex | ||
180 | var iPt0 = 3 * i0, | ||
181 | iPt1 = 3 * i1, | ||
182 | iPt2 = 3 * i2; | ||
183 | var x0 = verts[iPt0], y0 = verts[iPt0+1], z0 = verts[iPt0+2], | ||
184 | x1 = verts[iPt1], y1 = verts[iPt1+1], z1 = verts[iPt1+2], | ||
185 | x2 = verts[iPt2], y2 = verts[iPt2+1], z2 = verts[iPt2+2]; | ||
186 | |||
187 | // calculate the midpoints of the edges | ||
188 | var xA = (x0 + x1)/2.0, yA = (y0 + y1)/2.0, zA = (z0 + z1)/2.0, | ||
189 | xB = (x1 + x2)/2.0, yB = (y1 + y2)/2.0, zB = (z1 + z2)/2.0, | ||
190 | xC = (x2 + x0)/2.0, yC = (y2 + y0)/2.0, zC = (z2 + z0)/2.0; | ||
191 | |||
192 | // calculate the uv values of the new coordinates | ||
193 | var uA = (u0 + u1)/2.0, vA = (v0 + v1)/2.0, | ||
194 | uB = (u1 + u2)/2.0, vB = (v1 + v2)/2.0, | ||
195 | uC = (u2 + u0)/2.0, vC = (v2 + v0)/2.0; | ||
196 | |||
197 | // calculate the normals for the new points | ||
198 | var nx0 = norms[iPt0], ny0 = norms[iPt0+1], nz0 = norms[iPt0+2], | ||
199 | nx1 = norms[iPt1], ny1 = norms[iPt1+1], nz1 = norms[iPt1+2], | ||
200 | nx2 = norms[iPt2], ny2 = norms[iPt2+1], nz2 = norms[iPt2+2]; | ||
201 | var nxA = (nx0 + nx1), nyA = (ny0 + ny1), nzA = (nz0 + nz1); var nrmA = VecUtils.vecNormalize(3, [nxA, nyA, nzA], 1.0 ), | ||
202 | nxB = (nx1 + nx2), nyB = (ny1 + ny2), nzB = (nz1 + nz2); var nrmB = VecUtils.vecNormalize(3, [nxB, nyB, nzB], 1.0 ), | ||
203 | nxC = (nx2 + nx0), nyC = (ny2 + ny0), nzC = (nz2 + nz0); var nrmC = VecUtils.vecNormalize(3, [nxC, nyC, nzC], 1.0 ); | ||
204 | |||
205 | // push everything | ||
206 | verts.push(xA); verts.push(yA); verts.push(zA); | ||
207 | verts.push(xB); verts.push(yB); verts.push(zB); | ||
208 | verts.push(xC); verts.push(yC); verts.push(zC); | ||
209 | uvs.push(uA), uvs.push(vA); | ||
210 | uvs.push(uB), uvs.push(vB); | ||
211 | uvs.push(uC), uvs.push(vC); | ||
212 | norms.push(nrmA[0]); norms.push(nrmA[1]); norms.push(nrmA[2]); | ||
213 | norms.push(nrmB[0]); norms.push(nrmB[1]); norms.push(nrmB[2]); | ||
214 | norms.push(nrmC[0]); norms.push(nrmC[1]); norms.push(nrmC[2]); | ||
215 | |||
216 | // split the current triangle into 4 | ||
217 | indices[index+1] = nVertices; indices[index+2] = nVertices+2; | ||
218 | indices.push(nVertices); indices.push(i1); indices.push(nVertices+1); nTriangles++; | ||
219 | indices.push(nVertices+1); indices.push(i2); indices.push(nVertices+2); nTriangles++; | ||
220 | indices.push(nVertices); indices.push(nVertices+1); indices.push(nVertices+2); nTriangles++; | ||
221 | nVertices += 3; | ||
222 | |||