1 //////////////////////////////////////////////////////////////////////
2 //
3 //                             Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 //	This library is free software; you can redistribute it and/or
10 //	modify it under the terms of the GNU Lesser General Public
11 //	License as published by the Free Software Foundation; either
12 //	version 2.1 of the License, or (at your option) any later version.
13 //
14 //	This library is distributed in the hope that it will be useful,
15 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //	Lesser General Public License for more details.
18 //
19 //	You should have received a copy of the GNU Lesser General Public
20 //	License along with this library; if not, write to the Free Software
21 //	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 //  File				:	subdivisionCreator.cpp
27 //  Classes				:	CSision
28 //  Description			:	Implements a subdivision surface
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include <math.h>
32 #include <string.h>
33 
34 #include "subdivision.h"
35 #include "subdivisionCreator.h"
36 #include "memory.h"
37 #include "patches.h"
38 #include "stats.h"
39 #include "patchgrid.h"
40 #include "bsplinePatchgrid.h"
41 #include "shading.h"
42 #include "error.h"
43 #include "rendererContext.h"
44 #include "pl.h"
45 #include "renderer.h"
46 #include "ri.h"
47 
48 #undef new
49 
50 const	unsigned	int	FACE_MOVING				=	2;			// Set if the face is moving
51 const	unsigned	int	FACE_INTEPOLATEBOUNDARY	=	4;			// Set if we're interpolating the boundary
52 
53 const	float			bsplineBasis[16]		=	 {
54 	(float) (-1.0/6.0),	(float) (3.0/6.0),	(float) (-3.0/6.0),	(float)  (1.0/6.0),
55 	(float) (3.0/6.0),	(float) -(6.0/6.0),	(float) (3.0/6.0),	(float)  (0.0/6.0),
56 	(float) (-3.0/6.0),	(float) (0.0/6.0),	(float) (3.0/6.0),	(float)  (0.0/6.0),
57 	(float) (1.0/6.0),	(float) (4.0/6.0),	(float) (1.0/6.0),	(float)  (0.0/6.0)};
58 
59 class	CSVertex;
60 class	CSEdge;
61 class	CSFace;
62 
63 // This class some transient data we use during the tesselation of the subdivision surface
64 class CSubdivData {
65 public:
66 	int				vertexSize;					// The size of a vertex variable
67 	int				varyingSize;				// The size of a varying variable
68 	int				facevaryingSize;			// The size of a facevarying variable
69 	float			*vertexData;				// The array of vertices
70 	float			*varyingData;				// The array of varyings
71 	float			*facevaryingData;			// The array of facevaryings
72 
73 	int				irregularDepth;				// The depth of subdivision in the case of the creases / etc.
74 	CSVertex		**irregularVertices;		// The array of irregular vertices
75 	CSVertex		**irregularRing;			// The ring of irregular vertices about the extraordinary vert
76 	CVertexData		*vd;
77 	CAttributes		*currentAttributes;
78 	CXform			*currentXform;
79 	int				currentFlags;
80 	CPl				*parameterList;
81 
82 	CShadingContext	*context;
83 };
84 
85 
86 
87 
88 // Some misc functions for computing the vertex / varying coordinates
accumVertex(CSubdivData & data,float * dest,const float * src,float mul=1)89 inline void	accumVertex(CSubdivData &data,float *dest,const float *src,float mul = 1) {
90 	for (int i=0;i<data.vertexSize;i++) {
91 		dest[i]	+=	src[i]*mul;
92 	}
93 }
94 
scaleVertex(CSubdivData & data,float * dest,float mul=1)95 inline void	scaleVertex(CSubdivData &data,float *dest,float mul = 1) {
96 	for (int i=0;i<data.vertexSize;i++) {
97 		dest[i]	*=	mul;
98 	}
99 }
100 
initVertex(CSubdivData & data,float * dest)101 inline void	initVertex(CSubdivData &data,float *dest) {
102 	for (int i=0;i<data.vertexSize;i++) {
103 		dest[i]	=	0;
104 	}
105 }
106 
107 static void	gatherData(CSubdivData &data,int numVertex,CSVertex **vertices,CSVertex **varyings,int uniformNumber,float *&vertex,CParameter *&parameters);
108 
109 
110 ///////////////////////////////////////////////////////////////////////
111 // Class				:	CSVertex
112 // Description			:	Encapsulates a subdivision mesh vertex
113 // Comments				:
114 class	CSVertex {
115 
116 	///////////////////////////////////////////////////////////////////////
117 	// Class				:	CVertexFace
118 	// Description			:	Encapsulates a face incident on a vertex
119 	// Comments				:
120 	class	CVertexFace {
121 	public:
122 		CSFace			*face;
123 		CVertexFace		*next;
124 	};
125 
126 	///////////////////////////////////////////////////////////////////////
127 	// Class				:	CVertexEdge
128 	// Description			:	Encapsulates an edge incident on a vertex
129 	// Comments				:
130 	class	CVertexEdge {
131 	public:
132 		CSEdge			*edge;
133 		CVertexEdge		*next;
134 	};
135 public:
136 					///////////////////////////////////////////////////////////////////////
137 					// Class				:	CSVertex
138 					// Method				:	CSVertex
139 					// Description			:	Ctor
140 					// Return Value			:	-
141 					// Comments				:
CSVertex(CSubdivData & d)142 					CSVertex(CSubdivData &d) : data(d) {
143 						faces			=	NULL;
144 						edges			=	NULL;
145 						valence			=	0;
146 						fvalence		=	0;
147 						vertex			=	NULL;
148 						varying			=	NULL;
149 						facevarying		=	NULL;
150 						parentv			=	NULL;
151 						parente			=	NULL;
152 						parentf			=	NULL;
153 						childVertex		=	NULL;
154 						sharpness		=	0;
155 					}
156 
157 	CSubdivData		&data;
158 	CVertexFace		*faces;							// Incident faces
159 	CVertexEdge		*edges;							// Incident edges
160 	int				valence;						// Edge valence
161 	int				fvalence;						// Face valence i.e., the number of faces incident on the vertex
162 	float			*vertex;						// The vertex coordinates
163 	float			*varying,*facevarying;			// The varying coordinates
164 	CSVertex		*parentv;						// The parent simplex
165 	CSEdge			*parente;
166 	CSFace			*parentf;
167 	CSVertex		*childVertex;					// Child vertex
168 	float			sharpness;
169 
operator new(size_t s,CShadingContext * context)170 	void			*operator new(size_t s,CShadingContext *context) {
171 						return ralloc((int) s,context->threadMemory);
172 					}
173 
174 					///////////////////////////////////////////////////////////////////////
175 					// Class				:	CSVertex
176 					// Method				:	split
177 					// Description			:	Split a vertex
178 					// Return Value			:	-
179 					// Comments				:
split()180 	void			split() {
181 						if (childVertex == NULL) {
182 							childVertex					=	new (data.context) CSVertex(data);
183 							childVertex->parentv		=	this;
184 							childVertex->sharpness		=	max(sharpness-1,0);
185 						}
186 					}
187 
188 
189 					///////////////////////////////////////////////////////////////////////
190 					// Class				:	CSVertex
191 					// Method				:	addFace
192 					// Description			:	Add an incident face into the vertex
193 					// Return Value			:	-
194 					// Comments				:
addFace(CSFace * face)195 	void			addFace(CSFace *face) {
196 						CVertexFace	*cFace	=	(CVertexFace *) ralloc(sizeof(CVertexFace),data.context->threadMemory);
197 
198 						cFace->face	=	face;
199 						cFace->next	=	faces;
200 						faces		=	cFace;
201 
202 						fvalence++;
203 					}
204 
205 
206 					///////////////////////////////////////////////////////////////////////
207 					// Class				:	CSVertex
208 					// Method				:	addEdge
209 					// Description			:	Add an incident edge into the vertex
210 					// Return Value			:	-
211 					// Comments				:
addEdge(CSEdge * edge)212 	void			addEdge(CSEdge *edge) {
213 						CVertexEdge	*cEdge	=	(CVertexEdge *) ralloc(sizeof(CVertexEdge),data.context->threadMemory);
214 
215 						cEdge->edge	=	edge;
216 						cEdge->next	=	edges;
217 						edges		=	cEdge;
218 
219 						valence++;
220 					}
221 
222 	CSEdge			*edgeExists(CSVertex *v);
223 	void			splitIncidentFaces();
224 	void			sort(CSVertex **,CSEdge *,CSFace *,int);
225 	void			compute(float *);
226 	void			computeLimit(float *);
227 	void			computeVarying(float *,float *);
228 	void			compute();
229 	int				funny();
230 	int				shouldSplit();
231 };
232 
233 ///////////////////////////////////////////////////////////////////////
234 // Class				:	CSEdge
235 // Description			:	Encapsulates an edge
236 // Comments				:
237 class	CSEdge {
238 public:
239 
240 					///////////////////////////////////////////////////////////////////////
241 					// Class				:	CSEdge
242 					// Method				:	CSEdge
243 					// Description			:	Ctor
244 					// Return Value			:	-
245 					// Comments				:
CSEdge(CSubdivData & d)246 					CSEdge(CSubdivData &d) : data(d) {
247 						vertices[0]	=	NULL;
248 						vertices[1]	=	NULL;
249 						faces[0]	=	NULL;
250 						faces[1]	=	NULL;
251 						sharpness	=	0;
252 						childVertex	=	NULL;
253 						children[0]	=	NULL;
254 						children[1]	=	NULL;
255 					}
256 
257 
258 	CSubdivData		&data;
259 	CSVertex		*vertices[2];					// Incident vertices
260 	CSFace			*faces[2];						// Incident faces
261 	float			sharpness;						// Edge sharpness
262 	CSVertex		*childVertex;					// The child vertex
263 	CSEdge			*children[2];					// The child edges
264 
operator new(size_t s,CShadingContext * context)265 	void			*operator new(size_t s,CShadingContext *context) {
266 						return ralloc((int) s,context->threadMemory);
267 					}
268 
269 					///////////////////////////////////////////////////////////////////////
270 					// Class				:	CSEdge
271 					// Method				:	split
272 					// Description			:	Split an edge
273 					// Return Value			:	-
274 					// Comments				:
split()275 	void			split() {
276 						if (childVertex == NULL) {
277 							vertices[0]->split();
278 							vertices[1]->split();
279 
280 							children[0]					=	new (data.context) CSEdge(data);
281 							children[1]					=	new (data.context) CSEdge(data);
282 							childVertex					=	new (data.context) CSVertex(data);
283 
284 							childVertex->parente		=	this;
285 
286 							children[0]->vertices[0]	=	vertices[0]->childVertex;
287 							children[0]->vertices[1]	=	childVertex;
288 							children[0]->sharpness		=	max(sharpness-1,0);
289 
290 							children[1]->vertices[0]	=	vertices[1]->childVertex;
291 							children[1]->vertices[1]	=	childVertex;
292 							children[1]->sharpness		=	max(sharpness-1,0);
293 
294 							children[0]->vertices[0]->addEdge(children[0]);
295 							children[0]->vertices[1]->addEdge(children[0]);
296 							children[1]->vertices[0]->addEdge(children[1]);
297 							children[1]->vertices[1]->addEdge(children[1]);
298 						}
299 					}
300 
301 					///////////////////////////////////////////////////////////////////////
302 					// Class				:	CSEdge
303 					// Method				:	addFace
304 					// Description			:	Add a face into an edge
305 					// Return Value			:	-
306 					// Comments				:
addFace(CSFace * face)307 	void			addFace(CSFace *face) {
308 						if (faces[0] == NULL)	faces[0]	=	face;
309 						else {
310 							assert(faces[1] == NULL);
311 							assert(faces[0] != face);
312 							faces[1]	=	face;
313 						}
314 					}
315 
316 	void			compute(float *);
317 	void			computeVarying(float *,float *);
318 };
319 
320 
321 
322 
323 
324 ///////////////////////////////////////////////////////////////////////
325 // Class				:	CSFace
326 // Description			:	Encapsulates a face
327 // Comments				:
328 class	CSFace {
329 public:
330 					///////////////////////////////////////////////////////////////////////
331 					// Class				:	CSFace
332 					// Method				:	CSFace
333 					// Description			:	Ctor
334 					// Return Value			:	-
335 					// Comments				:
CSFace(CSubdivData & d,int ui)336 					CSFace(CSubdivData &d,int ui) : data(d) {
337 						numEdges		=	0;
338 						edges			=	NULL;
339 						vertices		=	NULL;
340 						uniformIndex	=	ui;
341 						children		=	NULL;
342 						childVertex		=	NULL;
343 						hole			=	FALSE;
344 					}
345 
346 	CSubdivData		&data;
347 	int				numEdges;
348 	CSEdge			**edges;
349 	CSVertex		**vertices;
350 	int				uniformIndex;
351 	int				hole;
352 	CSFace			**children;
353 	CSVertex		*childVertex;
354 
operator new(size_t s,CShadingContext * context)355 	void			*operator new(size_t s,CShadingContext *context) {
356 						return ralloc((int) s,context->threadMemory);
357 					}
358 
359 					///////////////////////////////////////////////////////////////////////
360 					// Class				:	CSFace
361 					// Method				:	split
362 					// Description			:	Split the face
363 					// Return Value			:	-
364 					// Comments				:
split()365 	void			split() {
366 						if (childVertex == NULL) {
367 							int			i;
368 							CSEdge		**newEdges	=	(CSEdge **) ralloc(numEdges*sizeof(CSEdge *),data.context->threadMemory);
369 
370 							children				=	(CSFace **) ralloc(numEdges*sizeof(CSFace *),data.context->threadMemory);
371 							childVertex				=	new (data.context) CSVertex(data);
372 							childVertex->parentf	=	this;
373 
374 							// Make sure the incident edges are split
375 							for (i=0;i<numEdges;i++) {
376 								edges[i]->split();
377 							}
378 
379 							// Create the edges connected to the center
380 							for (i=0;i<numEdges;i++) {
381 								CSFace	*cFace		=	new (data.context) CSFace(data,uniformIndex);
382 								CSEdge	*cEdge		=	new (data.context) CSEdge(data);
383 
384 								cFace->numEdges		=	4;
385 								cFace->edges		=	(CSEdge **)		ralloc(4*sizeof(CSEdge *),data.context->threadMemory);
386 								cFace->vertices		=	(CSVertex **)	ralloc(4*sizeof(CSVertex *),data.context->threadMemory);
387 
388 								cEdge->vertices[0]	=	edges[i]->childVertex;
389 								cEdge->vertices[1]	=	childVertex;
390 
391 								childVertex->addEdge(cEdge);
392 								edges[i]->childVertex->addEdge(cEdge);
393 
394 								children[i]			=	cFace;
395 								newEdges[i]			=	cEdge;
396 							}
397 
398 							// Create the children faces
399 							for (i=0;i<numEdges;i++) {
400 								int	t;
401 
402 								if (	(vertices[i]->childVertex == edges[i]->children[0]->vertices[0]) ||
403 										(vertices[i]->childVertex == edges[i]->children[0]->vertices[1])) {
404 									children[i]->edges[0]	=	edges[i]->children[0];
405 								} else {
406 									assert(	(vertices[i]->childVertex == edges[i]->children[1]->vertices[0]) ||
407 											(vertices[i]->childVertex == edges[i]->children[1]->vertices[1]));
408 									children[i]->edges[0]	=	edges[i]->children[1];
409 								}
410 
411 								t	=	(i-1+numEdges) % numEdges;
412 
413 								children[i]->edges[1]		=	newEdges[i];
414 								children[i]->edges[2]		=	newEdges[t];
415 
416 								if (	(vertices[i]->childVertex == edges[t]->children[0]->vertices[0]) ||
417 										(vertices[i]->childVertex == edges[t]->children[0]->vertices[1])) {
418 									children[i]->edges[3]	=	edges[t]->children[0];
419 								} else {
420 									assert(	(vertices[i]->childVertex == edges[t]->children[1]->vertices[0]) ||
421 											(vertices[i]->childVertex == edges[t]->children[1]->vertices[1]));
422 									children[i]->edges[3]	=	edges[t]->children[1];
423 								}
424 
425 
426 								children[i]->vertices[0]	=	vertices[i]->childVertex;
427 								children[i]->vertices[1]	=	edges[i]->childVertex;
428 								children[i]->vertices[2]	=	childVertex;
429 								children[i]->vertices[3]	=	edges[t]->childVertex;
430 
431 								assert(children[i]->vertices[0] != NULL);
432 								assert(children[i]->vertices[1] != NULL);
433 								assert(children[i]->vertices[2] != NULL);
434 								assert(children[i]->vertices[3] != NULL);
435 							}
436 
437 							// Manage the connectivity
438 							for (i=0;i<numEdges;i++) {
439 								children[i]->vertices[0]->addFace(children[i]);
440 								children[i]->vertices[1]->addFace(children[i]);
441 								children[i]->vertices[2]->addFace(children[i]);
442 								children[i]->vertices[3]->addFace(children[i]);
443 
444 								children[i]->edges[0]->addFace(children[i]);
445 								children[i]->edges[1]->addFace(children[i]);
446 								children[i]->edges[2]->addFace(children[i]);
447 								children[i]->edges[3]->addFace(children[i]);
448 							}
449 						}
450 					}
451 
452 
453 					///////////////////////////////////////////////////////////////////////
454 					// Class				:	CSFace
455 					// Method				:	Create
456 					// Description			:	Split / create children objects
457 					// Return Value			:	-
458 					// Comments				:
create(CObject * & children)459 	void			create(CObject *&children) {
460 						int	split				=	FALSE;
461 						int	funny				=	FALSE;
462 						int funnyBorder			=	FALSE;
463 						int	i,j;
464 						int	numExtraordinary	=	0;
465 						int	extraordinary		=	0;
466 
467 						if (hole == TRUE)	return;							// If we're a hole, don't create
468 
469 						if (numEdges != 4) {
470 							split	=	TRUE;								// If we're not a quad, we must split (vanilla, no funny patch treatment)
471 						} else {
472 							// Count the extraordinary vertices
473 							for (i=0;i<numEdges;i++) {
474 
475 								// was: if (vertices[i]->valence != 4 ) {
476 								// The following is better as it forces borders to split such that there is
477 								// one extraordinart vertex which isn't a natural border point
478 								if ( ((vertices[i]->valence != 4) || (vertices[i]->fvalence != 4)) && (!((vertices[i]->valence == 3) && (vertices[i]->fvalence == 2))) ) {
479 									numExtraordinary++;
480 									extraordinary	=	i;
481 								}
482 
483 								if (vertices[i]->valence != vertices[i]->fvalence) {
484 									if (!(data.currentFlags & FACE_INTEPOLATEBOUNDARY)) {
485 										// We're a face adjacent to a boundary and the interpolate boundary flag is not set
486 										return;
487 									} else {
488 										funny		=	TRUE;
489 										funnyBorder	=	TRUE;
490 									}
491 								}
492 
493 								if (vertices[i]->shouldSplit()) split	=	TRUE;
494 							}
495 
496 
497 							// was: if (numExtraordinary > 1) {
498 							// prefer to split if possible to enforce above
499 							// constraint on extraordinary border vertices
500 							if (numExtraordinary > 1) {				// If we have more than one ordinary, we must split
501 								split = TRUE;
502 								funny = FALSE;
503 							}
504 
505 							if (numExtraordinary == 1) {
506 								if (vertices[extraordinary]->valence < 3) funny = TRUE;
507 							}
508 						}
509 
510 						if ((split == FALSE) || (funny == TRUE)) {
511 							// Check if we're a "funny" quad. i.e., have crease edges
512 							for (i=0;i<numEdges;i++) {
513 								if (vertices[i]->funny() == TRUE) {
514 									funny	=	TRUE;
515 									break;
516 								}
517 							}
518 
519 							if (funny == FALSE) {
520 
521 								// We're not a funny patch
522 								// We are either:
523 								//		1 - A regular patch - Create a bi-cubic patch
524 								//		2 - An extraordinary patch - Create an extraordinary patch
525 								if (numExtraordinary == 1) {
526 									// This is an extraordinary patch
527 									CSVertex	**v,*va[4];
528 									int			N		=	vertices[extraordinary]->valence;
529 									int			K		=	2*N + 8;
530 									CSVertex	**ring	=	(CSVertex **) alloca(2*N*sizeof(CSVertex *));	// Holds the ring around the extraordinary vertex (transient)
531 									CSVertex	*ringt[8];
532 									float		*vertex;
533 									CParameter	*parameters;
534 
535 									v		=	(CSVertex **) alloca((K+1)*sizeof(CSVertex *));				// Holds the vertices that effect the current patch (transient)
536 
537 									// First, deal with the vertices around the extraordinary vertex
538 									vertices[(extraordinary + 0) & 3]->sort(ring,edges[(extraordinary + 0) & 3],this,2*N);
539 									for (i=0;i<(2*N);i++) {
540 										v[i + 2]	=	ring[(i + 2*N - 2) % (2*N)];
541 									}
542 
543 									vertices[(extraordinary + 1) & 3]->sort(ringt,edges[(extraordinary + 1) & 3],this,8);
544 									v[2*N+8]	=	ringt[5];
545 									v[2*N+7]	=	ringt[6];
546 									v[2*N+6]	=	ringt[7];
547 
548 									vertices[(extraordinary + 2) & 3]->sort(ringt,edges[(extraordinary + 2) & 3],this,8);
549 									v[2*N+2]	=	ringt[5];
550 
551 									vertices[(extraordinary + 3) & 3]->sort(ringt,edges[(extraordinary + 3) & 3],this,8);
552 									v[2*N+5]	=	ringt[5];
553 									v[2*N+4]	=	ringt[4];
554 									v[2*N+3]	=	ringt[3];
555 
556 									v[1]		=	vertices[(extraordinary + 0) & 3];
557 									assert(v[4]	==	vertices[(extraordinary + 1) & 3]);
558 									assert(v[5]	==	vertices[(extraordinary + 2) & 3]);
559 									assert(v[6]	==	vertices[(extraordinary + 3) & 3]);
560 
561 									va[0]		=	v[1];
562 									va[1]		=	v[4];
563 									va[2]		=	v[6];
564 									va[3]		=	v[5];
565 
566 									// Gather the data
567 									gatherData(data,K,v+1,va,uniformIndex,vertex,parameters);
568 
569 									// Create the primitive
570 									CObject	*nObject	=	new CSubdivision(data.currentAttributes,data.currentXform,data.vd,parameters,N,0.0f,0.0f,1.0f,1.0f,vertex);
571 									nObject->sibling	=	children;
572 									children			=	nObject;
573 								} else {
574 									// This is an ordinary patch
575 									CSVertex	*v[16],*va[4];
576 									CSVertex	*ring[8];
577 									float		*vertex;
578 									CParameter	*parameters;
579 
580 									// Gather the regular neighborhood
581 									vertices[0]->sort(ring,edges[0],this,8);
582 									v[0*4+0]	=	ring[5];
583 									v[0*4+1]	=	ring[6];
584 									v[0*4+2]	=	ring[7];
585 									v[1*4+0]	=	ring[4];
586 									v[2*4+0]	=	ring[3];
587 
588 									vertices[1]->sort(ring,edges[1],this,8);
589 									v[0*4+3]	=	ring[5];
590 									v[1*4+3]	=	ring[6];
591 									v[2*4+3]	=	ring[7];
592 
593 									vertices[2]->sort(ring,edges[2],this,8);
594 									v[3*4+1]	=	ring[7];
595 									v[3*4+2]	=	ring[6];
596 									v[3*4+3]	=	ring[5];
597 
598 									vertices[3]->sort(ring,edges[3],this,8);
599 									v[3*4+0]	=	ring[5];
600 
601 									v[1*4+1]	=	vertices[(extraordinary+0)&3];
602 									v[1*4+2]	=	vertices[(extraordinary+1)&3];
603 									v[2*4+2]	=	vertices[(extraordinary+2)&3];
604 									v[2*4+1]	=	vertices[(extraordinary+3)&3];
605 
606 									va[0]		=	v[1*4+1];
607 									va[1]		=	v[1*4+2];
608 									va[2]		=	v[2*4+1];
609 									va[3]		=	v[2*4+2];
610 
611 									// Gather the data
612 									gatherData(data,16,v,va,uniformIndex,vertex,parameters);
613 
614 									// Create the primitive
615 									CObject	*nObject	=	new CBicubicPatch(data.currentAttributes,data.currentXform,data.vd,parameters,0,0,1,1,vertex,bsplineBasis,bsplineBasis);
616 									nObject->sibling	=	children;
617 									children			=	nObject;
618 								}
619 							} else {
620 								// Damn, we're a funny patch, deal with it
621 								int			nv		=	(1 << data.irregularDepth) + 1;
622 								float		*vertex;
623 								CSVertex	*va[4];
624 								CParameter	*parameters;
625 
626 								data.irregularVertices	=	(CSVertex **) ralloc(sizeof(CSVertex *)*(nv+2)*(nv+2),data.context->threadMemory);
627 								for (i=0;i<(nv+2)*(nv+2);i++) {
628 									data.irregularVertices[i] = NULL;
629 								}
630 
631 								if ( (numExtraordinary > 0) && (vertices[(extraordinary+0)&3]->valence >= 3)) {
632 									data.irregularRing	=	(CSVertex **) ralloc(sizeof(CSVertex *)*(vertices[(extraordinary+0)&3]->valence*2),data.context->threadMemory);
633 								}
634 
635 								// Create irregular patch
636 								unconditionalSplit(data.irregularDepth,0,0,vertices[extraordinary]);
637 
638 								va[0]	=	vertices[(extraordinary+0)&3];
639 								va[1]	=	vertices[(extraordinary+1)&3];
640 								va[2]	=	vertices[(extraordinary+3)&3];
641 								va[3]	=	vertices[(extraordinary+2)&3];
642 
643 								if ( funnyBorder == TRUE ) {
644 									// We're at the border so it'll have to be a bilinear patch
645 
646 
647 									// Note: At the border, we may not have found all the corner vertices - this is particularly true
648 									// if only the corner is at the border.  Set these to the nearest point to ensure
649 									// gather will succeed (we don't use these points anyway)
650 
651 									if (data.irregularVertices[0*(nv+2)+0] == NULL)				data.irregularVertices[0*(nv+2)+0]				= data.irregularVertices[1*(nv+2)+1];
652 									if (data.irregularVertices[0*(nv+2)+(nv+1)] == NULL)		data.irregularVertices[0*(nv+2)+(nv+1)]			= data.irregularVertices[1*(nv+2)+(nv)];
653 									if (data.irregularVertices[(nv+1)*(nv+2)+(nv+1)] == NULL)	data.irregularVertices[(nv+1)*(nv+2)+(nv+1)]	= data.irregularVertices[(nv)*(nv+2)+(nv)];
654 									if (data.irregularVertices[(nv+1)*(nv+2)+0] == NULL)		data.irregularVertices[(nv+1)*(nv+2)+0]			= data.irregularVertices[(nv)*(nv+2)+1];
655 
656 									// now we gather the grid from neighbors on patches where it exists
657 									// pass all available data to the patch grid and flags to indicate which
658 									// edges are valid.  This is used to create symmetric normals
659 									int bTop = (edges[(extraordinary+0)&3]->faces[0] == NULL) || (edges[(extraordinary+0)&3]->faces[1] == NULL);
660 									int bRgt = (edges[(extraordinary+1)&3]->faces[0] == NULL) || (edges[(extraordinary+1)&3]->faces[1] == NULL);
661 									int bBot = (edges[(extraordinary+2)&3]->faces[0] == NULL) || (edges[(extraordinary+2)&3]->faces[1] == NULL);
662 									int bLft = (edges[(extraordinary+3)&3]->faces[0] == NULL) || (edges[(extraordinary+3)&3]->faces[1] == NULL);
663 
664 									gatherData(data,(nv+2)*(nv+2),data.irregularVertices,va,uniformIndex,vertex,parameters);
665 
666 									// Create the primitive
667 									CObject	*nObject	=	new CPatchGrid(data.currentAttributes,data.currentXform,data.vd,parameters,nv,nv,bTop,bRgt,bBot,bLft,vertex);
668 									nObject->sibling	=	children;
669 									children			=	nObject;
670 								} else {
671 									if ( (numExtraordinary > 0) && (vertices[(extraordinary+0)&3]->valence >= 3)) {
672 										// We're have an extraordinary patch
673 										// divide main patch into two side strips which are adjacent
674 										// to the extraordinary pathc and a smaller grid
675 
676 										int			N				=	vertices[extraordinary]->valence;
677 										int			K				=	2*N + 8;
678 										CSVertex	**v				=	(CSVertex **) ralloc((K+1)*sizeof(CSVertex *),data.context->threadMemory);
679 										CSVertex** strip1Vertices	=	(CSVertex**) ralloc(sizeof(CSVertex*)*4*(nv+1),data.context->threadMemory);
680 										CSVertex** strip2Vertices	=	(CSVertex**) ralloc(sizeof(CSVertex*)*4*(nv+1),data.context->threadMemory);
681 										CSVertex** patchVertices	=	(CSVertex**) ralloc(sizeof(CSVertex*)*(nv+1)*(nv+1),data.context->threadMemory);
682 										const float mult			=	1.0f/(nv-1);
683 
684 										for (i=0;i<(nv+1);i++) {
685 											strip1Vertices[4*i+0] = data.irregularVertices[(i+1)*(nv+2)+0];
686 											strip1Vertices[4*i+1] = data.irregularVertices[(i+1)*(nv+2)+1];
687 											strip1Vertices[4*i+2] = data.irregularVertices[(i+1)*(nv+2)+2];
688 											strip1Vertices[4*i+3] = data.irregularVertices[(i+1)*(nv+2)+3];
689 
690 											strip2Vertices[0*(nv+1)+i] = data.irregularVertices[0*(nv+2)+1+i];
691 											strip2Vertices[1*(nv+1)+i] = data.irregularVertices[1*(nv+2)+1+i];
692 											strip2Vertices[2*(nv+1)+i] = data.irregularVertices[2*(nv+2)+1+i];
693 											strip2Vertices[3*(nv+1)+i] = data.irregularVertices[3*(nv+2)+1+i];
694 
695 											for (j=0;j<(nv+1);j++) {
696 												patchVertices[i*(nv+1)+j] = data.irregularVertices[(i+1)*(nv+2)+j+1];
697 											}
698 										}
699 
700 										CObject	*nObject;
701 
702 										// 'left' strip
703 										gatherData(data,(nv+1)*(4),strip1Vertices,va,uniformIndex,vertex,parameters);
704 										nObject				=	new CBSplinePatchGrid(data.currentAttributes,data.currentXform,data.vd,parameters,4,nv+1,0.0f,mult,mult,(nv-2)*mult,vertex);
705 										nObject->sibling	=	children;
706 										children			=	nObject;
707 
708 										// 'top' strip
709 										gatherData(data,(4)*(nv+1),strip2Vertices,va,uniformIndex,vertex,parameters);
710 										nObject				=	new CBSplinePatchGrid(data.currentAttributes,data.currentXform,data.vd,parameters,nv+1,4,mult,0.0f,(nv-2)*mult,mult,vertex);
711 										nObject->sibling	=	children;
712 										children			=	nObject;
713 
714 										// main grid
715 										gatherData(data,(nv+1)*(nv+1),patchVertices,va,uniformIndex,vertex,parameters);
716 										nObject				=	new CBSplinePatchGrid(data.currentAttributes,data.currentXform,data.vd,parameters,nv+1,nv+1,mult,mult,(nv-2)*mult,(nv-2)*mult,vertex);
717 										nObject->sibling	=	children;
718 										children			=	nObject;
719 
720 										// extraordinary patch
721 										for (i=0;i<(2*N);i++) {
722 											v[i + 2]	=	data.irregularRing[(i + 2*N - 2) % (2*N)];
723 										}
724 
725 										v[1]		= data.irregularVertices[1*(nv+2)+1];
726 
727 										v[2*N+6]	= data.irregularVertices[2*(nv+2)+3];
728 										v[2*N+7]	= data.irregularVertices[1*(nv+2)+3];
729 										v[2*N+8]	= data.irregularVertices[0*(nv+2)+3];
730 
731 										v[2*N+5]	= data.irregularVertices[3*(nv+2)+0];
732 										v[2*N+4]	= data.irregularVertices[3*(nv+2)+1];
733 										v[2*N+3]	= data.irregularVertices[3*(nv+2)+2];
734 										v[2*N+2]	= data.irregularVertices[3*(nv+2)+3];
735 
736 										// Gather the data
737 										gatherData(data,K,v+1,va,uniformIndex,vertex,parameters);
738 
739 										// Create the primitive
740 										nObject				=	new CSubdivision(data.currentAttributes,data.currentXform,data.vd,parameters,N,0.0f,0.0f,mult,mult,vertex);
741 										nObject->sibling	=	children;
742 										children			=	nObject;
743 									} else {
744 										// No extraordinary patch, use the a bicubic b-spline patch
745 
746 										// Gather the data
747 										gatherData(data,(nv+2)*(nv+2),data.irregularVertices,va,uniformIndex,vertex,parameters);
748 
749 										// Create the primitive
750 										CObject	*nObject	=	new CBSplinePatchGrid(data.currentAttributes,data.currentXform,data.vd,parameters,nv+2,nv+2,0.0f,0.0f,1.0f,1.0f,vertex);
751 										nObject->sibling	=	children;
752 										children			=	nObject;
753 									}
754 								}
755 							}
756 						} else {
757 							for (i=0;i<numEdges;i++) {
758 								vertices[i]->splitIncidentFaces();
759 							}
760 
761 							for (i=0;i<numEdges;i++) {
762 								this->children[i]->create(children);
763 							}
764 						}
765 					}
766 
767 					///////////////////////////////////////////////////////////////////////
768 					// Class				:	CSFace
769 					// Method				:	unconditionalSplit
770 					// Description			:	Unconditionally split this quad until a predefined depth for table computation
771 					// Return Value			:	-
772 					// Comments				:
unconditionalSplit(int depth,int x,int y,CSVertex * org)773 	void			unconditionalSplit(int depth,int x,int y,CSVertex *org) {
774 						if (depth > 0) {
775 							int	i;
776 
777 							for (i=0;i<numEdges;i++) {
778 								vertices[i]->splitIncidentFaces();
779 							}
780 
781 							for (i=0;i<4;i++) {
782 								if (vertices[i] == org) {
783 									children[(i+0) & 3]->unconditionalSplit(depth-1,(x << 1),(y << 1),				vertices[(i+0) & 3]->childVertex);
784 									children[(i+1) & 3]->unconditionalSplit(depth-1,(x << 1) + 1,(y << 1),			edges[(i+0) & 3]->childVertex);
785 									children[(i+2) & 3]->unconditionalSplit(depth-1,(x << 1) + 1,(y << 1) + 1,		childVertex);
786 									children[(i+3) & 3]->unconditionalSplit(depth-1,(x << 1),(y << 1) + 1,			edges[(i+3) & 3]->childVertex);
787 									break;
788 								}
789 							}
790 
791 							assert(i != 4);
792 						} else {
793 							int	i;
794 
795 							for (i=0;i<4;i++) {
796 								if (vertices[i] == org) {
797 									char l = (x==0);
798 									char r = (x==(1 << data.irregularDepth)-1);
799 									char t = (y==0);
800 									char b = (y==(1 << data.irregularDepth)-1);
801 									char ml=0,mr=0,mt=0,mb=0;
802 
803 									data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 1]		=	vertices[(i + 0) & 3];
804 									data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 2]		=	vertices[(i + 1) & 3];
805 									data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 2]		=	vertices[(i + 2) & 3];
806 									data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 1]		=	vertices[(i + 3) & 3];
807 
808 									// If we're not at an edge, the rest is not relevant
809 									if (!(l||r||t||b)) break;
810 
811 									// Deal with the edges
812 									//  either we fetch vertices from a neighboring face or duplicate the edge
813 									if (l) {
814 										CSVertex *v1	=	data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 1];
815 										CSVertex *v2	= 	data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 1];
816 										ml = findEdgeVertices((i+3)&3,(i+3)&3,v1,v2);
817 										data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x] = v1;
818 										data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x] = v2;
819 									}
820 									if (r) {
821 										CSVertex *v1	=	data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 2];
822 										CSVertex *v2	=	data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 2];
823 										mr = findEdgeVertices((i+1)&3,(i+2)&3,v1,v2);
824 										data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 3] = v1;
825 										data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 3] = v2;
826 									}
827 									if (t) {
828 										CSVertex *v1	=	data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 1];
829 										CSVertex *v2	=	data.irregularVertices[(y+1) * ((1 << data.irregularDepth) + 3) + x + 2];
830 										mt = findEdgeVertices((i+0)&3,(i+1)&3,v1,v2);
831 										data.irregularVertices[(y) * ((1 << data.irregularDepth) + 3) + x + 1] = v1;
832 										data.irregularVertices[(y) * ((1 << data.irregularDepth) + 3) + x + 2] = v2;
833 									}
834 									if (b) {
835 										CSVertex *v1	=	data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 1];
836 										CSVertex *v2	=	data.irregularVertices[(y+2) * ((1 << data.irregularDepth) + 3) + x + 2];
837 										mb = findEdgeVertices((i+2)&3,(i+2)&3,v1,v2);
838 										data.irregularVertices[(y+3) * ((1 << data.irregularDepth) + 3) + x + 1] = v1;
839 										data.irregularVertices[(y+3) * ((1 << data.irregularDepth) + 3) + x + 2] = v2;
840 									}
841 
842 									// Deal with the corners
843 									//  find the corner from an corner-adjacent face if possible, or
844 									//  duplicate a neighboring point
845 									// Note: there's no more than 1 extraordinary vertex here, and its
846 									//  at vertices[(i+0)&3] in (0,0) if there is such a point
847 
848 									if (l&&t) {
849 										if (((vertices[(i+0)&3]->valence != 4) && (vertices[(i+0)&3]->valence >= 3) && (vertices[(i+0)&3]->valence==vertices[(i+0)&3]->fvalence))) {
850 											// We're an extraordinary point and not at the border
851 											vertices[(i+0)&3]->sort(data.irregularRing,edges[(i+0)&3],this,2*vertices[(i+0)&3]->valence);
852 										} else {
853 											CSVertex *v = data.irregularVertices[(y+mt) * ((1 << data.irregularDepth) + 3) + x + ml];
854 											if(!findCornerVertex((i+0)&3,(i+0)&3,v))
855 												findCornerVertex((i+3)&3,(i+0)&3,v);
856 											data.irregularVertices[(y) * ((1 << data.irregularDepth) + 3) + x] = v;
857 										}
858 									}
859 									if (r&&t) {
860 										CSVertex *v = data.irregularVertices[(y+mt) * ((1 << data.irregularDepth) + 3) + x + 3 - mr];
861 										if(!findCornerVertex((i+1)&3,(i+1)&3,v))
862 											findCornerVertex((i+0)&3,(i+1)&3,v);
863 										data.irregularVertices[(y) * ((1 << data.irregularDepth) + 3) + x + 3] = v;
864 									}
865 									if (r&&b) {
866 										CSVertex *v = data.irregularVertices[(y+3-mb) * ((1 << data.irregularDepth) + 3) + x + 3 - mr];
867 										if(!findCornerVertex((i+2)&3,(i+2)&3,v))
868 											findCornerVertex((i+1)&3,(i+2)&3,v);
869 										data.irregularVertices[(y+3) * ((1 << data.irregularDepth) + 3) + x + 3] = v;
870 									}
871 									if (l&&b) {
872 										CSVertex *v = data.irregularVertices[(y+3-mb) * ((1 << data.irregularDepth) + 3) + x + ml];
873 										if(!findCornerVertex((i+3)&3,(i+3)&3,v))
874 											findCornerVertex((i+2)&3,(i+3)&3,v);
875 										data.irregularVertices[(y+3) * ((1 << data.irregularDepth) + 3) + x] = v;
876 									}
877 
878 									break;
879 								}
880 							}
881 
882 							assert(i != 4);
883 						}
884 					}
885 
886 	void			compute(float *);
887 	void			computeVarying(float *,float *);
888 	char			findEdgeVertices(int,int,CSVertex*&,CSVertex*&);
889 	int				findCornerVertex(int,int,CSVertex*&);
890 };
891 
892 
893 
894 
895 
896 
897 
898 
899 
900 
901 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
902 //
903 //	Misc functions related to subdivision surface vertices
904 //
905 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
906 
907 ///////////////////////////////////////////////////////////////////////
908 // Class				:	CSVertex
909 // Method				:	splitIncidentFaces
910 // Description			:	Split all the incident faces
911 // Return Value			:	-
912 // Comments				:
splitIncidentFaces()913 void		CSVertex::splitIncidentFaces() {
914 	CVertexFace	*cFace;
915 
916 	for (cFace=faces;cFace!=NULL;cFace=cFace->next) {
917 		cFace->face->split();
918 	}
919 }
920 
921 ///////////////////////////////////////////////////////////////////////
922 // Class				:	CSVertex
923 // Method				:	edgeExists
924 // Description			:	Figure out if an edge has already been inserted
925 // Return Value			:	-
926 // Comments				:
edgeExists(CSVertex * v)927 CSEdge		*CSVertex::edgeExists(CSVertex *v) {
928 	CVertexEdge	*cEdge;
929 
930 	for (cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
931 		if (	(cEdge->edge->vertices[0] == v) ||
932 				(cEdge->edge->vertices[1] == v))	return cEdge->edge;
933 	}
934 
935 	return NULL;
936 }
937 
938 
939 ///////////////////////////////////////////////////////////////////////
940 // Class				:	CSVertex
941 // Method				:	sort
942 // Description			:	Sort 1 ring neighborhood
943 // Return Value			:	-
944 // Comments				:
sort(CSVertex ** v,CSEdge * cEdge,CSFace * cFace,int exp)945 void		CSVertex::sort(CSVertex **v,CSEdge *cEdge,CSFace *cFace,int exp) {
946 	CSEdge	*estart	=	cEdge;
947 	int		i;
948 
949 	do {
950 		if (cEdge->vertices[0] == this)	*v++	=	cEdge->vertices[1];
951 		else							*v++	=	cEdge->vertices[0];
952 
953 		exp--;
954 
955 		assert(cFace->numEdges == 4);
956 
957 		for (i=0;i<4;i++) {
958 			if (cFace->vertices[i] == this)	{
959 				*v++	=	cFace->vertices[(i+2) & 3];
960 				break;
961 			}
962 		}
963 
964 		exp--;
965 
966 		assert(i != 4);
967 
968 		cEdge	=	cFace->edges[(i+1) & 3];
969 		if (!((cEdge->vertices[0] == this) || (cEdge->vertices[1] == this)))	cEdge	=	cFace->edges[(i+3) & 3];
970 
971 		if (cEdge->faces[0] == cFace)	cFace	=	cEdge->faces[1];
972 		else							cFace	=	cEdge->faces[0];
973 
974 	} while(cEdge != estart && exp);
975 
976 	assert(exp == 0);
977 }
978 
979 
980 
981 ///////////////////////////////////////////////////////////////////////
982 // Class				:	CSVertex
983 // Method				:	funny
984 // Description			:	Figure out if there's something funny in the neighborhood of the vertex
985 // Return Value			:	TRUE if funny
986 // Comments				:
funny()987 int		CSVertex::funny() {
988 	CVertexEdge	*cEdge;
989 
990 	if (fvalence != valence) {
991 		assert(data.currentFlags & FACE_INTEPOLATEBOUNDARY);
992 		return TRUE;
993 	}
994 
995 	for (cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
996 		if (cEdge->edge->sharpness > 0)	return TRUE;
997 		if (sharpness > 0) return TRUE;
998 
999 		if (cEdge->edge->faces[1] == NULL) {
1000 
1001 			return TRUE;
1002 		}
1003 	}
1004 
1005 	return FALSE;
1006 }
1007 
1008 ///////////////////////////////////////////////////////////////////////
1009 // Class				:	CSVertex
1010 // Method				:	shouldSplit
1011 // Description			:	TRUE if there is a non-quad incident face
1012 // Return Value			:
1013 // Comments				:
shouldSplit()1014 int		CSVertex::shouldSplit() {
1015 	CVertexFace	*cFace;
1016 
1017 	for (cFace=faces;cFace!=NULL;cFace=cFace->next) {
1018 		if (cFace->face->numEdges != 4) return TRUE;
1019 	}
1020 
1021 	return FALSE;
1022 }
1023 
1024 ///////////////////////////////////////////////////////////////////////
1025 // Class				:	CSFace
1026 // Method				:	findEdgeVertices
1027 // Description			:	get the vertex pair bordering an edge
1028 // Return Value			:	-
1029 // Comments				:
findEdgeVertices(int eOrg,int vOrg,CSVertex * & v1,CSVertex * & v2)1030 char	CSFace::findEdgeVertices(int eOrg,int vOrg,CSVertex* &v1,CSVertex* &v2) {
1031 	CSEdge		*cEdge = edges[eOrg];
1032 	CSVertex	*cVert = vertices[vOrg];
1033 	CSFace		*cFace = NULL;
1034 	int			i;
1035 
1036 	if (cEdge->faces[0] == this)	cFace = cEdge->faces[1];
1037 	else							cFace = cEdge->faces[0];
1038 
1039 	if (cFace != NULL){
1040 		for (i=0;i<4;i++) {
1041 			if (cFace->edges[i] == cEdge) {
1042 				if (cFace->vertices[i] == cVert) {
1043 					v1 = cFace->vertices[(i + 2) & 3];
1044 					v2 = cFace->vertices[(i + 3) & 3];
1045 				} else {
1046 					v1 = cFace->vertices[(i + 3) & 3];
1047 					v2 = cFace->vertices[(i + 2) & 3];
1048 					//assert(cFace->vertices[(i+1)&3] != cVert);
1049 				}
1050 				break;
1051 			}
1052 		}
1053 		assert(i!=4);
1054 	} else {
1055 		return 1;
1056 	}
1057 	return 0;
1058 }
1059 
1060 ///////////////////////////////////////////////////////////////////////
1061 // Class				:	CSFace
1062 // Method				:	findCornerVertex
1063 // Description			:	find the vertex corner-opposite by edge walking
1064 // Return Value			:	-
1065 // Comments				:
findCornerVertex(int eOrg,int vOrg,CSVertex * & v)1066 int		CSFace::findCornerVertex(int eOrg,int vOrg,CSVertex *&v) {
1067 	CSEdge		*cEdge = edges[eOrg];
1068 	CSVertex	*cVert = vertices[vOrg];
1069 	CSFace		*cFace = this;
1070 	int i,j;
1071 
1072 	for (j=1;j>=0;j--){
1073 		if (cEdge->faces[0] == cFace)	cFace = cEdge->faces[1];
1074 		else							cFace = cEdge->faces[0];
1075 
1076 		if (cFace == NULL) break;
1077 
1078 		for (i=0;i<4;i++){
1079 			if (cFace->edges[i] == cEdge) {
1080 				if (cFace->vertices[(i+0)&3] == cVert) {
1081 					cEdge = cFace->edges[(i+3)&3];
1082 					if (!j && (cEdge->faces[0] != this) && (cEdge->faces[1] != this) ) {
1083 						v = cFace->vertices[(i+2)&3];
1084 						return TRUE;
1085 					}
1086 				} else {
1087 					cEdge = cFace->edges[(i+1)&3];
1088 					assert(cFace->vertices[(i+1)&3] == cVert);
1089 					if (!j && (cEdge->faces[0] != this) && (cEdge->faces[1] != this) ) {
1090 						v = cFace->vertices[(i+3)&3];
1091 						return TRUE;
1092 					}
1093 				}
1094 				break;
1095 			}
1096 		}
1097 		assert(i!=4);
1098 	}
1099 	return FALSE;
1100 }
1101 
1102 
1103 
1104 
1105 
1106 
1107 
1108 
1109 
1110 
1111 
1112 
1113 
1114 
1115 
1116 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
1117 //
1118 //	Subdivision rules implementation
1119 //
1120 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
1121 
1122 
1123 
1124 
1125 
1126 
1127 
1128 
1129 
1130 
1131 
1132 
1133 ///////////////////////////////////////////////////////////////////////
1134 // Class				:	CSVertex
1135 // Method				:	compute
1136 // Description			:	Compute the vertex / varying
1137 // Return Value			:	-
1138 // Comments				:
compute()1139 void	CSVertex::compute() {
1140 	assert(vertex == NULL);
1141 
1142 	vertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1143 
1144 	if (parentv != NULL)		parentv->compute(vertex);
1145 	else if (parente != NULL)	parente->compute(vertex);
1146 	else if (parentf != NULL)	parentf->compute(vertex);
1147 	else {
1148 		assert(FALSE);
1149 	}
1150 }
1151 
1152 ///////////////////////////////////////////////////////////////////////
1153 // Class				:	CSVertex
1154 // Method				:	compute
1155 // Description			:	Compute the vertex / varying
1156 // Return Value			:	-
1157 // Comments				:
compute(float * vertex)1158 void	CSVertex::compute(float *vertex) {
1159 	CVertexEdge	*cEdge;
1160 	CVertexFace	*cFace;
1161 	float		*tvertex;
1162 	float		sharpness;
1163 	int			numSharp;
1164 
1165 	if (this->vertex == NULL)	compute();
1166 
1167 	tvertex			=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1168 
1169 	for (numSharp=0,sharpness=0,cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
1170 		if (cEdge->edge->sharpness > 0) {
1171 			sharpness	+=	cEdge->edge->sharpness;
1172 			numSharp++;
1173 		}
1174 	}
1175 
1176 	if ((numSharp > 2) || (valence == 2)) {	// We're a corner vertex
1177 		memcpy(vertex,this->vertex,data.vertexSize*sizeof(float));
1178 	} else {											// We're not a corner vertex
1179 		float	*sharpVertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1180 		float	*smoothVertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1181 
1182 		sharpness	/=	(float) numSharp;
1183 
1184 		// Compute the smooth rule
1185 		initVertex(data,smoothVertex);
1186 		initVertex(data,sharpVertex);
1187 
1188 		for (cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
1189 			CSVertex	*oVertex;
1190 
1191 			if (cEdge->edge->vertices[0] == this) oVertex	=	cEdge->edge->vertices[1];
1192 			else {
1193 				assert(cEdge->edge->vertices[1] == this);
1194 				oVertex	=	cEdge->edge->vertices[0];
1195 			}
1196 
1197 			if (oVertex->vertex == NULL)	oVertex->compute();
1198 
1199 			accumVertex(data,smoothVertex,oVertex->vertex);
1200 
1201 			if (cEdge->edge->sharpness > 0) {
1202 				accumVertex(data,sharpVertex,oVertex->vertex);
1203 			}
1204 		}
1205 
1206 		for (cFace=faces;cFace!=NULL;cFace=cFace->next) {
1207 			cFace->face->compute(tvertex);
1208 			accumVertex(data,smoothVertex,tvertex);
1209 		}
1210 
1211 		scaleVertex(data,smoothVertex, 1 / (float) (valence*valence));
1212 		accumVertex(data,smoothVertex,this->vertex,(valence - 2) / (float) valence);
1213 
1214 		scaleVertex(data,sharpVertex, 1.0 / 8.0);
1215 		accumVertex(data,sharpVertex,this->vertex,6.0 / 8.0);
1216 
1217 		if (numSharp == 2) {
1218 			// We're a crease vertex
1219 			if (sharpness >= 1) {
1220 				memcpy(vertex,sharpVertex,data.vertexSize*sizeof(float));
1221 			} else if (sharpness <= 0) {
1222 				memcpy(vertex,smoothVertex,data.vertexSize*sizeof(float));
1223 			} else {
1224 				initVertex(data,vertex);
1225 				accumVertex(data,vertex,smoothVertex,1-sharpness);
1226 				accumVertex(data,vertex,sharpVertex,sharpness);
1227 			}
1228 		} else {
1229 			// We're a dart or a non-crease vertex
1230 			memcpy(vertex,smoothVertex,data.vertexSize*sizeof(float));
1231 		}
1232 	}
1233 
1234 	if (this->sharpness >= 1) {			// sharp corner rule
1235 		memcpy(vertex,this->vertex,data.vertexSize*sizeof(float));
1236 	}
1237 	else if (this->sharpness > 0) {		// smooth corner rule
1238 		scaleVertex(data,vertex,1 - this->sharpness);
1239 		accumVertex(data,vertex,this->vertex,this->sharpness);
1240 	}
1241 }
1242 
1243 
1244 ///////////////////////////////////////////////////////////////////////
1245 // Class				:	CSVertex
1246 // Method				:	compute
1247 // Description			:	Compute the vertex / varying
1248 // Return Value			:	-
1249 // Comments				:
computeVarying(float * varying,float * facevarying)1250 void	CSVertex::computeVarying(float *varying,float *facevarying) {
1251 	if		(parentv != NULL)	parentv->computeVarying(varying,facevarying);
1252 	else if (parente != NULL)	parente->computeVarying(varying,facevarying);
1253 	else if (parentf != NULL)	parentf->computeVarying(varying,facevarying);
1254 	else {
1255 		if (this->varying != NULL) {
1256 			memcpy(varying,this->varying,sizeof(float)*data.varyingSize);
1257 		}
1258 
1259 		if (this->facevarying != NULL) {
1260 			memcpy(facevarying,this->facevarying,sizeof(float)*data.facevaryingSize);
1261 		}
1262 	}
1263 }
1264 
1265 ///////////////////////////////////////////////////////////////////////
1266 // Class				:	CSVertex
1267 // Method				:	computeLimit
1268 // Description			:	Compute the vertex / varying
1269 // Return Value			:	-
1270 // Comments				:
computeLimit(float * vertex)1271 void	CSVertex::computeLimit(float *vertex) {
1272 	CVertexEdge	*cEdge;
1273 	CVertexFace	*cFace;
1274 	float		*tvertex;
1275 	float		sharpness;
1276 	int			numSharp;
1277 
1278 	if (this->vertex == NULL)	compute();
1279 
1280 	tvertex			=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1281 
1282 	for (numSharp=0,sharpness=0,cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
1283 		if (cEdge->edge->sharpness > 0) {
1284 			sharpness	+=	cEdge->edge->sharpness;
1285 			numSharp++;
1286 		}
1287 	}
1288 
1289 	if ((numSharp > 2) || (valence == 2)) {	// We're a corner vertex
1290 		memcpy(vertex,this->vertex,data.vertexSize*sizeof(float));
1291 	} else {											// We're not a corner vertex
1292 		float	*sharpVertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1293 		float	*smoothVertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1294 
1295 		sharpness	/=	(float) numSharp;
1296 
1297 		// Compute the smooth rule
1298 		initVertex(data,smoothVertex);
1299 		initVertex(data,sharpVertex);
1300 
1301 		for (cEdge=edges;cEdge!=NULL;cEdge=cEdge->next) {
1302 			accumVertex(data,smoothVertex,tvertex,4);
1303 
1304 			if (cEdge->edge->sharpness > 0) {
1305 				accumVertex(data,sharpVertex,tvertex);
1306 			}
1307 		}
1308 
1309 		for (cFace=faces;cFace!=NULL;cFace=cFace->next) {
1310 			accumVertex(data,smoothVertex,tvertex);
1311 		}
1312 
1313 		accumVertex(data,smoothVertex,this->vertex,(float) (valence*valence));
1314 		scaleVertex(data,smoothVertex, 1 / (float) (valence*(valence+5)));
1315 
1316 		scaleVertex(data,sharpVertex, 1.0 / 4.0);
1317 		accumVertex(data,sharpVertex,this->vertex,1.0 / 2.0);
1318 
1319 		if (numSharp == 2) {
1320 			// We're a crease vertex
1321 			if (sharpness >= 1) {
1322 				memcpy(vertex,sharpVertex,data.vertexSize*sizeof(float));
1323 			} else if (sharpness <= 0) {
1324 				memcpy(vertex,smoothVertex,data.vertexSize*sizeof(float));
1325 			} else {
1326 				initVertex(data,vertex);
1327 				accumVertex(data,vertex,smoothVertex,1-sharpness);
1328 				accumVertex(data,vertex,sharpVertex,sharpness);
1329 			}
1330 		} else {
1331 			// We're a dart or a non-crease vertex
1332 			memcpy(vertex,smoothVertex,data.vertexSize*sizeof(float));
1333 		}
1334 	}
1335 
1336 	if (this->sharpness >= 1) {			// sharp corner rule
1337 		memcpy(vertex,this->vertex,data.vertexSize*sizeof(float));
1338 	}
1339 	else if (this->sharpness > 0) {		// smooth corner rule
1340 		scaleVertex(data,vertex,1 - this->sharpness);
1341 		accumVertex(data,vertex,this->vertex,this->sharpness);
1342 	}
1343 }
1344 
1345 ///////////////////////////////////////////////////////////////////////
1346 // Class				:	CSEdge
1347 // Method				:	compute
1348 // Description			:	Edge subdivision rule
1349 // Return Value			:	-
1350 // Comments				:
compute(float * vertex)1351 void	CSEdge::compute(float *vertex) {
1352 	float	*tvertex;
1353 	float	*smoothVertex,*sharpVertex;
1354 
1355 	smoothVertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1356 	sharpVertex		=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1357 	tvertex			=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1358 
1359 	if (vertices[0]->vertex == NULL)	vertices[0]->compute();
1360 	if (vertices[1]->vertex == NULL)	vertices[1]->compute();
1361 
1362 	if ((sharpness > 0) || (faces[1] == NULL)) {	// Have to compute the sharp vertex
1363 		initVertex(data,sharpVertex);
1364 		accumVertex(data,sharpVertex,vertices[0]->vertex);
1365 		accumVertex(data,sharpVertex,vertices[1]->vertex);
1366 		scaleVertex(data,sharpVertex,0.5f);
1367 	}
1368 
1369 	if ((sharpness < 1) && (faces[1] != NULL)) {	// Have to compute the smooth vertex
1370 		faces[0]->compute(smoothVertex);
1371 		faces[1]->compute(tvertex);
1372 		accumVertex(data,smoothVertex,tvertex);
1373 		accumVertex(data,smoothVertex,vertices[0]->vertex);
1374 		accumVertex(data,smoothVertex,vertices[1]->vertex);
1375 		scaleVertex(data,smoothVertex,1 / (float) 4);
1376 	}
1377 
1378 	if ((sharpness >= 1) || (faces[1] == NULL))			memcpy(vertex,sharpVertex,data.vertexSize*sizeof(float));
1379 	else if (sharpness <= 0)							memcpy(vertex,smoothVertex,data.vertexSize*sizeof(float));
1380 	else {
1381 		initVertex(data,vertex);
1382 		accumVertex(data,vertex,smoothVertex,(1-sharpness));
1383 		accumVertex(data,vertex,sharpVertex,sharpness);
1384 	}
1385 }
1386 
1387 ///////////////////////////////////////////////////////////////////////
1388 // Class				:	CSEdge
1389 // Method				:	computeVarying
1390 // Description			:	Edge subdivision rule
1391 // Return Value			:	-
1392 // Comments				:
computeVarying(float * varying,float * facevarying)1393 void	CSEdge::computeVarying(float *varying,float *facevarying) {
1394 	float	*varying1,*facevarying1;
1395 	int		i;
1396 
1397 	varying1		=	(float *) ralloc(sizeof(float)*data.varyingSize,data.context->threadMemory);
1398 	facevarying1	=	(float *) ralloc(sizeof(float)*data.facevaryingSize,data.context->threadMemory);
1399 
1400 	vertices[0]->computeVarying(varying,facevarying);
1401 	vertices[1]->computeVarying(varying1,facevarying1);
1402 
1403 	for (i=0;i<data.varyingSize;i++) {
1404 		varying[i]	=	(varying[i] + varying1[i])*0.5f;
1405 	}
1406 
1407 	for (i=0;i<data.facevaryingSize;i++) {
1408 		facevarying[i]	=	(facevarying[i] + facevarying1[i])*0.5f;
1409 	}
1410 }
1411 
1412 ///////////////////////////////////////////////////////////////////////
1413 // Class				:	CSFace
1414 // Method				:	compute
1415 // Description			:	Face subdivision rule
1416 // Return Value			:	-
1417 // Comments				:
compute(float * vertex)1418 void	CSFace::compute(float *vertex) {
1419 	int	i;
1420 
1421 	initVertex(data,vertex);
1422 
1423 	for (i=0;i<numEdges;i++) {
1424 		if (vertices[i]->vertex == NULL)	vertices[i]->compute();
1425 
1426 		accumVertex(data,vertex,vertices[i]->vertex);
1427 	}
1428 
1429 	scaleVertex(data,vertex,1 / (float) numEdges);
1430 }
1431 
1432 
1433 
1434 ///////////////////////////////////////////////////////////////////////
1435 // Class				:	CSFace
1436 // Method				:	computeVarying
1437 // Description			:	Face subdivision rule
1438 // Return Value			:	-
1439 // Comments				:
computeVarying(float * varying,float * facevarying)1440 void	CSFace::computeVarying(float *varying,float *facevarying) {
1441 	float		*varying1,*facevarying1;
1442 	int			i,j;
1443 	const float	scale	=	1 / (float) numEdges;
1444 
1445 	varying1		=	(float *) ralloc(sizeof(float)*data.varyingSize,data.context->threadMemory);
1446 	facevarying1	=	(float *) ralloc(sizeof(float)*data.facevaryingSize,data.context->threadMemory);
1447 
1448 	for (i=0;i<data.varyingSize;i++) {
1449 		varying[i]	=	0;
1450 	}
1451 
1452 	for (i=0;i<data.facevaryingSize;i++) {
1453 		facevarying[i]	=	0;
1454 	}
1455 
1456 	for (j=0;j<numEdges;j++) {
1457 		vertices[j]->computeVarying(varying1,facevarying1);
1458 
1459 		for (i=0;i<data.varyingSize;i++) {
1460 			varying[i]	+=	varying1[i];
1461 		}
1462 
1463 		for (i=0;i<data.facevaryingSize;i++) {
1464 			facevarying[i]	+=	facevarying1[i];
1465 		}
1466 	}
1467 
1468 	for (i=0;i<data.varyingSize;i++) {
1469 		varying[i]	*=	scale;
1470 	}
1471 
1472 	for (i=0;i<data.facevaryingSize;i++) {
1473 		facevarying[i]	*=	scale;
1474 	}
1475 }
1476 
1477 
1478 
1479 
1480 
1481 
1482 
1483 
1484 
1485 
1486 
1487 
1488 
1489 
1490 
1491 
1492 
1493 
1494 
1495 
1496 
1497 
1498 
1499 
1500 
1501 
1502 
1503 
1504 
1505 
1506 
1507 
1508 
1509 
1510 
1511 
1512 
1513 
1514 
1515 
1516 
1517 
1518 
1519 
1520 
1521 
1522 
1523 
1524 
gatherData(CSubdivData & data,int numVertex,CSVertex ** vertices,CSVertex ** varyings,int uniformNumber,float * & vertex,CParameter * & parameters)1525 static void	gatherData(CSubdivData &data,int numVertex,CSVertex **vertices,CSVertex **varyings,int uniformNumber,float *&vertex,CParameter *&parameters) {
1526 	int			i;
1527 	float		*varyingsT,*facevaryingsT;
1528 
1529 	assert(data.vertexSize > 0);
1530 
1531 	vertex		=	(float *) ralloc(data.vertexSize*numVertex*sizeof(float),data.context->threadMemory);
1532 
1533 	for (i=0;i<numVertex;i++) {
1534 		if (vertices[i]->vertex == NULL)	vertices[i]->compute();
1535 
1536 		memcpy(vertex+i*data.vertexSize,vertices[i]->vertex,sizeof(float)*data.vertexSize);
1537 	}
1538 
1539 
1540 	varyingsT		=	(float *) ralloc(data.varyingSize*4*sizeof(float),data.context->threadMemory);
1541 	facevaryingsT	=	(float *) ralloc(data.facevaryingSize*4*sizeof(float),data.context->threadMemory);
1542 
1543 	for (i=0;i<4;i++) {
1544 		varyings[i]->computeVarying(varyingsT + i*data.varyingSize,facevaryingsT + i*data.facevaryingSize);
1545 	}
1546 
1547 	parameters		=	data.parameterList->uniform(uniformNumber,NULL);
1548 	parameters		=	data.parameterList->varying(	varyingsT+0*data.varyingSize,
1549 														varyingsT+1*data.varyingSize,
1550 														varyingsT+2*data.varyingSize,
1551 														varyingsT+3*data.varyingSize,parameters);
1552 	parameters		=	data.parameterList->facevarying(	facevaryingsT+0*data.facevaryingSize,
1553 															facevaryingsT+1*data.facevaryingSize,
1554 															facevaryingsT+2*data.facevaryingSize,
1555 															facevaryingsT+3*data.facevaryingSize,parameters);
1556 }
1557 
1558 
1559 
1560 
1561 
1562 
1563 
1564 
1565 
1566 
1567 
1568 
1569 
1570 
1571 
1572 ///////////////////////////////////////////////////////////////////////
1573 // Class				:	CSubdivMesh
1574 // Method				:	CSubdivMesh
1575 // Description			:	Ctor
1576 // Return Value			:	-
1577 // Comments				:
CSubdivMesh(CAttributes * a,CXform * x,CPl * c,int numFaces,int * numVerticesPerFace,int * vertexIndices,int ntags,const char ** tags,int * nargs,int * intargs,float * floatargs)1578 CSubdivMesh::CSubdivMesh(CAttributes *a,CXform *x,CPl *c,int numFaces,int *numVerticesPerFace,int *vertexIndices,int ntags,const char **tags,int *nargs,int *intargs,float *floatargs) : CObject(a,x) {
1579 	int			i,j,ias,fas;
1580 	const float	*P;
1581 
1582 	atomicIncrement(&stats.numGprims);
1583 
1584 	this->pl					=	c;
1585 	this->numFaces				=	numFaces;
1586 
1587 	// Count the number of faces / vertices
1588 	for (i=0,j=0;i<numFaces;j+=numVerticesPerFace[i],i++);
1589 
1590 	for (numVertices=-1,i=0;i<j;i++) {
1591 		if (vertexIndices[i] > numVertices)	numVertices	=	vertexIndices[i];
1592 	}
1593 	numVertices++;
1594 
1595 	// Create a fresh copy of the parameters
1596 	this->numVerticesPerFace	=	new int[numFaces];		memcpy(this->numVerticesPerFace,numVerticesPerFace,sizeof(int)*numFaces);
1597 	this->vertexIndices			=	new int[j];				memcpy(this->vertexIndices,vertexIndices,sizeof(int)*j);
1598 	this->ntags					=	ntags;
1599 	this->tags					=	NULL;
1600 	this->nargs					=	NULL;
1601 	this->intargs				=	NULL;
1602 	this->floatargs				=	NULL;
1603 
1604 	if (ntags > 0) {
1605 		this->tags				=	new char*[ntags];
1606 		this->nargs				=	new int[ntags*2];		memcpy(this->nargs,nargs,sizeof(int)*ntags*2);
1607 
1608 		for (ias=0,fas=0,i=0;i<ntags;i++) {
1609 			this->tags[i]		=	strdup(tags[i]);
1610 			ias					+=	nargs[i*2];
1611 			fas					+=	nargs[i*2+1];
1612 		}
1613 
1614 		if (ias > 0)	this->intargs			=	new int[ias];			memcpy(this->intargs,intargs,ias*sizeof(int));
1615 		if (fas > 0)	this->floatargs			=	new float[fas];			memcpy(this->floatargs,floatargs,fas*sizeof(float));
1616 	}
1617 
1618 	// Compute the bounding box
1619 	initv(bmin,C_INFINITY);
1620 	initv(bmax,-C_INFINITY);
1621 	for (P=pl->data0,i=0;i<numVertices;i++,P+=3) {
1622 		addBox(bmin,bmax,P);
1623 	}
1624 
1625 	if (pl->data1 != NULL) {
1626 		for (P=pl->data1,i=0;i<numVertices;i++,P+=3) {
1627 			addBox(bmin,bmax,P);
1628 		}
1629 	}
1630 
1631 	xform->transformBound(bmin,bmax);
1632 	makeBound(bmin,bmax);
1633 
1634 	// Create the synch. object
1635 	osCreateMutex(mutex);
1636 }
1637 
1638 ///////////////////////////////////////////////////////////////////////
1639 // Class				:	CSubdivMesh
1640 // Method				:	~CSubdivMesh
1641 // Description			:	Dtor
1642 // Return Value			:	-
1643 // Comments				:
~CSubdivMesh()1644 CSubdivMesh::~CSubdivMesh() {
1645 	int	i;
1646 
1647 	atomicDecrement(&stats.numGprims);
1648 
1649 	delete pl;
1650 	delete [] numVerticesPerFace;
1651 	delete [] vertexIndices;
1652 
1653 	if (ntags > 0) {
1654 		for (i=0;i<ntags;i++) {
1655 			free(tags[i]);
1656 		}
1657 		delete [] tags;
1658 		delete [] nargs;
1659 		if (intargs != NULL)	delete [] intargs;
1660 		if (floatargs != NULL)	delete [] floatargs;
1661 	}
1662 
1663 	// Delete the synch. object
1664 	osDeleteMutex(mutex);
1665 }
1666 
1667 
1668 ///////////////////////////////////////////////////////////////////////
1669 // Class				:	CSubdivMesh
1670 // Method				:	intersect
1671 // Description			:	Intersect the thing
1672 // Return Value			:	-
1673 // Comments				:
intersect(CShadingContext * rasterizer,CRay * cRay)1674 void		CSubdivMesh::intersect(CShadingContext *rasterizer,CRay *cRay) {
1675 
1676 	if (children == NULL)	create(rasterizer);
1677 }
1678 
1679 
1680 ///////////////////////////////////////////////////////////////////////
1681 // Class				:	CSubdivMesh
1682 // Method				:	dice
1683 // Description			:	Dice the primitive
1684 // Return Value			:	-
1685 // Comments				:
dice(CShadingContext * rasterizer)1686 void		CSubdivMesh::dice(CShadingContext *rasterizer) {
1687 
1688 	if (children == NULL)	create(rasterizer);
1689 
1690 	CObject	*cObject,*nObject;
1691 	for (cObject=children;cObject!=NULL;cObject=nObject) {
1692 		nObject	=	cObject->sibling;
1693 
1694 		cObject->attach();
1695 
1696 		rasterizer->drawObject(cObject);
1697 
1698 		cObject->detach();
1699 	}
1700 }
1701 
1702 ///////////////////////////////////////////////////////////////////////
1703 // Class				:	CSubdivMesh
1704 // Method				:	instantiate
1705 // Description			:	Clone the primitive
1706 // Return Value			:	-
1707 // Comments				:
instantiate(CAttributes * a,CXform * x,CRendererContext * c) const1708 void		CSubdivMesh::instantiate(CAttributes *a,CXform *x,CRendererContext *c) const {
1709 	CXform	*nx		=	new CXform(x);
1710 
1711 	nx->concat(xform);	// Concetenate the local xform
1712 
1713 	if (a == NULL)	a	=	attributes;
1714 
1715 	c->addObject(new CSubdivMesh(a,nx,pl->clone(a),numFaces,numVerticesPerFace,vertexIndices,ntags,(const char **) tags,nargs,intargs,floatargs));
1716 }
1717 
1718 
1719 ///////////////////////////////////////////////////////////////////////
1720 // Class				:	CSubdivMesh
1721 // Method				:	split
1722 // Description			:	Split this into smaller primitives
1723 // Return Value			:	-
1724 // Comments				:
create(CShadingContext * context)1725 void		CSubdivMesh::create(CShadingContext *context) {
1726 	int			i;
1727 	int			j,k;
1728 	CSFace		**faces;
1729 	CSVertex	**vertices;
1730 	int			*cnargs;
1731 	int			*cintargs;
1732 	float		*cfloatargs;
1733 	int			*cvertexIndex;
1734 	CSubdivData	data;
1735 	CObject		*allChildren;
1736 
1737 	osLock(mutex);
1738 	if (children != NULL) {
1739 		osUnlock(mutex);
1740 		return;
1741 	}
1742 
1743 	memBegin(context->threadMemory);
1744 
1745 	// Transform the core
1746 	pl->transform(xform);
1747 
1748 	data.vertexSize			=	0;
1749 	data.varyingSize		=	0;
1750 	data.facevaryingSize	=	0;
1751 	data.vertexData			=	NULL;
1752 	data.varyingData		=	NULL;
1753 	data.facevaryingData	=	NULL;
1754 
1755 	data.irregularDepth		=	5;
1756 	data.irregularVertices	=	NULL;
1757 	data.irregularRing		=	NULL;
1758 	data.vd					=	NULL;
1759 	data.currentAttributes	=	NULL;
1760 	data.currentXform		=	NULL;
1761 	data.currentFlags		=	0;
1762 	data.parameterList		=	NULL;
1763 
1764 	data.context			=	context;
1765 
1766 	data.vd					=	pl->vertexData();
1767 	data.currentFlags		=	0;
1768 	data.currentAttributes	=	this->attributes;
1769 	data.currentXform		=	this->xform;
1770 	data.parameterList		=	this->pl;
1771 
1772 	// Collect the misc data
1773 	data.vertexData			=	NULL;			pl->collect(data.vertexSize,data.vertexData,CONTAINER_VERTEX,context->threadMemory);
1774 	data.varyingData		=	NULL;			pl->collect(data.varyingSize,data.varyingData,CONTAINER_VARYING,context->threadMemory);
1775 	data.facevaryingData	=	NULL;			pl->collect(data.facevaryingSize,data.facevaryingData,CONTAINER_FACEVARYING,context->threadMemory);
1776 
1777 	faces					=	(CSFace **)		ralloc(numFaces*sizeof(CSFace *),data.context->threadMemory);
1778 	vertices				=	(CSVertex **)	ralloc(numVertices*sizeof(CSVertex *),data.context->threadMemory);
1779 
1780 	// Create the vertices and copy the vertex / varying data over
1781 	for (i=0;i<numVertices;i++)	{
1782 		const float	*src			=	data.vertexData + i*data.vertexSize;
1783 		float		*dest;
1784 		int			k;
1785 
1786 		vertices[i]					=	new (data.context) CSVertex(data);
1787 		dest = vertices[i]->vertex	=	(float *) ralloc(data.vertexSize*sizeof(float),data.context->threadMemory);
1788 
1789 		for (k=0;k<data.vertexSize;k++)	*dest++	=	*src++;
1790 	}
1791 
1792 	if (data.varyingData != NULL) {
1793 		for (i=0;i<numVertices;i++) {
1794 			vertices[i]->varying	=	data.varyingData + i*data.varyingSize;
1795 		}
1796 	}
1797 
1798 	// Create the faces
1799 	for (i=0;i<numFaces;i++) {
1800 		faces[i]				=	new (data.context) CSFace(data,i);
1801 	}
1802 
1803 	// Manage the connectivity
1804 	for (i=0,cvertexIndex=vertexIndices;i<numFaces;i++) {
1805 		CSFace	*cFace			=	faces[i];
1806 		int		numEdges		=	numVerticesPerFace[i];
1807 		cFace->numEdges			=	numEdges;
1808 		cFace->vertices			=	(CSVertex **)	ralloc(numEdges*sizeof(CSVertex *),data.context->threadMemory);
1809 		cFace->edges			=	(CSEdge **)		ralloc(numEdges*sizeof(CSEdge *),data.context->threadMemory);
1810 
1811 		// Set the vertices belonging to a face
1812 		for (j=0;j<numEdges;j++) {
1813 			cFace->vertices[j]	=	vertices[*cvertexIndex++];
1814 		}
1815 
1816 		// Figure out the edges
1817 		for (j=0;j<numEdges;j++) {
1818 			CSEdge	*cEdge;
1819 
1820 			if ((cEdge = cFace->vertices[j]->edgeExists(cFace->vertices[(j+1) % numEdges])) == NULL) {
1821 				cEdge				=	new (data.context) CSEdge(data);
1822 				cEdge->vertices[0]	=	cFace->vertices[j];
1823 				cEdge->vertices[1]	=	cFace->vertices[(j+1) % numEdges];
1824 				cEdge->vertices[0]->addEdge(cEdge);
1825 				cEdge->vertices[1]->addEdge(cEdge);
1826 			}
1827 
1828 			cFace->edges[j]	=	cEdge;
1829 		}
1830 
1831 		for (j=0;j<cFace->numEdges;j++) {
1832 			cFace->vertices[j]->addFace(cFace);
1833 			cFace->edges[j]->addFace(cFace);
1834 		}
1835 	}
1836 
1837 	// Process the tags
1838 	for (i=0,cnargs=nargs,cintargs=intargs,cfloatargs=floatargs;i<ntags;i++) {
1839 		if (strcmp(tags[i],RI_HOLE) == 0) {
1840 			if (cnargs[1] != 0)	error(CODE_RANGE,"Hole takes no floating point arguments\n");
1841 			for (j=0;j<cnargs[0];j++) {
1842 				faces[cintargs[j]]->hole	=	TRUE;
1843 			}
1844 		} else if (strcmp(tags[i],RI_CREASE) == 0) {
1845 			for (j=0;j<cnargs[0]-1;j++) {
1846 				CSVertex	*v0	=	vertices[cintargs[j]];
1847 				CSVertex	*v1	=	vertices[cintargs[j+1]];
1848 				CSEdge		*cEdge;
1849 
1850 				cEdge			=	v0->edgeExists(v1);
1851 
1852 				if (cEdge != NULL) {
1853 					cEdge->sharpness	=	min(cfloatargs[0],10);
1854 				} else {
1855 					error(CODE_RANGE,"The edge between vertices %d-%d not found\n",cintargs[j],cintargs[j+1]);
1856 				}
1857 			}
1858 			if (cnargs[1] != 1) {
1859 				error(CODE_RANGE,"Creases expect exactly 1 float argument\n");
1860 			}
1861 		} else if (strcmp(tags[i],RI_INTERPOLATEBOUNDARY) == 0) {
1862 			data.currentFlags	|=	FACE_INTEPOLATEBOUNDARY;
1863 		} else if (strcmp(tags[i],RI_CORNER) == 0) {
1864 			if (cnargs[1] == cnargs[0]) {
1865 				for (j=0;j<cnargs[0];j++) {
1866 					vertices[cintargs[j]]->sharpness = cfloatargs[j];
1867 				}
1868 			} else if (cnargs[1] == 1) {
1869 				for (j=0;j<cnargs[0];j++) {
1870 					vertices[cintargs[j]]->sharpness = cfloatargs[0];
1871 				}
1872 			} else {
1873 				error(CODE_RANGE,"Corner has 1 or n float arguments\n");
1874 			}
1875 		} else {
1876 			error(CODE_BADTOKEN,"Unknown subdivision tag: \"%s\"\n",tags[i]);
1877 		}
1878 
1879 		cintargs	+=	cnargs[0];
1880 		cfloatargs	+=	cnargs[1];
1881 		cnargs		+=	2;
1882 	}
1883 
1884 	// Add sharp creases when we've got an interpolateboundary tag
1885 	// Note: corner in the literature refers to v.valence == 2,
1886 	// whereas the spec overloads corners as tags to mean sharp vertices
1887 	if (data.currentFlags & FACE_INTEPOLATEBOUNDARY) {
1888 		for (i=0;i<numFaces;i++) {
1889 			CSFace	*cFace			=	faces[i];
1890 			int		numEdges		=	numVerticesPerFace[i];
1891 
1892 			// Figure out the edges
1893 			for (j=0;j<numEdges;j++) {
1894 				CSEdge	*cEdge = cFace->edges[j];
1895 
1896 				if (cEdge->faces[1] == NULL) {
1897 					cEdge->sharpness = 10;
1898 				}
1899 			}
1900 		}
1901 	}
1902 
1903 	// Finalize the faces
1904 	allChildren	=	NULL;
1905 	for (k=0,i=0;i<numFaces;i++) {
1906 
1907 		// Set the facevarying parameters
1908 		for (j=0;j<faces[i]->numEdges;j++) {
1909 			faces[i]->vertices[j]->facevarying	=	data.facevaryingData + (k+j)*data.facevaryingSize;
1910 
1911 			// Check for degenerate faces
1912 			const int val	= faces[i]->vertices[j]->valence;
1913 			const int fval	= faces[i]->vertices[j]->fvalence;
1914 			if((val == 1))					{ warning(CODE_CONSISTENCY,"Subdivision mesh has hanging vertex");			k    +=    faces[i]->numEdges;	goto skipFace; }
1915 			if((val == 2) && (fval != 1)) 	{ warning(CODE_CONSISTENCY,"Subdivision mesh is degenerate (face %d)\n",i); k    +=    faces[i]->numEdges;	goto skipFace; }
1916 			if((val >= 3) && (fval > val)) 	{ warning(CODE_CONSISTENCY,"Subdivision mesh is degenerate (face %d)\n",i); k    +=    faces[i]->numEdges;	goto skipFace; }
1917 		}
1918 
1919 		k	+=	j;
1920 
1921 		// Finally, create the face
1922 		faces[i]->create(allChildren);
1923 
1924 		skipFace:
1925 			;		// intentionally empty
1926 	}
1927 
1928 	// Re-claim the memory
1929 	memEnd(context->threadMemory);
1930 
1931 	// Set the children objects
1932 	setChildren(context,allChildren);
1933 
1934 	if (i==0) warning(CODE_CONSISTENCY,"Subdivision mesh is trivial (skipped)\n");
1935 
1936 	osUnlock(mutex);
1937 }
1938 
1939