2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.com
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Implements the classes for subdivision surfaces.
23
\author Paul C. Gregory (pgregory@aqsis.com)
26
#include "subdivision2.h"
32
START_NAMESPACE( Aqsis )
35
//------------------------------------------------------------------------------
40
CqSubdivision2::CqSubdivision2( )
41
: CqMotionSpec<boost::shared_ptr<CqPolygonPoints> >( boost::shared_ptr<CqPolygonPoints>() ),
42
m_bInterpolateBoundary( TqFalse ),
48
//------------------------------------------------------------------------------
53
CqSubdivision2::CqSubdivision2( const boost::shared_ptr<CqPolygonPoints>& pPoints ) : CqMotionSpec<boost::shared_ptr<CqPolygonPoints> >(pPoints), m_bInterpolateBoundary( TqFalse ), m_fFinalised(TqFalse)
55
// Store the reference to our points.
56
AddTimeSlot( 0, pPoints );
58
STATS_INC( GPR_subdiv );
62
//------------------------------------------------------------------------------
67
CqSubdivision2::~CqSubdivision2()
69
// Delete the array of laths generated during the facet adding phase.
70
for(std::vector<CqLath*>::const_iterator iLath=apLaths().begin(); iLath!=apLaths().end(); iLath++)
71
if(*iLath) delete(*iLath);
75
//------------------------------------------------------------------------------
77
* Get a pointer to a lath referencing the specified facet index.
78
* The returned lath pointer can be any lath on the edge of the facet.
79
* Asserts if the facet index is invalid.
81
* @param iIndex Index of the facet to query.
83
* @return Pointer to a lath on the facet.
85
CqLath* CqSubdivision2::pFacet(TqInt iIndex)
87
assert(iIndex < static_cast<TqInt>(m_apFacets.size()));
88
return(m_apFacets[iIndex]);
92
//------------------------------------------------------------------------------
94
* Get a pointer to a lath which references the specified vertex index.
95
* The returned lath pointer can be any lath which references the vertex.
96
* Asserts if the vertex index is invalid.
98
* @param iIndex Index of the vertex to query.
100
* @return Pointer to a lath on the vertex.
102
CqLath* CqSubdivision2::pVertex(TqInt iIndex)
104
assert(iIndex < static_cast<TqInt>(m_aapVertices.size()) && m_aapVertices[iIndex].size() >= 1);
105
return(m_aapVertices[iIndex][0]);
109
//------------------------------------------------------------------------------
111
* Initialise the topology class to store the specified number of vertices.
112
* Use this function to prepare the topology structure to receive a number of
113
* vertices then use SetVertex to initialise them.
115
* @param cVerts Then number of vertices that will be needed.
117
void CqSubdivision2::Prepare(TqInt cVerts)
119
// Initialise the array of vertex indexes to the appropriate size.
120
m_aapVertices.resize(cVerts);
122
m_fFinalised=TqFalse;
126
//------------------------------------------------------------------------------
128
* Add a completely new vertex to the list.
129
* Appends a new vertex to the end of the list, updating the referencing
132
* @return The index of the new point.
134
void CqSubdivision2::AddVertex(CqLath* pVertex, TqInt& iVIndex, TqInt& iFVIndex)
138
// If -1 is passed in as the 'vertex' class index, we must create a new value.
139
TqBool fNewVertex = iVIndex < 0;
141
std::vector<CqParameter*>::iterator iUP;
144
for( iTime = 0; iTime < cTimes(); iTime++ )
146
for( iUP = pPoints( iTime )->aUserParams().begin(); iUP != pPoints( iTime )->aUserParams().end(); iUP++ )
148
TqInt iIndex = ( *iUP )->Size();
149
// Store the index in the return variable based on its type.
150
if( ( *iUP )->Class() == class_vertex || ( *iUP )->Class() == class_varying )
154
assert( iVIndex<0 || iVIndex==iIndex );
156
( *iUP )->SetSize( iIndex+1 );
157
// Resize the vertex lath
158
m_aapVertices.resize(iVIndex+1);
163
else if( ( *iUP )->Class() == class_facevarying )
165
assert( iFVIndex==0 || iFVIndex==iIndex );
167
( *iUP )->SetSize( iIndex+1 );
170
switch ( ( *iUP )->Type() )
174
CqParameterTyped<TqFloat, TqFloat>* pParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( ( *iUP ) );
175
CreateVertex( pParam, pVertex, iIndex );
181
CqParameterTyped<TqInt, TqFloat>* pParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( ( *iUP ) );
182
CreateVertex( pParam, pVertex, iIndex );
190
CqParameterTyped<CqVector3D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
191
CreateVertex( pParam, pVertex, iIndex );
197
CqParameterTyped<CqColor, CqColor>* pParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( ( *iUP ) );
198
CreateVertex( pParam, pVertex, iIndex );
204
CqParameterTyped<CqVector4D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( ( *iUP ) );
205
CreateVertex( pParam, pVertex, iIndex );
211
//CqParameterTyped<CqString, CqString>* pParam = static_cast<CqParameterTyped<CqString, CqString>*>( ( *iUP ) );
212
//CreateVertex( pParam, pVertex, iIndex );
218
//CqParameterTyped<CqMatrix, CqMatrix>* pParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( ( *iUP ) );
219
//CreateVertex( pParam, pVertex, iIndex );
225
// left blank to avoid compiler warnings about unhandled types
235
//------------------------------------------------------------------------------
237
* Add a completely new vertex to the list.
238
* Appends a new vertex to the end of the list, updating the referencing
241
* @return The index of the new point.
243
void CqSubdivision2::AddEdgeVertex(CqLath* pVertex, TqInt& iVIndex, TqInt& iFVIndex )
247
// If -1 is passed in as the 'vertex' class index, we must create a new value.
248
TqBool fNewVertex = iVIndex < 0;
250
std::vector<CqParameter*>::iterator iUP;
253
for( iTime = 0; iTime < cTimes(); iTime ++ )
255
for ( iUP = pPoints( iTime )->aUserParams().begin(); iUP != pPoints( iTime )->aUserParams().end(); iUP++ )
257
TqInt iIndex = ( *iUP )->Size();
258
// Store the index in the return variable based on its type.
259
if( ( *iUP )->Class() == class_vertex || ( *iUP )->Class() == class_varying )
263
assert( iVIndex<0 || iVIndex==iIndex );
265
( *iUP )->SetSize( iIndex+1 );
266
// Resize the vertex lath
267
m_aapVertices.resize(iVIndex+1);
272
else if( ( *iUP )->Class() == class_facevarying )
274
assert( iFVIndex==0 || iFVIndex==iIndex );
276
( *iUP )->SetSize( iIndex+1 );
279
switch ( ( *iUP )->Type() )
283
CqParameterTyped<TqFloat, TqFloat>* pParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( ( *iUP ) );
284
CreateEdgeVertex( pParam, pVertex, iIndex );
290
CqParameterTyped<TqInt, TqFloat>* pParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( ( *iUP ) );
291
CreateEdgeVertex( pParam, pVertex, iIndex );
299
CqParameterTyped<CqVector3D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
300
CreateEdgeVertex( pParam, pVertex, iIndex );
306
CqParameterTyped<CqColor, CqColor>* pParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( ( *iUP ) );
307
CreateEdgeVertex( pParam, pVertex, iIndex );
313
CqParameterTyped<CqVector4D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( ( *iUP ) );
314
CreateEdgeVertex( pParam, pVertex, iIndex );
320
//CqParameterTyped<CqString, CqString>* pParam = static_cast<CqParameterTyped<CqString, CqString>*>( ( *iUP ) );
321
//CreateEdgeVertex( pParam, pVertex, iIndex );
327
//CqParameterTyped<CqMatrix, CqMatrix>* pParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( ( *iUP ) );
328
//CreateEdgeVertex( pParam, pVertex, iIndex );
334
// left blank to avoid compiler warnings about unhandled types
343
//------------------------------------------------------------------------------
345
* Add a completely new vertex to the list.
346
* Appends a new vertex to the end of the list, updating the referencing
349
* @return The index of the new point.
351
void CqSubdivision2::AddFaceVertex(CqLath* pVertex, TqInt& iVIndex, TqInt& iFVIndex)
356
std::vector<CqParameter*>::iterator iUP;
359
for( iTime = 0; iTime < cTimes(); iTime++ )
361
for ( iUP = pPoints( iTime )->aUserParams().begin(); iUP != pPoints( iTime )->aUserParams().end(); iUP++ )
363
TqInt iIndex = ( *iUP )->Size();
364
( *iUP )->SetSize( iIndex+1 );
365
// Store the index in the return variable based on its type.
366
if( ( *iUP )->Class() == class_vertex || ( *iUP )->Class() == class_varying )
368
assert( iVIndex==0 || iVIndex==iIndex );
371
else if( ( *iUP )->Class() == class_facevarying )
373
assert( iFVIndex==0 || iFVIndex==iIndex );
377
switch ( ( *iUP )->Type() )
381
CqParameterTyped<TqFloat, TqFloat>* pParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( ( *iUP ) );
382
CreateFaceVertex( pParam, pVertex, iIndex );
388
CqParameterTyped<TqInt, TqFloat>* pParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( ( *iUP ) );
389
CreateFaceVertex( pParam, pVertex, iIndex );
397
CqParameterTyped<CqVector3D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
398
CreateFaceVertex( pParam, pVertex, iIndex );
404
CqParameterTyped<CqColor, CqColor>* pParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( ( *iUP ) );
405
CreateFaceVertex( pParam, pVertex, iIndex );
411
CqParameterTyped<CqVector4D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( ( *iUP ) );
412
CreateFaceVertex( pParam, pVertex, iIndex );
418
//CqParameterTyped<CqString, CqString>* pParam = static_cast<CqParameterTyped<CqString, CqString>*>( ( *iUP ) );
419
//CreateFaceVertex( pParam, pVertex, iIndex );
425
//CqParameterTyped<CqMatrix, CqMatrix>* pParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( ( *iUP ) );
426
//CreateFaceVertex( pParam, pVertex, iIndex );
432
// left blank to avoid compiler warnings about unhandled types
440
// Resize the vertex lath
441
m_aapVertices.resize(iVIndex+1);
445
//------------------------------------------------------------------------------
447
* Add a new facet to the topology structure.
448
* Adds the facet by adding new laths for the specified vertex indices, and
449
* linking them to each other clockwise about the facet. By convention, as
450
* outside of the topology structure facets are stored counter clockwise, the
451
* vertex indices should be passed to this function as counter clockwise and
452
* they will be internally altered to specify the facet as clockwise.
454
* @param cVerts The number of vertices in the facet.
455
* @param pIndices Pointer to an array of vertex indices.
457
* @return Pointer to one of the laths which represent this new
458
* facet in the topology structure.
460
CqLath* CqSubdivision2::AddFacet(TqInt cVerts, TqInt* pIndices, TqInt iFVIndex)
462
CqLath* pLastLath=NULL;
463
CqLath* pFirstLath=NULL;
464
// Add the laths for this facet, referencing the appropriate vertexes as we go.
465
for(TqInt iVert = 0; iVert < cVerts; iVert++)
467
CqLath* pNewLath = new CqLath();
468
pNewLath->SetVertexIndex(pIndices[iVert]);
469
pNewLath->SetFaceVertexIndex(iFVIndex+iVert);
472
pNewLath->SetpClockwiseFacet(pLastLath);
474
m_apLaths.push_back(pNewLath);
475
pLastLath = pNewLath;
476
if(iVert == 0) pFirstLath = pLastLath;
478
// We also need to keep up to date a complete list of which laths refer to which
479
// vertices to aid us in finalising the topology structure later.
480
m_aapVertices[pIndices[iVert]].push_back(pLastLath);
482
// complete the chain by linking the last one as the next clockwise one to the first.
483
pFirstLath->SetpClockwiseFacet(pLastLath);
485
// Add the start lath in as the one referring to this facet in the list.
486
m_apFacets.push_back(pFirstLath);
492
//------------------------------------------------------------------------------
494
* Finalise the linkage of the laths.
495
* After adding vertices and facets, call this to complete the linkage of the
496
* laths. To overcome any non-manifold areas in the mesh, this function may
497
* change the topology in order to produce a manifold mesh, or series of
498
* manifold meshes. This also means that all facets in the mesh may no longer
499
* be joined in a complete loop, so care must be taken when traversing the
500
* topology to ensure that all facets are processed.
502
TqBool CqSubdivision2::Finalise()
504
for(std::vector<std::vector<CqLath*> >::const_iterator ivert=m_aapVertices.begin(); ivert!=m_aapVertices.end(); ivert++)
506
TqInt cLaths = (*ivert).size();
508
// If there is only one lath, it can't be connected to anything.
509
if(cLaths<=1) continue;
511
// Create an array for the laths on this vertex that have been visited.
512
std::vector<TqBool> aVisited;
513
aVisited.resize(cLaths);
516
// Initialise it to all false.
517
aVisited.assign(cLaths, TqFalse);
519
CqLath* pCurrent = (*ivert)[0];
520
CqLath* pStart = pCurrent;
524
TqBool fDone = TqFalse;
527
// Find a clockwise vertex match for the counterclockwise vertex index of this lath.
528
TqInt ccwVertex = pCurrent->ccf()->VertexIndex();
530
for(iLath = 0; iLath < cLaths; iLath++)
532
// Only check non-visited laths.
533
if(!aVisited[iLath] && (*ivert)[iLath]->cf()->VertexIndex() == ccwVertex)
535
pCurrent->SetpClockwiseVertex((*ivert)[iLath]);
536
pCurrent = (*ivert)[iLath];
538
// Mark the linked to lath as visited.
539
aVisited[iLath] = TqTrue;
545
// If we didn't find a match then we are done.
546
fDone = iLath==cLaths;
549
// If the last lath wasn't linked, then we have a boundary condition, so
550
// start again from the initial lath and process backwards.
551
if(NULL == pCurrent->cv())
556
// Find a counterclockwise vertex match for the clockwise vertex index of this lath.
557
TqInt cwVertex = pStart->cf()->VertexIndex();
559
for(iLath = 0; iLath < cLaths; iLath++)
561
// Only check non-visited laths.
562
if(!aVisited[iLath] && (*ivert)[iLath]->ccf()->VertexIndex() == cwVertex)
564
// Link the current to the match.
565
(*ivert)[iLath]->SetpClockwiseVertex(pStart);
566
// Mark the linked to lath as visited.
567
aVisited[iStart] = TqTrue;
569
pStart = (*ivert)[iLath];
575
// If we didn't find a match then we are done.
576
fDone = iLath==cLaths;
579
aVisited[iStart] = TqTrue;
581
// If we have not visited all the laths referencing this vertex, then we have a non-manifold situation.
582
if(cVisited < cLaths)
588
m_fFinalised = TqTrue;
593
#define modulo(a, b) (a * b >= 0 ? a % b : (a % b) + b)
594
struct SqFaceLathList {
595
CqLath* pA, *pB, *pC, *pD;
598
void CqSubdivision2::SubdivideFace(CqLath* pFace, std::vector<CqLath*>& apSubFaces)
602
// If this has already beed subdivided then skip it.
603
if( pFace->pFaceVertex() )
606
std::vector<CqLath*> aQvf;
607
pFace->pFaceVertex()->Qvf(aQvf);
608
// Fill in the lath pointers to the same laths that reference the faces in the topology list. This ensures that
609
// the dicing routine will still get the lath it expects in the corner for reading data out.
610
std::vector<CqLath*>::iterator iVF;
611
for( iVF = aQvf.begin(); iVF != aQvf.end(); iVF++ )
612
apSubFaces.push_back( (*iVF)->ccf()->ccf() );
616
// First make sure that the appropriate neighbour facets have been subdivided if this is >0 level face.
617
if( pFace->pParentFacet() )
619
std::vector<CqLath*> aQff;
620
std::vector<CqLath*> apSubFaces2;
621
pFace->pParentFacet()->Qff( aQff );
622
std::vector<CqLath*>::iterator iF;
623
for( iF = aQff.begin(); iF != aQff.end(); iF++ )
625
if( NULL == (*iF)->pFaceVertex() )
626
SubdivideFace(*iF, apSubFaces2);
630
std::vector<CqLath*> aQfv;
631
std::vector<TqInt> aVertices;
632
std::vector<TqInt> aFVertices;
635
TqInt n = aQfv.size();
637
aVertices.resize((2*n)+1);
638
aFVertices.resize((2*n)+1);
640
// Clear the return array for subdface indices.
643
// First of all setup the points.
646
// Create new point for the face midpoint.
647
TqInt iVert=-1, iFVert=-1;
648
AddFaceVertex(pFace, iVert, iFVert);
650
// Store the index, for later lath creation
651
aVertices[2*n] = iVert;
652
aFVertices[2*n] = iFVert;
654
// Create new points for the edge midpoints.
655
for(i = 0; i < n; i++)
657
TqInt iVert=-1, iFVert=-2;
658
// Create new vertices for the edge mid points.
659
if( aQfv[i]->ec() && NULL != aQfv[i]->ec()->pMidVertex() )
660
// There is already a next level vertex for this, so reuse the 'vertex' class index.
661
iVert = aQfv[i]->ec()->pMidVertex()->VertexIndex();
662
// Create new vertex for the edge midpoint.
663
AddEdgeVertex(aQfv[i], iVert, iFVert);
665
// Store the index, for later lath creation
666
aVertices[i+n] = iVert;
667
aFVertices[i+n] = iFVert;
670
// Create new points for the existing vertices
671
for(i = 0; i < n; i++)
673
TqInt iVert=-1, iFVert=-3;
674
// Create new vertices for the original points.
675
if( aQfv[i]->pChildVertex() )
676
// There is already a next level vertex for this, so reuse the 'vertex' class index.
677
iVert = aQfv[i]->pChildVertex()->VertexIndex();
679
// Create a new vertex for the next level
680
AddVertex(aQfv[i], iVert, iFVert);
682
// Store the index, for later lath creation
683
aVertices[i] = iVert;
684
aFVertices[i] = iFVert;
687
// Now create new laths for the new facets
688
std::vector<SqFaceLathList> apFaceLaths;
689
apFaceLaths.resize(n);
691
for( i = 0; i < n; i++ )
693
// For each facet, create 4 laths and join them in the order of the facet
694
CqLath* pLathA = apFaceLaths[i].pA = new CqLath( aVertices[i], aFVertices[i] );
695
m_apLaths.push_back(pLathA);
696
CqLath* pLathB = apFaceLaths[i].pB = new CqLath( aVertices[(modulo((i+1),n))+n], aFVertices[(modulo((i+1),n))+n] );
697
m_apLaths.push_back(pLathB);
698
CqLath* pLathC = apFaceLaths[i].pC = new CqLath( aVertices[2*n], aFVertices[2*n] );
699
m_apLaths.push_back(pLathC);
700
CqLath* pLathD = apFaceLaths[i].pD = new CqLath( aVertices[i+n], aFVertices[i+n] );
701
m_apLaths.push_back(pLathD);
702
pLathA->SetpClockwiseFacet(pLathB);
703
pLathB->SetpClockwiseFacet(pLathC);
704
pLathC->SetpClockwiseFacet(pLathD);
705
pLathD->SetpClockwiseFacet(pLathA);
706
pLathA->SetpParentFacet(pFace);
707
pLathB->SetpParentFacet(pFace);
708
pLathC->SetpParentFacet(pFace);
709
pLathD->SetpParentFacet(pFace);
711
// Fill in the vertex references table for these vertices.
712
m_aapVertices[pLathA->VertexIndex()].push_back(pLathA);
713
m_aapVertices[pLathB->VertexIndex()].push_back(pLathB);
714
m_aapVertices[pLathC->VertexIndex()].push_back(pLathC);
715
m_aapVertices[pLathD->VertexIndex()].push_back(pLathD);
717
// Set the child vertex pointer for all laths which reference the A vertex of this facet
718
// so that we can use them when subdividing other faces.
719
CqLath* pNextV = aQfv[i];
722
pNextV->SetpChildVertex(pLathA);
723
pNextV = pNextV->cv();
724
}while( pNextV && pNextV != aQfv[i]);
725
// Make sure that if we have hit a boundary, we go backwards from the start point until we hit the boundary that
729
pNextV = aQfv[i]->ccv();
730
// We know we are going to hit a boundary in this direction as well so we can just look for that
731
// case as a terminator.
734
assert( pNextV != aQfv[i] );
735
pNextV->SetpChildVertex(pLathA);
736
pNextV = pNextV->ccv();
740
// For this edge of the original face, set a ponter to the new midpoint lath, so that we can
741
// use it when subdividing neighbour facets.
742
aQfv[i]->SetpMidVertex(pLathD);
744
// Transfer sharpness information
745
float sharpness = EdgeSharpness( aQfv[ i ] );
746
if( sharpness > 0.0f )
747
AddSharpEdge( pLathA, sharpness * sharpness );
749
sharpness = EdgeSharpness( aQfv[ modulo( (i+1),n ) ] );
750
if( sharpness > 0.0f )
751
AddSharpEdge( pLathB, sharpness * sharpness );
753
if( CornerSharpness( aQfv[ i ] ) > 0.0f )
754
AddSharpCorner( pLathA, CornerSharpness( aQfv[ i ] ) );
756
// Store a lath reference for the facet.
757
apSubFaces.push_back( pLathA );
758
m_apFacets.push_back( pLathA );
761
// Now connect up the laths we have created.
762
// The clcckwise face connections will have already been made, we need to fixup and clockwise
763
// vertex connections we can.
764
for( i = 0; i < n; i++ )
766
// Set the facet point reference for all laths representing this facet.
767
aQfv[i]->SetpFaceVertex(apFaceLaths[i].pC);
768
// Connect midpoints clockwise vertex pointers.
769
apFaceLaths[((i+1)%n)].pD->SetpClockwiseVertex( apFaceLaths[i].pB );
770
// Connect all laths around the new face point.
771
apFaceLaths[i].pC->SetpClockwiseVertex( apFaceLaths[ ((i+1)%n) ].pC );
773
// Connect the new corner vertices, this is only possible if neighbouring facets have previously been
775
std::vector<CqLath*>::iterator iVertLath;
776
for( iVertLath = m_aapVertices[apFaceLaths[i].pA->VertexIndex()].begin(); iVertLath != m_aapVertices[apFaceLaths[i].pA->VertexIndex()].end(); iVertLath++ )
778
if( (*iVertLath)->cf()->VertexIndex() == apFaceLaths[i].pD->VertexIndex() )
779
apFaceLaths[i].pA->SetpClockwiseVertex( (*iVertLath ) );
780
if( (*iVertLath)->ccf()->VertexIndex() == apFaceLaths[i].pB->VertexIndex() )
781
(*iVertLath)->SetpClockwiseVertex( apFaceLaths[i].pA );
785
for( i = 0; i < n; i++ )
787
// Connect the new edge midpoint vertices to any neighbours, this is only possible if neighbouring facets have previously been
789
std::vector<CqLath*>::iterator iVertLath;
790
for( iVertLath = m_aapVertices[apFaceLaths[i].pB->VertexIndex()].begin(); iVertLath != m_aapVertices[apFaceLaths[i].pB->VertexIndex()].end(); iVertLath++ )
792
if( (*iVertLath)->cf()->VertexIndex() == apFaceLaths[i].pA->VertexIndex() )
793
apFaceLaths[i].pB->SetpClockwiseVertex( (*iVertLath ) );
795
for( iVertLath = m_aapVertices[apFaceLaths[i].pD->VertexIndex()].begin(); iVertLath != m_aapVertices[apFaceLaths[i].pD->VertexIndex()].end(); iVertLath++ )
797
if( (*iVertLath)->ccf()->VertexIndex() == apFaceLaths[i].pA->VertexIndex() )
798
(*iVertLath )->SetpClockwiseVertex( apFaceLaths[i].pD );
801
//OutputInfo("out.dat");
805
void CqSubdivision2::OutputMesh(const char* fname, std::vector<CqLath*>* paFaces)
807
std::ofstream file(fname);
808
std::vector<CqLath*> aQfv;
811
for( i = 0; i < cVertices(); i++ )
813
CqVector3D vec = pPoints()->P()->pValue()[ pVertex( i )->VertexIndex() ];
814
file << "v " << vec.x() << " " << vec.y() << " " << vec.z() << std::endl;
818
for(i = 0; i < cFacets(); i++)
820
if( NULL == pFacet(i)->pFaceVertex())
822
pFacet(i)->Qfv(aQfv);
825
for( j = 0; j < aQfv.size(); j++ )
826
file << aQfv[j]->VertexIndex()+1 << " ";
833
file << "g CurrentFace" << std::endl;
834
for(i = 0; i < static_cast<TqInt>( paFaces->size() ); i++)
836
(*paFaces)[i]->Qfv(aQfv);
839
for( j = 0; j < aQfv.size(); j++ )
840
file << aQfv[j]->VertexIndex()+1 << " ";
849
void CqSubdivision2::OutputInfo(const char* fname, std::vector<CqLath*>* paFaces)
851
std::ofstream file(fname);
852
std::vector<CqLath*> aQfv;
854
std::vector<CqLath*>* paLaths = paFaces;
856
if( NULL == paLaths )
857
paLaths = &m_apFacets;
859
for(TqUint i = 0; i < paLaths->size(); i++)
861
CqLath* pL = (*paLaths)[i];
862
file << i << " - 0x" << pL << " - " <<
863
pL->VertexIndex() << " - " <<
864
pL->FaceVertexIndex() << " - (cf) ";
866
file << "0x" << pL->cf();
872
file << "0x" << pL->cv();
883
CqBound CqSurfaceSubdivisionPatch::Bound() const
885
assert( pTopology() );
886
assert( pTopology()->pPoints() );
889
// First make sure that the appropriate neighbour facets have been subdivided if this is >0 level face.
890
if( pFace()->pParentFacet() )
892
std::vector<CqLath*> aQff;
893
std::vector<CqLath*> apSubFaces2;
894
pFace()->pParentFacet()->Qff( aQff );
895
std::vector<CqLath*>::iterator iF;
896
for( iF = aQff.begin(); iF != aQff.end(); iF++ )
897
pTopology()->SubdivideFace(*iF, apSubFaces2);
902
// Get the laths of the surrounding faces.
903
std::vector<CqLath*> aQff;
905
std::vector<CqLath*>::iterator iFF;
906
for( iFF = aQff.begin(); iFF != aQff.end(); iFF++ )
908
// Get the laths that reference the vertices of this face
909
std::vector<CqLath*> aQfv;
912
// Now get the vertices, and form the bound.
913
std::vector<CqLath*>::iterator iQfv;
914
for( iQfv = aQfv.begin(); iQfv != aQfv.end(); iQfv++ )
917
for( iTime = 0; iTime < pTopology()->cTimes(); iTime++ )
918
B.Encapsulate((CqVector3D)pTopology()->pPoints( iTime )->P()->pValue((*iQfv)->VertexIndex())[0]);
922
return( AdjustBoundForTransformationMotion( B ) );
926
CqMicroPolyGridBase* CqSurfaceSubdivisionPatch::Dice()
928
boost::shared_ptr<CqSubdivision2> pSurface;
929
std::vector<CqMicroPolyGridBase*> apGrids;
932
for( iTime = 0; iTime < pTopology()->cTimes(); iTime++ )
934
pSurface = Extract(iTime);
935
boost::shared_ptr<CqSurfaceSubdivisionPatch> pPatch( new CqSurfaceSubdivisionPatch(pSurface, pSurface->pFacet(0)) );
936
pPatch->m_uDiceSize = m_uDiceSize;
937
pPatch->m_vDiceSize = m_vDiceSize;
938
CqMicroPolyGridBase* pGrid = pPatch->DiceExtract();
939
apGrids.push_back( pGrid );
942
if( apGrids.size() == 1 )
943
return( apGrids[ 0 ] );
946
CqMotionMicroPolyGrid * pGrid = new CqMotionMicroPolyGrid;
948
for ( i = 0; i < pTopology()->cTimes(); i++ )
949
pGrid->AddTimeSlot( pTopology()->Time( i ), apGrids[ i ] );
955
/** Dice the patch this primitive represents.
956
* Subdivide recursively the appropriate number of times, then extract the information into
960
CqMicroPolyGridBase* CqSurfaceSubdivisionPatch::DiceExtract()
962
// Dice rate table 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
963
static TqInt aDiceSizes[] = { 0, 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
964
assert( pTopology() );
965
assert( pTopology()->pPoints() );
968
TqInt dicesize = MAX(m_uDiceSize, m_vDiceSize);
970
TqInt sdcount = aDiceSizes[ dicesize ];
971
dicesize = 1 << sdcount;
972
TqInt lUses = Uses();
974
std::vector<CqMicroPolyGrid*> apGrids;
977
for( iTime = 0; iTime < pTopology()->cTimes(); iTime++ )
979
CqMicroPolyGrid* pGrid = new CqMicroPolyGrid( dicesize, dicesize, pTopology()->pPoints() );
981
boost::shared_ptr<CqPolygonPoints> pMotionPoints = pTopology()->pPoints( iTime );
984
std::vector<CqLath*> apSubFace1, apSubFace2;
985
apSubFace1.push_back(pFace());
987
for( isd = 0; isd < sdcount; isd++ )
990
std::vector<CqLath*>::iterator iSF;
991
for( iSF = apSubFace1.begin(); iSF != apSubFace1.end(); iSF++ )
993
// Subdivide this face, storing the resulting new face indices.
994
std::vector<CqLath*> apSubFaceTemp;
995
pTopology()->SubdivideFace( (*iSF), apSubFaceTemp );
996
// Now combine these into the new face indices for this subdivision level.
997
apSubFace2.insert(apSubFace2.end(), apSubFaceTemp.begin(), apSubFaceTemp.end());
999
// Now swap the new level's indices for the old before repeating at the next level, if appropriate.
1000
apSubFace1.swap(apSubFace2);
1003
// Now we use the first face index to start our extraction
1008
CqLath* pLath, *pTemp;
1009
pLath = apSubFace1[0];
1012
// Get data from pLath
1013
TqInt ivA = pLath->VertexIndex();
1014
TqInt iFVA = pLath->FaceVertexIndex();
1016
StoreDice( pGrid, pMotionPoints, ivA, iFVA, indexA );
1019
pLath = pLath->ccf();
1023
TqInt ivA = pLath->VertexIndex();
1024
TqInt iFVA = pLath->FaceVertexIndex();
1025
StoreDice( pGrid, pMotionPoints, ivA, iFVA, indexA );
1027
if( c < ( nc - 1 ) )
1028
pLath = pLath->cv()->ccf();
1037
pLath = pTemp->cf();
1039
pTemp = pLath->ccv();
1041
// Get data from pLath
1042
TqInt ivA = pLath->VertexIndex();
1043
TqInt iFVA = pLath->FaceVertexIndex();
1044
TqInt indexA = ( r * ( nc + 1 ) );
1045
StoreDice( pGrid, pMotionPoints, ivA, iFVA, indexA );
1048
pLath = pLath->cf();
1052
TqInt ivA = pLath->VertexIndex();
1053
TqInt iFVA = pLath->FaceVertexIndex();
1054
StoreDice( pGrid, pMotionPoints, ivA, iFVA, indexA );
1056
if( c < ( nc - 1 ) )
1057
pLath = pLath->ccv()->cf();
1067
// If the color and opacity are not defined, use the system values.
1068
if ( USES( lUses, EnvVars_Cs ) && !pTopology()->pPoints()->bHasVar(EnvVars_Cs) )
1070
if ( pAttributes() ->GetColorAttribute( "System", "Color" ) )
1071
pGrid->pVar(EnvVars_Cs) ->SetColor( pAttributes() ->GetColorAttribute( "System", "Color" ) [ 0 ] );
1073
pGrid->pVar(EnvVars_Cs) ->SetColor( CqColor( 1, 1, 1 ) );
1076
if ( USES( lUses, EnvVars_Os ) && !pTopology()->pPoints()->bHasVar(EnvVars_Os) )
1078
if ( pAttributes() ->GetColorAttribute( "System", "Opacity" ) )
1079
pGrid->pVar(EnvVars_Os) ->SetColor( pAttributes() ->GetColorAttribute( "System", "Opacity" ) [ 0 ] );
1081
pGrid->pVar(EnvVars_Os) ->SetColor( CqColor( 1, 1, 1 ) );
1083
apGrids.push_back( pGrid );
1085
// Fill in u/v if required.
1086
if ( USES( lUses, EnvVars_u ) && !pTopology()->pPoints()->bHasVar(EnvVars_u) )
1089
for ( iv = 0; iv <= dicesize; iv++ )
1091
TqFloat v = ( 1.0f / ( dicesize + 1 ) ) * iv;
1092
for ( iu = 0; iu <= dicesize; iu++ )
1094
TqFloat u = ( 1.0f / ( dicesize + 1 ) ) * iu;
1095
TqInt igrid = ( iv * ( dicesize + 1 ) ) + iu;
1096
pGrid->pVar(EnvVars_u)->SetFloat( BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u, v ), igrid );
1101
if ( USES( lUses, EnvVars_v ) && !pTopology()->pPoints()->bHasVar(EnvVars_v) )
1104
for ( iv = 0; iv <= dicesize; iv++ )
1106
TqFloat v = ( 1.0f / ( dicesize + 1 ) ) * iv;
1107
for ( iu = 0; iu <= dicesize; iu++ )
1109
TqFloat u = ( 1.0f / ( dicesize + 1 ) ) * iu;
1110
TqInt igrid = ( iv * ( dicesize + 1 ) ) + iu;
1111
pGrid->pVar(EnvVars_v)->SetFloat( BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u, v ), igrid );
1116
// Fill in s/t if required.
1117
if ( USES( lUses, EnvVars_s ) && !pTopology()->pPoints()->bHasVar(EnvVars_s) )
1119
pGrid->pVar(EnvVars_s)->SetValueFromVariable( pGrid->pVar(EnvVars_u) );
1122
if ( USES( lUses, EnvVars_t ) && !pTopology()->pPoints()->bHasVar(EnvVars_t) )
1124
pGrid->pVar(EnvVars_t)->SetValueFromVariable( pGrid->pVar(EnvVars_v) );
1128
if( apGrids.size() == 1 )
1129
return( apGrids[ 0 ] );
1132
CqMotionMicroPolyGrid * pGrid = new CqMotionMicroPolyGrid;
1134
for ( i = 0; i < pTopology()->cTimes(); i++ )
1135
pGrid->AddTimeSlot( pTopology()->Time( i ), apGrids[ i ] );
1142
static void StoreDiceAPVar( IqShader* pShader, CqParameter* pParam, TqUint ivA, TqUint indexA )
1144
// Find the argument
1145
IqShaderData * pArg = pShader->FindArgument( pParam->strName() );
1148
switch ( pParam->Type() )
1152
CqParameterTyped<TqFloat, TqFloat>* pNParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam );
1153
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1159
CqParameterTyped<TqInt, TqFloat>* pNParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam );
1160
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1168
CqParameterTyped<CqVector3D, CqVector3D>* pNParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam );
1169
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1175
CqParameterTyped<CqVector4D, CqVector3D>* pNParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam );
1176
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1182
CqParameterTyped<CqString, CqString>* pNParam = static_cast<CqParameterTyped<CqString, CqString>*>( pParam );
1183
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1189
CqParameterTyped<CqColor, CqColor>* pNParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam );
1190
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1196
CqParameterTyped<CqMatrix, CqMatrix>* pNParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam );
1197
pArg->SetValue( *pNParam->pValue( ivA ), indexA );
1203
// left blank to avoid compiler warnings about unhandled types
1211
void CqSurfaceSubdivisionPatch::StoreDice( CqMicroPolyGrid* pGrid, const boost::shared_ptr<CqPolygonPoints>& pPoints, TqInt iParam, TqInt iFVParam, TqInt iData)
1213
TqInt lUses = Uses();
1216
if ( USES( lUses, EnvVars_P ) )
1217
pGrid->pVar(EnvVars_P) ->SetPoint( pPoints->P()->pValue( iParam )[0], iData );
1219
// Special cases for s and t if "st" exists, it should override s and t.
1220
CqParameter* pParam;
1221
if( ( pParam = pPoints->FindUserParam("st") ) != NULL )
1223
TqInt index = iParam;
1224
if( pParam->Class() == class_facevarying )
1226
CqParameterTyped<TqFloat, TqFloat>* pSTParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>(pParam);
1227
if ( USES( lUses, EnvVars_s ) && ( NULL != pGrid->pVar(EnvVars_s) ) )
1228
pGrid->pVar( EnvVars_s )->SetFloat( pSTParam->pValue( index )[0], iData);
1229
if ( USES( lUses, EnvVars_t ) && ( NULL != pGrid->pVar(EnvVars_t) ) )
1230
pGrid->pVar( EnvVars_t )->SetFloat( pSTParam->pValue( index )[1], iData);
1231
DONE( lDone, EnvVars_s);
1232
DONE( lDone, EnvVars_t);
1235
if ( USES( lUses, EnvVars_s ) && ( NULL != pGrid->pVar(EnvVars_s) ) && ( pPoints->bHasVar(EnvVars_s) ) && !isDONE(lDone, EnvVars_s ) )
1237
if( pPoints->s()->Class() == class_varying || pPoints->s()->Class() == class_vertex )
1238
pGrid->pVar(EnvVars_s) ->SetFloat( pPoints->s()->pValue( iParam )[0], iData );
1239
else if( pPoints->s()->Class() == class_facevarying )
1240
pGrid->pVar(EnvVars_s) ->SetFloat( pPoints->s()->pValue( iFVParam )[0], iData );
1243
if ( USES( lUses, EnvVars_t ) && ( NULL != pGrid->pVar(EnvVars_t) ) && ( pPoints->bHasVar(EnvVars_t) ) && !isDONE(lDone, EnvVars_t ) )
1245
if( pPoints->t()->Class() == class_varying || pPoints->t()->Class() == class_vertex )
1246
pGrid->pVar(EnvVars_t) ->SetFloat( pPoints->t()->pValue( iParam )[0], iData );
1247
else if( pPoints->t()->Class() == class_facevarying )
1248
pGrid->pVar(EnvVars_t) ->SetFloat( pPoints->t()->pValue( iFVParam )[0], iData );
1251
if ( USES( lUses, EnvVars_Cs ) && ( pGrid->pVar(EnvVars_Cs) ) && ( pPoints->bHasVar(EnvVars_Cs) ) )
1253
if( pPoints->Cs()->Class() == class_varying || pPoints->Cs()->Class() == class_vertex )
1254
pGrid->pVar(EnvVars_Cs) ->SetColor( pPoints->Cs()->pValue(iParam)[0], iData );
1255
else if( pPoints->Cs()->Class() == class_facevarying )
1256
pGrid->pVar(EnvVars_Cs) ->SetColor( pPoints->Cs()->pValue(iFVParam)[0], iData );
1259
if ( USES( lUses, EnvVars_Os ) && ( pGrid->pVar(EnvVars_Os) ) && ( pPoints->bHasVar(EnvVars_Os) ) )
1260
pGrid->pVar(EnvVars_Os) ->SetColor( pPoints->Os()->pValue(iParam)[0], iData );
1262
// Now lets store the diced user specified primitive variables.
1263
std::vector<CqParameter*>::iterator iUP;
1264
for ( iUP = pPoints->aUserParams().begin(); iUP != pPoints->aUserParams().end(); iUP++ )
1266
/// \todo: Must transform point/vector/normal/matrix parameter variables from 'object' space to current before setting.
1268
if ( (pShader=pGrid->pAttributes() ->pshadSurface(QGetRenderContextI()->Time())) != NULL )
1269
StoreDiceAPVar( pShader, ( *iUP ), iParam, iData );
1271
if ( (pShader=pGrid->pAttributes() ->pshadDisplacement(QGetRenderContextI()->Time())) != NULL )
1272
StoreDiceAPVar( pShader, ( *iUP ), iParam, iData );
1274
if ( (pShader=pGrid->pAttributes() ->pshadAtmosphere(QGetRenderContextI()->Time())) != NULL )
1275
StoreDiceAPVar( pShader, ( *iUP ), iParam, iData );
1279
TqInt CqSurfaceSubdivisionPatch::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
1281
assert( pTopology() );
1282
assert( pTopology()->pPoints() );
1285
if( pTopology()->CanUsePatch( pFace() ) )
1287
// Find the point indices for the 16 patch vertices.
1288
CqLath* pPoint = pFace()->cv()->cv()->cf()->cf();
1289
CqLath* pRow = pPoint;
1291
std::vector<TqInt> aiVertices;
1292
std::vector<TqInt> aiFVertices;
1295
aiVertices.push_back( pPoint->VertexIndex() );
1296
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1298
pPoint = pPoint->ccf();
1299
aiVertices.push_back( pPoint->VertexIndex() );
1300
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1302
pPoint = pPoint->cv()->ccf();
1303
aiVertices.push_back( pPoint->VertexIndex() );
1304
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1306
pPoint = pPoint->cv()->ccf();
1307
aiVertices.push_back( pPoint->VertexIndex() );
1308
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1310
pRow = pPoint = pRow->cf();
1311
aiVertices.push_back( pPoint->VertexIndex() );
1312
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1314
pPoint = pPoint->cf();
1315
aiVertices.push_back( pPoint->VertexIndex() );
1316
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1318
pPoint = pPoint->ccv()->cf();
1319
aiVertices.push_back( pPoint->VertexIndex() );
1320
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1322
pPoint = pPoint->ccv()->cf();
1323
aiVertices.push_back( pPoint->VertexIndex() );
1324
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1326
pRow = pPoint = pRow->ccv()->cf();
1327
aiVertices.push_back( pPoint->VertexIndex() );
1328
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1330
pPoint = pPoint->cf();
1331
aiVertices.push_back( pPoint->VertexIndex() );
1332
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1334
pPoint = pPoint->ccv()->cf();
1335
aiVertices.push_back( pPoint->VertexIndex() );
1336
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1338
pPoint = pPoint->ccv()->cf();
1339
aiVertices.push_back( pPoint->VertexIndex() );
1340
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1342
pPoint = pRow->ccv()->cf();
1343
aiVertices.push_back( pPoint->VertexIndex() );
1344
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1346
pPoint = pPoint->cf();
1347
aiVertices.push_back( pPoint->VertexIndex() );
1348
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1350
pPoint = pPoint->ccv()->cf();
1351
aiVertices.push_back( pPoint->VertexIndex() );
1352
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1354
pPoint = pPoint->ccv()->cf();
1355
aiVertices.push_back( pPoint->VertexIndex() );
1356
aiFVertices.push_back( pPoint->FaceVertexIndex() );
1358
std::vector< boost::shared_ptr<CqSurfacePatchBicubic> > apSurfaces;
1362
for( iTime = 0; iTime < pTopology()->cTimes(); iTime++ )
1364
// Create a surface patch
1365
boost::shared_ptr<CqSurfacePatchBicubic> pSurface( new CqSurfacePatchBicubic() );
1366
// Fill in default values for all primitive variables not explicitly specified.
1367
pSurface->SetSurfaceParameters( *pTopology()->pPoints( iTime ) );
1369
std::vector<CqParameter*>::iterator iUP;
1370
std::vector<CqParameter*>::iterator end = pTopology()->pPoints( iTime)->aUserParams().end();
1371
for ( iUP = pTopology()->pPoints( iTime )->aUserParams().begin(); iUP != end; iUP++ )
1373
if ( ( *iUP ) ->Class() == class_varying )
1375
// Copy any 'varying' class primitive variables.
1376
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1377
pNewUP->SetSize( pSurface->cVarying() );
1378
pNewUP->SetValue( ( *iUP ), 0, aiVertices[5] );
1379
pNewUP->SetValue( ( *iUP ), 1, aiVertices[6] );
1380
pNewUP->SetValue( ( *iUP ), 2, aiVertices[9] );
1381
pNewUP->SetValue( ( *iUP ), 3, aiVertices[10] );
1382
pSurface->AddPrimitiveVariable( pNewUP );
1384
else if ( ( *iUP ) ->Class() == class_vertex )
1386
// Copy any 'vertex' class primitive variables.
1387
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1388
pNewUP->SetSize( pSurface->cVertex() );
1390
for( i = 0; i < pSurface->cVertex(); i++ )
1391
pNewUP->SetValue( ( *iUP ), i, aiVertices[i] );
1392
pSurface->AddPrimitiveVariable( pNewUP );
1394
else if ( ( *iUP ) ->Class() == class_facevarying )
1396
// Copy any 'facevarying' class primitive variables.
1397
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1398
pNewUP->SetSize( pSurface->cVertex() );
1400
for( i = 0; i < pSurface->cVertex(); i++ )
1401
pNewUP->SetValue( ( *iUP ), i, aiFVertices[i] );
1402
pSurface->AddPrimitiveVariable( pNewUP );
1404
else if ( ( *iUP ) ->Class() == class_uniform )
1406
// Copy any 'uniform' class primitive variables.
1407
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1408
pNewUP->SetSize( pSurface->cUniform() );
1409
pNewUP->SetValue( ( *iUP ), 0, 0 );
1410
pSurface->AddPrimitiveVariable( pNewUP );
1412
else if ( ( *iUP ) ->Class() == class_constant )
1414
// Copy any 'constant' class primitive variables.
1415
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1416
pNewUP->SetSize( 1 );
1417
pNewUP->SetValue( ( *iUP ), 0, 0 );
1418
pSurface->AddPrimitiveVariable( pNewUP );
1422
// Need to get rid of any 'h' values added to the "P" variables during multiplication.
1424
for( i = 0; i < pSurface->cVertex(); i++ )
1425
pSurface->P()->pValue(i)[0] = static_cast<CqVector3D>( pSurface->P()->pValue(i)[0] );
1427
CqMatrix matuBasis( RiBSplineBasis );
1428
CqMatrix matvBasis( RiBSplineBasis );
1429
pSurface->ConvertToBezierBasis( matuBasis, matvBasis );
1431
TqInt iUses = Uses();
1433
// If the shader needs s/t or u/v, and s/t is not specified, then at this point store the object space x,y coordinates.
1434
if ( USES( iUses, EnvVars_s ) || USES( iUses, EnvVars_t ) || USES( iUses, EnvVars_u ) || USES( iUses, EnvVars_v ) )
1436
if ( USES( iUses, EnvVars_s ) && !pTopology()->pPoints()->bHasVar(EnvVars_s) )
1438
CqParameterTypedVarying<TqFloat, type_float, TqFloat>* pNewUP = new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "s" );
1439
pNewUP->SetSize( pSurface->cVarying() );
1441
pNewUP->pValue() [ 0 ] = 0.0f;
1442
pNewUP->pValue() [ 1 ] = 1.0f;
1443
pNewUP->pValue() [ 2 ] = 0.0f;
1444
pNewUP->pValue() [ 3 ] = 1.0f;
1446
pSurface->AddPrimitiveVariable( pNewUP );
1449
if ( USES( iUses, EnvVars_t ) && !pTopology()->pPoints()->bHasVar(EnvVars_t) )
1451
CqParameterTypedVarying<TqFloat, type_float, TqFloat>* pNewUP = new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "t" );
1452
pNewUP->SetSize( pSurface->cVarying() );
1454
pNewUP->pValue() [ 0 ] = 0.0f;
1455
pNewUP->pValue() [ 1 ] = 0.0f;
1456
pNewUP->pValue() [ 2 ] = 1.0f;
1457
pNewUP->pValue() [ 3 ] = 1.0f;
1459
pSurface->AddPrimitiveVariable( pNewUP );
1462
if ( USES( iUses, EnvVars_u ) && !pTopology()->pPoints()->bHasVar(EnvVars_u) )
1464
CqParameterTypedVarying<TqFloat, type_float, TqFloat>* pNewUP = new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "u" );
1465
pNewUP->SetSize( pSurface->cVarying() );
1467
pNewUP->pValue() [ 0 ] = 0.0f;
1468
pNewUP->pValue() [ 1 ] = 1.0f;
1469
pNewUP->pValue() [ 2 ] = 0.0f;
1470
pNewUP->pValue() [ 3 ] = 1.0f;
1472
pSurface->AddPrimitiveVariable( pNewUP );
1475
if ( USES( iUses, EnvVars_v ) && !pTopology()->pPoints()->bHasVar(EnvVars_v) )
1477
CqParameterTypedVarying<TqFloat, type_float, TqFloat>* pNewUP = new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "v" );
1478
pNewUP->SetSize( pSurface->cVarying() );
1480
pNewUP->pValue() [ 0 ] = 0.0f;
1481
pNewUP->pValue() [ 1 ] = 0.0f;
1482
pNewUP->pValue() [ 2 ] = 1.0f;
1483
pNewUP->pValue() [ 3 ] = 1.0f;
1485
pSurface->AddPrimitiveVariable( pNewUP );
1488
apSurfaces.push_back( pSurface );
1491
if( apSurfaces.size() == 1 )
1492
aSplits.push_back(apSurfaces[ 0 ]);
1493
else if( apSurfaces.size() > 1 )
1495
boost::shared_ptr<CqDeformingSurface> pMotionSurface( new CqDeformingSurface( boost::shared_ptr<CqBasicSurface>() ) );
1496
for( iTime = 0; iTime < pTopology()->cTimes(); iTime++ )
1498
RtFloat time = pTopology()->Time( iTime );
1499
pMotionSurface->AddTimeSlot( time, apSurfaces[ iTime ] );
1501
aSplits.push_back(pMotionSurface);
1506
// Subdivide the face, and create new patches for the subfaces.
1507
std::vector<CqLath*> apSubFaces;
1508
pTopology()->SubdivideFace( pFace(), apSubFaces );
1510
// Now create new patch objects for each subface.
1511
std::vector<CqLath*>::iterator iSF;
1512
for( iSF = apSubFaces.begin(); iSF != apSubFaces.end(); iSF++ )
1514
boost::shared_ptr<CqSurfaceSubdivisionPatch> pNew( new CqSurfaceSubdivisionPatch( pTopology(), (*iSF) ) );
1515
aSplits.push_back(pNew);
1519
return(aSplits.size());
1522
TqBool CqSurfaceSubdivisionPatch::Diceable()
1524
assert( pTopology() );
1525
assert( pTopology()->pPoints() );
1528
// If the cull check showed that the primitive cannot be diced due to crossing the e and hither planes,
1529
// then we can return immediately.
1533
// If we can use a patch, don't dice, as dicing a patch is much quicker.
1534
if( pTopology()->CanUsePatch( pFace() ) )
1537
// Get the laths that reference the vertices of this face
1538
std::vector<CqLath*> aQfv;
1541
// Cannot dice if not 4 points
1542
if ( aQfv.size() != 4 )
1545
// Otherwise we should continue to try to find the most advantageous split direction, OR the dice size.
1546
const CqMatrix & matCtoR = QGetRenderContext() ->matSpaceToSpace( "camera", "raster", CqMatrix(), CqMatrix(), QGetRenderContext()->Time() );
1548
// Convert the control hull to raster space.
1549
CqVector2D avecHull[ 4 ];
1552
TqFloat ShadingRate = pAttributes() ->GetFloatAttribute( "System", "ShadingRate" ) [ 0 ];
1554
for ( i = 0; i < 4; i++ )
1555
avecHull[ i ] = matCtoR * pTopology()->pPoints()->P()->pValue() [ aQfv[ i ]->VertexIndex() ];
1560
CqVector2D Vec1 = avecHull[ 1 ] - avecHull[ 0 ];
1561
CqVector2D Vec2 = avecHull[ 2 ] - avecHull[ 3 ];
1562
uLen = ( Vec1.Magnitude2() > Vec2.Magnitude2() ) ? Vec1.Magnitude2() : Vec2.Magnitude2();
1564
Vec1 = avecHull[ 3 ] - avecHull[ 0 ];
1565
Vec2 = avecHull[ 2 ] - avecHull[ 1 ];
1566
vLen = ( Vec1.Magnitude2() > Vec2.Magnitude2() ) ? Vec1.Magnitude2() : Vec2.Magnitude2();
1568
uLen = sqrt( uLen / ShadingRate);
1569
vLen = sqrt( vLen / ShadingRate);
1571
m_SplitDir = ( uLen > vLen ) ? SplitDir_U : SplitDir_V;
1573
// TODO: Should ensure powers of half to prevent cracking.
1574
uLen = MAX( ROUND( uLen ), 1 );
1575
vLen = MAX( ROUND( vLen ), 1 );
1577
m_uDiceSize = static_cast<TqInt>( uLen );
1578
m_vDiceSize = static_cast<TqInt>( vLen );
1580
// Ensure power of 2 to avoid cracking
1581
m_uDiceSize = CEIL_POW2( m_uDiceSize );
1582
m_vDiceSize = CEIL_POW2( m_vDiceSize );
1584
if ( uLen < FLT_EPSILON || vLen < FLT_EPSILON )
1586
m_fDiscard = TqTrue;
1591
const TqFloat* poptGridSize = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "SqrtGridSize" );
1593
gs = poptGridSize[0];
1595
if ( m_uDiceSize > gs) return TqFalse;
1596
if ( m_vDiceSize > gs) return TqFalse;
1602
* Determine if the topology surrounding the specified face is suitable for
1603
* conversion to a bicubic patch.
1606
TqBool CqSubdivision2::CanUsePatch( CqLath* pFace )
1608
// If the patch is a quad with each corner having valence 4, and no special features,
1609
// we can just create a B-Spline patch.
1610
if( pFace->cQfv() != 4 )
1613
std::vector<CqLath*> aQff, aQfv;
1615
std::vector<CqLath*>::iterator iFV;
1616
for( iFV = aQfv.begin(); iFV!=aQfv.end(); iFV++ )
1618
// Check if all vertices are valence 4.
1619
if( (*iFV)->cQvv() != 4 )
1622
// Check if all vertices smooth.
1623
if( EdgeSharpness((*iFV)) != 0.0f ||
1624
CornerSharpness((*iFV)) != 0.0f )
1627
// Check if no internal boundaries.
1628
CqLath* pEnd = (*iFV)->cv();
1629
while( (*iFV) != pEnd )
1637
// Check local neighbourhood of patch is 9 quads.
1639
if( aQff.size() != 9 )
1642
std::vector<CqLath*>::iterator iFF;
1643
for( iFF = aQff.begin(); iFF!=aQff.end(); iFF++ )
1645
if( (*iFF)->cQfv() != 4 )
1648
std::vector<CqLath*> aQfv;
1650
std::vector<CqLath*>::iterator iFV;
1651
for( iFV = aQfv.begin(); iFV!=aQfv.end(); iFV++ )
1653
// Check if all vertices smooth.
1654
if( EdgeSharpness((*iFV)) != 0.0f ||
1655
CornerSharpness((*iFV)) != 0.0f )
1660
// Finally check if the "facevarying" indexes match, as patches can't have
1661
// different facevarying indexes across the parameter lines.
1662
for( iFV = aQfv.begin(); iFV != aQfv.end(); iFV++ )
1664
std::vector<CqLath*> aQvv;
1666
// We already know this must have 4 entries to have passed the previous tests.
1667
if( !( aQvv[0]->FaceVertexIndex() == aQvv[1]->FaceVertexIndex() == aQvv[2]->FaceVertexIndex() == aQvv[3]->FaceVertexIndex() ) )
1670
// Check the edge parameter lines from this face vertex.
1671
if( (*iFV)->ccv()->ccf()->FaceVertexIndex() != (*iFV)->ccv()->ccf()->ccv()->FaceVertexIndex() )
1673
if( (*iFV)->ccv()->ccv()->ccf()->FaceVertexIndex() != (*iFV)->ccv()->ccv()->ccf()->ccv()->FaceVertexIndex() )
1681
CqBound CqSurfaceSubdivisionMesh::Bound() const
1684
if( m_pTopology && m_pTopology->pPoints() && m_pTopology->pPoints()->P() )
1687
for( PointIndex = m_pTopology->pPoints()->P()->Size()-1; PointIndex >= 0; PointIndex-- )
1688
B.Encapsulate( (CqVector3D)m_pTopology->pPoints()->P()->pValue()[PointIndex] );
1690
return( AdjustBoundForTransformationMotion( B ) );
1693
TqInt CqSurfaceSubdivisionMesh::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
1695
TqInt CreatedPolys = 0;
1698
for ( face = 0; face < m_NumFaces; face++ )
1700
// Don't add faces which are on the boundary, unless "interpolateboundary" is specified.
1701
if( ( !m_pTopology->pFacet( face )->isBoundaryFacet() ) || ( m_pTopology->isInterpolateBoundary() ) )
1703
// Don't add "hole" faces
1704
if( !m_pTopology->isHoleFace( face ) )
1706
// Add a patch surface to the bucket queue
1707
boost::shared_ptr<CqSurfaceSubdivisionPatch> pNew( new CqSurfaceSubdivisionPatch( m_pTopology, m_pTopology->pFacet( face ) ) );
1708
aSplits.push_back( pNew );
1713
return( CreatedPolys );
1717
boost::shared_ptr<CqSubdivision2> CqSurfaceSubdivisionPatch::Extract( TqInt iTime )
1719
assert( pTopology() );
1720
assert( pTopology()->pPoints() );
1723
// Find the point indices for the polygons surrounding this one.
1724
// Use a map to ensure that shared vertices are only counted once.
1725
std::map<TqInt, TqInt> Vertices;
1727
std::vector<TqInt> FVertices;
1729
std::vector<CqLath*> aQff;
1730
std::vector<CqLath*> apSubFaces2;
1731
pFace()->Qff( aQff );
1732
std::vector<CqLath*>::iterator iF;
1733
for( iF = aQff.begin(); iF != aQff.end(); iF++ )
1735
std::vector<CqLath*> aQfv;
1737
std::vector<CqLath*>::reverse_iterator iV;
1738
for( iV = aQfv.rbegin(); iV != aQfv.rend(); iV++ )
1740
if( Vertices.find((*iV)->VertexIndex()) == Vertices.end() )
1742
Vertices[(*iV)->VertexIndex()] = cVerts;
1745
FVertices.push_back( (*iV)->FaceVertexIndex() );
1748
TqInt cFaceVerts = FVertices.size();
1749
TqInt cFaces = aQff.size();
1751
// Create a storage class for all the points.
1752
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, aQff.size(), FVertices.size() ) );
1753
// Fill in default values for all primitive variables not explicitly specified.
1754
pPointsClass->SetSurfaceParameters( *pTopology()->pPoints( iTime ) );
1756
boost::shared_ptr<CqSubdivision2> pSurface( new CqSubdivision2( pPointsClass ) );
1757
pSurface->Prepare( cVerts );
1759
std::vector<CqParameter*>::iterator iUP;
1760
std::vector<CqParameter*>::iterator end = pTopology()->pPoints( iTime)->aUserParams().end();
1761
for ( iUP = pTopology()->pPoints( iTime )->aUserParams().begin(); iUP != end; iUP++ )
1763
if ( ( *iUP ) ->Class() == class_vertex || ( *iUP ) ->Class() == class_varying )
1765
// Copy any 'vertex' or 'varying' class primitive variables.
1766
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1767
pNewUP->SetSize( cVerts );
1768
std::map<TqInt, TqInt>::iterator i;
1769
for( i = Vertices.begin(); i != Vertices.end(); i++ )
1770
pNewUP->SetValue( ( *iUP ), (*i).second, (*i).first );
1771
pSurface->pPoints()->AddPrimitiveVariable( pNewUP );
1773
else if ( ( *iUP ) ->Class() == class_facevarying )
1775
// Copy any 'facevarying' class primitive variables.
1776
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1777
pNewUP->SetSize( FVertices.size() );
1778
std::vector<TqInt>::iterator i;
1780
for( i = FVertices.begin(); i != FVertices.end(); i++, iv++ )
1781
pNewUP->SetValue( ( *iUP ), iv, (*i) );
1782
pSurface->pPoints()->AddPrimitiveVariable( pNewUP );
1784
else if ( ( *iUP ) ->Class() == class_uniform )
1786
// Copy any 'uniform' class primitive variables.
1787
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1788
pNewUP->SetSize( pSurface->pPoints()->cUniform() );
1789
pNewUP->SetValue( ( *iUP ), 0, 0 );
1790
pSurface->pPoints()->AddPrimitiveVariable( pNewUP );
1792
else if ( ( *iUP ) ->Class() == class_constant )
1794
// Copy any 'constant' class primitive variables.
1795
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1796
pNewUP->SetSize( 1 );
1797
pNewUP->SetValue( ( *iUP ), 0, 0 );
1798
pSurface->pPoints()->AddPrimitiveVariable( pNewUP );
1802
// Need to get rid of any 'h' values added to the "P" variables during multiplication.
1804
for( i = 0; i < cVerts; i++ )
1805
pSurface->pPoints()->P()->pValue(i)[0] = static_cast<CqVector3D>( pSurface->pPoints()->P()->pValue(i)[0] );
1807
TqInt iUses = Uses();
1810
for( iF = aQff.begin(); iF != aQff.end(); iF++ )
1812
std::vector<TqInt> vertices;
1813
std::vector<CqLath*> aQfv;
1815
std::vector<CqLath*>::reverse_iterator iV;
1816
for( iV = aQfv.rbegin(); iV != aQfv.rend(); ++iV )
1817
vertices.push_back( Vertices[(*iV)->VertexIndex()] );
1818
pSurface->AddFacet( vertices.size(), &vertices[ 0 ], iP );
1819
iP += vertices.size();
1821
pSurface->Finalise();
1826
END_NAMESPACE( Aqsis )