~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to render/subdivision2.h

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Aqsis
 
2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
 
3
//
 
4
// Contact: pgregory@aqsis.com
 
5
//
 
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.
 
10
//
 
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.
 
15
//
 
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
 
19
 
 
20
 
 
21
/** \file
 
22
                \brief Declares the classes for subdivision surfaces.
 
23
                \author Paul C. Gregory (pgregory@aqsis.com)
 
24
*/
 
25
 
 
26
 
 
27
#ifndef SUBDIVISION2_H_LOADED
 
28
#define SUBDIVISION2_H_LOADED
 
29
 
 
30
#include "aqsis.h"
 
31
#include "lath.h"
 
32
#include "vector3d.h"
 
33
#include "refcount.h"
 
34
#include "surface.h"
 
35
#include "polygon.h"
 
36
 
 
37
START_NAMESPACE( Aqsis )
 
38
 
 
39
//------------------------------------------------------------------------------
 
40
/**
 
41
 *      Container for the topology description of a mesh.
 
42
 *      Holds information about which Laths represent which facets and vertices, and 
 
43
 *  provides functions to build topology data structures from unstructured meshes.
 
44
 */
 
45
 
 
46
class CqSubdivision2 : public CqMotionSpec<boost::shared_ptr<CqPolygonPoints> >
 
47
{
 
48
public:
 
49
    /// Constructor.
 
50
    CqSubdivision2( );
 
51
 
 
52
    /// Constructor.
 
53
    CqSubdivision2( const boost::shared_ptr<CqPolygonPoints>& pPoints );
 
54
 
 
55
    /// Destructor.
 
56
    virtual ~CqSubdivision2();
 
57
 
 
58
#ifdef _DEBUG
 
59
    CqString className() const { return CqString("CqSubdivision2"); }
 
60
#endif
 
61
 
 
62
    CqLath* pFacet(TqInt iIndex);
 
63
    CqLath* pVertex(TqInt iIndex);
 
64
 
 
65
    /// Get the number of faces representing this topology.
 
66
    TqInt       cFacets() const         {return(m_apFacets.size());}
 
67
    /// Get the number of laths representing this topology.
 
68
    TqInt       cLaths() const          {return(m_apLaths.size());}
 
69
    /// Get the number of faces representing this topology.
 
70
    TqInt       cVertices() const       {return(m_aapVertices.size());}
 
71
 
 
72
    /// Get a refrence to the array of autoatically generated laths.
 
73
    const std::vector<CqLath*>& apLaths() const
 
74
        {return(m_apLaths);}
 
75
 
 
76
    /// Get pointer to the vertex storage class
 
77
    boost::shared_ptr<CqPolygonPoints> pPoints( TqInt TimeIndex = 0 ) const
 
78
    {
 
79
        return ( GetMotionObject( Time( TimeIndex ) ) );
 
80
    }
 
81
 
 
82
    void                Prepare(TqInt cVerts);
 
83
    CqLath*             AddFacet(TqInt cVerts, TqInt* pIndices, TqInt iFVIndex);
 
84
    TqBool              Finalise();
 
85
    void                SubdivideFace(CqLath* pFace, std::vector<CqLath*>& apSubFaces);
 
86
    TqBool              CanUsePatch( CqLath* pFace );
 
87
    void                SetInterpolateBoundary( TqBool state = TqTrue )
 
88
    {
 
89
        m_bInterpolateBoundary = state;
 
90
    }
 
91
    TqBool              isInterpolateBoundary( ) const
 
92
    {
 
93
        return( m_bInterpolateBoundary );
 
94
    }
 
95
    void                SetHoleFace( TqInt iFaceIndex )
 
96
    {
 
97
        m_mapHoles[ iFaceIndex ] = TqTrue;
 
98
    }
 
99
    TqBool              isHoleFace( TqInt iFaceIndex ) const
 
100
    {
 
101
        return( m_mapHoles.find( iFaceIndex ) != m_mapHoles.end() );
 
102
    }
 
103
    void                AddSharpEdge( CqLath* pLath, TqFloat Sharpness )
 
104
    {
 
105
        m_mapSharpEdges[pLath] = Sharpness;
 
106
    }
 
107
    TqFloat             EdgeSharpness( CqLath* pLath )
 
108
    {
 
109
        if( m_mapSharpEdges.find( pLath ) != m_mapSharpEdges.end() )
 
110
            return( m_mapSharpEdges[ pLath ] );
 
111
        return( 0.0f );
 
112
    }
 
113
    void                AddSharpCorner( CqLath* pLath, TqFloat Sharpness )
 
114
    {
 
115
        std::vector<CqLath*> aQve;
 
116
        pLath->Qve( aQve );
 
117
        std::vector<CqLath*>::iterator iVE;
 
118
        for( iVE = aQve.begin(); iVE != aQve.end(); iVE++ )
 
119
            m_mapSharpCorners[(*iVE)] = Sharpness;
 
120
    }
 
121
    TqFloat             CornerSharpness( CqLath* pLath )
 
122
    {
 
123
        if( m_mapSharpCorners.find( pLath ) != m_mapSharpCorners.end() )
 
124
            return( m_mapSharpCorners[ pLath ] );
 
125
        return( 0.0f );
 
126
    }
 
127
 
 
128
    void                AddVertex(CqLath* pVertex, TqInt& iVIndex, TqInt& iFVIndex);
 
129
    template<class TypeA, class TypeB>
 
130
    void                CreateVertex(CqParameterTyped<TypeA, TypeB>* pParam, CqLath* pVertex, TqInt iIndex)
 
131
    {
 
132
                TqInt arraysize = 0, arrayindex;
 
133
                arraysize = pParam->Count();
 
134
                for( arrayindex = 0; arrayindex < arraysize; arrayindex++ )
 
135
                {
 
136
                        TypeA S = TypeA(0.0f);
 
137
                        TypeA Q = TypeA(0.0f);
 
138
                        TypeA R = TypeA(0.0f);
 
139
                        TqInt n;
 
140
 
 
141
                        if(pParam->Class() == class_vertex /*|| pParam->Class() == class_facevarying*/)
 
142
                        {
 
143
                                // Get a pointer to the appropriate index accessor function on CqLath based on class.
 
144
                                TqInt (CqLath::*IndexFunction)() const;
 
145
                                if( pParam->Class() == class_vertex )
 
146
                                        IndexFunction = &CqLath::VertexIndex;
 
147
                                else
 
148
                                        IndexFunction = &CqLath::FaceVertexIndex;
 
149
 
 
150
                                // Determine if we have a boundary vertex.
 
151
                                if( pVertex->isBoundaryVertex() )
 
152
                                {
 
153
                                        // The vertex is on a boundary.
 
154
                                        /// \note If "interpolateboundary" is not specified, we will never see this as
 
155
                                        /// the boundary facets aren't rendered. So we don't need to check for "interpolateboundary" here.
 
156
                                        std::vector<CqLath*> apQve;
 
157
                                        pVertex->Qve(apQve);
 
158
                                        // Is the valence == 2 ?
 
159
                                        if( apQve.size() == 2 )
 
160
                                        {
 
161
                                                // Yes, boundary with valence 2 is corner.
 
162
                                                pParam->pValue( iIndex )[arrayindex] = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
163
                                        }
 
164
                                        else
 
165
                                        {
 
166
                                                // No, boundary is average of two adjacent boundary edges, and original point.
 
167
                                                // Get the midpoints of the adjacent boundary edges
 
168
                                                std::vector<CqLath*> aQve;
 
169
                                                pVertex->Qve( aQve );
 
170
 
 
171
                                                TqInt cBoundaryEdges = 0;
 
172
                                                std::vector<CqLath*>::iterator iE;
 
173
                                                for( iE = aQve.begin(); iE != aQve.end(); iE++ )
 
174
                                                {
 
175
                                                        // Only consider the boundary edges.
 
176
                                                        if( NULL == (*iE)->ec() )
 
177
                                                        {
 
178
                                                                if( (*iE)->VertexIndex() == (pVertex->*IndexFunction)() )
 
179
                                                                        R += pParam->pValue( ((*iE)->ccf()->*IndexFunction)() )[arrayindex];
 
180
                                                                else
 
181
                                                                        R += pParam->pValue( ((*iE)->*IndexFunction)() )[arrayindex];
 
182
                                                                cBoundaryEdges++;
 
183
                                                        }
 
184
                                                }
 
185
                                                assert( cBoundaryEdges == 2 );
 
186
 
 
187
                                                // Get the current vertex;
 
188
                                                S = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
189
                                                pParam->pValue( iIndex )[arrayindex] = static_cast<TypeA>( ( R + ( S * 6.0f ) ) / 8.0f );
 
190
                                        }
 
191
                                }
 
192
                                else
 
193
                                {
 
194
                                        // Check if a sharp corner vertex.
 
195
                                        if( CornerSharpness( pVertex ) > 0.0f )
 
196
                                        {
 
197
                                                pParam->pValue( iIndex )[arrayindex] = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
198
                                        }
 
199
                                        else
 
200
                                        {
 
201
                                                // Check if crease vertex.
 
202
                                                std::vector<CqLath*> aQve;
 
203
                                                pVertex->Qve( aQve );
 
204
 
 
205
                                                CqLath* hardEdge1 = NULL;
 
206
                                                CqLath* hardEdge2 = NULL;
 
207
                                                CqLath* hardEdge3 = NULL;
 
208
                                                TqInt se = 0;
 
209
                                                std::vector<CqLath*>::iterator iEdge;
 
210
                                                for( iEdge = aQve.begin(); iEdge != aQve.end(); iEdge++ )
 
211
                                                {
 
212
                                                        float h = EdgeSharpness( (*iEdge) );
 
213
                                                        if( hardEdge1 == NULL || h > EdgeSharpness(hardEdge1) )
 
214
                                                        {
 
215
                                                                hardEdge3 = hardEdge2;
 
216
                                                                hardEdge2 = hardEdge1;
 
217
                                                                hardEdge1 = *iEdge;
 
218
                                                        }
 
219
                                                        else if( hardEdge2 == NULL || h > EdgeSharpness(hardEdge2) )
 
220
                                                        {
 
221
                                                                hardEdge3 = hardEdge2;
 
222
                                                                hardEdge2 = *iEdge;
 
223
                                                        }
 
224
                                                        else if( hardEdge3 == NULL || h > EdgeSharpness(hardEdge3) )
 
225
                                                        {
 
226
                                                                hardEdge3 = *iEdge;
 
227
                                                        }
 
228
 
 
229
                                                        if( h > 0.0f )
 
230
                                                        {
 
231
                                                                se++;
 
232
                                                                //              printf("h = %f\n", h);
 
233
                                                        }
 
234
                                                }
 
235
 
 
236
                                                TypeA softPos;
 
237
                                                TypeA semiSharpPos;
 
238
                                                TypeA sharpPos;
 
239
                                                // Smooth
 
240
                                                // Vertex point is...
 
241
                                                //    Q     2R     S(n-3)
 
242
                                                //   --- + ---- + --------
 
243
                                                //    n      n        n
 
244
                                                //
 
245
                                                // Q = Average of face points surrounding old vertex
 
246
                                                // R = average of midpoints of edges surrounding old vertex
 
247
                                                // S = old vertex
 
248
                                                // n = number of edges sharing the old vertex.
 
249
 
 
250
                                                n = aQve.size();
 
251
 
 
252
                                                // Get the face points of the surrounding faces
 
253
                                                std::vector<CqLath*> aQvf;
 
254
                                                pVertex->Qvf( aQvf );
 
255
                                                std::vector<CqLath*>::iterator iF;
 
256
                                                for( iF = aQvf.begin(); iF != aQvf.end(); iF++ )
 
257
                                                {
 
258
                                                        std::vector<CqLath*> aQfv;
 
259
                                                        (*iF)->Qfv(aQfv);
 
260
                                                        std::vector<CqLath*>::iterator iV;
 
261
                                                        TypeA Val = TypeA(0.0f);
 
262
                                                        for( iV = aQfv.begin(); iV != aQfv.end(); iV++ )
 
263
                                                                Val += pParam->pValue( ((*iV)->*IndexFunction)() )[arrayindex];
 
264
                                                        Val = static_cast<TypeA>( Val / static_cast<TqFloat>( aQfv.size() ) );
 
265
                                                        Q += Val;
 
266
                                                }
 
267
                                                Q /= aQvf.size();
 
268
                                                Q /= n;
 
269
 
 
270
                                                // Get the midpoints of the surrounding edges
 
271
                                                TypeA A = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
272
                                                TypeA B = TypeA(0.0f);
 
273
                                                std::vector<CqLath*>::iterator iE;
 
274
                                                for( iE = aQve.begin(); iE != aQve.end(); iE++ )
 
275
                                                {
 
276
                                                        B = pParam->pValue( ((*iE)->ccf()->*IndexFunction)() )[arrayindex];
 
277
                                                        R += static_cast<TypeA>( (A+B)/2.0f );
 
278
                                                }
 
279
                                                R = static_cast<TypeA>( R * 2.0f );
 
280
                                                R /= n;
 
281
                                                R /= n;
 
282
 
 
283
                                                // Get the current vertex;
 
284
                                                S = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
285
                                                S = static_cast<TypeA>( S * static_cast<TqFloat>(n-3) );
 
286
                                                S /= n;
 
287
 
 
288
                                                //pParam->pValue( iIndex )[0] = Q+R+S;
 
289
                                                softPos = Q+R+S;
 
290
 
 
291
                                                if( se >= 2 )
 
292
                                                {
 
293
                                                        // Crease
 
294
                                                        // Get the midpoints of the surrounding 2 hardest edges
 
295
                                                        R = pParam->pValue((hardEdge1->ccf()->*IndexFunction)() )[arrayindex];
 
296
                                                        R = R + pParam->pValue((hardEdge2->ccf()->*IndexFunction)() )[arrayindex];
 
297
 
 
298
                                                        // Get the current vertex;
 
299
                                                        S = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
300
                                                        semiSharpPos = static_cast<TypeA>( ( R + ( S * 6.0f ) ) / 8.0f );
 
301
                                                }
 
302
 
 
303
                                                sharpPos = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
304
 
 
305
                                                // Blend the three values together weighted by the sharpness values.
 
306
                                                TypeA Pos;
 
307
                                                float h2 = hardEdge2 != NULL ? EdgeSharpness(hardEdge2) : 0.0f;
 
308
                                                float h3 = hardEdge3 != NULL ? EdgeSharpness(hardEdge3) : 0.0f;
 
309
                                                Pos = static_cast<TypeA>( (1.0f - h2)*softPos );
 
310
                                                Pos = static_cast<TypeA>( Pos + (h2 - h3)*semiSharpPos );
 
311
                                                Pos = static_cast<TypeA>( Pos + h3*sharpPos );
 
312
                                                pParam->pValue( iIndex )[arrayindex] = Pos;
 
313
                                        }
 
314
                                }
 
315
                        }
 
316
                        else
 
317
                        {
 
318
                                // Get a pointer to the appropriate index accessor function on CqLath based on class.
 
319
                                TqInt (CqLath::*IndexFunction)() const;
 
320
                                if( pParam->Class() == class_varying )
 
321
                                        IndexFunction = &CqLath::VertexIndex;
 
322
                                else
 
323
                                        IndexFunction = &CqLath::FaceVertexIndex;
 
324
 
 
325
                                TypeA A = pParam->pValue( (pVertex->*IndexFunction)() )[arrayindex];
 
326
                                pParam->pValue( iIndex )[arrayindex] = A;
 
327
                        }
 
328
                }
 
329
    }
 
330
    void                AddEdgeVertex(CqLath* pEdge, TqInt& iVIndex, TqInt& iFVIndex);
 
331
    template<class TypeA, class TypeB>
 
332
    void                CreateEdgeVertex(CqParameterTyped<TypeA, TypeB>* pParam, CqLath* pEdge, TqInt iIndex)
 
333
    {
 
334
                TqInt arraysize = 0, arrayindex;
 
335
                arraysize = pParam->Count();
 
336
                for( arrayindex = 0; arrayindex < arraysize; arrayindex++ )
 
337
                {
 
338
                        TypeA A = TypeA(0.0f);
 
339
                        TypeA B = TypeA(0.0f);
 
340
                        TypeA C = TypeA(0.0f);
 
341
 
 
342
                        if(pParam->Class() == class_vertex /*|| pParam->Class() == class_facevarying*/)
 
343
                        {
 
344
                                // Get a pointer to the appropriate index accessor function on CqLath based on class.
 
345
                                TqInt (CqLath::*IndexFunction)() const;
 
346
                                if( pParam->Class() == class_vertex )
 
347
                                        IndexFunction = &CqLath::VertexIndex;
 
348
                                else
 
349
                                        IndexFunction = &CqLath::FaceVertexIndex;
 
350
 
 
351
                                if( NULL != pEdge->ec() )
 
352
                                {
 
353
                                        // Edge point is the average of the centrepoint of the original edge and the
 
354
                                        // average of the two new face points of the adjacent faces.
 
355
                                        std::vector<CqLath*> aQef;
 
356
                                        pEdge->Qef( aQef );
 
357
                                        std::vector<CqLath*>::iterator iF;
 
358
                                        for( iF = aQef.begin(); iF != aQef.end(); iF++ )
 
359
                                        {
 
360
                                                std::vector<CqLath*> aQfv;
 
361
                                                (*iF)->Qfv(aQfv);
 
362
                                                std::vector<CqLath*>::iterator iV;
 
363
                                                TypeA Val = TypeA(0.0f);
 
364
                                                for( iV = aQfv.begin(); iV != aQfv.end(); iV++ )
 
365
                                                        Val += pParam->pValue( ((*iV)->*IndexFunction)() )[arrayindex];
 
366
                                                Val = static_cast<TypeA>( Val / static_cast<TqFloat>( aQfv.size() ) );
 
367
                                                C += Val;
 
368
                                        }
 
369
                                        C = static_cast<TypeA>( C / static_cast<TqFloat>(aQef.size()) );
 
370
 
 
371
                                        A = pParam->pValue( (pEdge->*IndexFunction)() )[arrayindex];
 
372
                                        B = pParam->pValue( (pEdge->ccf()->*IndexFunction)() )[arrayindex];
 
373
 
 
374
                                        float h = EdgeSharpness( pEdge );
 
375
                                        A = static_cast<TypeA>( ((1.0f+h)*(A+B)) / 2.0f );
 
376
                                        A = static_cast<TypeA>( (A + (1.0f-h)*C) / 2.0f );
 
377
                                }
 
378
                                else
 
379
                                {
 
380
                                        A = pParam->pValue( (pEdge->*IndexFunction)() )[arrayindex];
 
381
                                        B = pParam->pValue( (pEdge->ccf()->*IndexFunction)() )[arrayindex];
 
382
                                        A = static_cast<TypeA>( (A+B)/2.0f );
 
383
                                }
 
384
                        }
 
385
                        else
 
386
                        {
 
387
                                // Get a pointer to the appropriate index accessor function on CqLath based on class.
 
388
                                TqInt (CqLath::*IndexFunction)() const;
 
389
                                if( pParam->Class() == class_varying )
 
390
                                        IndexFunction = &CqLath::VertexIndex;
 
391
                                else
 
392
                                        IndexFunction = &CqLath::FaceVertexIndex;
 
393
 
 
394
                                A = pParam->pValue( (pEdge->*IndexFunction)() )[arrayindex];
 
395
                                B = pParam->pValue( (pEdge->ccf()->*IndexFunction)() )[arrayindex];
 
396
                                A = static_cast<TypeA>( (A+B)/2.0f );
 
397
                        }
 
398
                        pParam->pValue( iIndex )[arrayindex] = A;
 
399
                }
 
400
    }
 
401
    void                AddFaceVertex(CqLath* pFace, TqInt& iVIndex, TqInt& iFVIndex);
 
402
    template<class TypeA, class TypeB>
 
403
    void                CreateFaceVertex(CqParameterTyped<TypeA, TypeB>* pParam, CqLath* pFace, TqInt iIndex)
 
404
    {
 
405
        // Get a pointer to the appropriate index accessor function on CqLath based on class.
 
406
        TqInt (CqLath::*IndexFunction)() const;
 
407
        if( pParam->Class() == class_vertex || pParam->Class() == class_varying)
 
408
            IndexFunction = &CqLath::VertexIndex;
 
409
        else
 
410
            IndexFunction = &CqLath::FaceVertexIndex;
 
411
        // Face point is just the average of the original faces vertices.
 
412
        std::vector<CqLath*> aQfv;
 
413
        pFace->Qfv(aQfv);
 
414
                TqInt arraysize = 0, arrayindex;
 
415
                arraysize = pParam->Count();
 
416
                for( arrayindex = 0; arrayindex < arraysize; arrayindex++ )
 
417
                {
 
418
                std::vector<CqLath*>::iterator iV;
 
419
                TypeA Val = TypeA(0.0f);
 
420
                        for( iV = aQfv.begin(); iV != aQfv.end(); iV++ )
 
421
                        {
 
422
                                assert( ((*iV)->*IndexFunction)() >= 0 &&
 
423
                                                ((*iV)->*IndexFunction)() < pParam->Size() );
 
424
                                Val += pParam->pValue( ((*iV)->*IndexFunction)() )[arrayindex];
 
425
                        }
 
426
                        Val = static_cast<TypeA>( Val / static_cast<TqFloat>( aQfv.size() ) );
 
427
                        pParam->pValue( iIndex )[arrayindex] = Val;
 
428
                }
 
429
    }
 
430
 
 
431
    // Overrides from CqMotionSpec
 
432
    virtual     void    ClearMotionObject( boost::shared_ptr<CqPolygonPoints>& A ) const
 
433
        {}
 
434
    ;
 
435
    virtual     boost::shared_ptr<CqPolygonPoints> ConcatMotionObjects( boost::shared_ptr<CqPolygonPoints> const & A, boost::shared_ptr<CqPolygonPoints> const & B ) const
 
436
    {
 
437
        return ( A );
 
438
    }
 
439
    virtual     boost::shared_ptr<CqPolygonPoints> LinearInterpolateMotionObjects( TqFloat Fraction, boost::shared_ptr<CqPolygonPoints> const & A, boost::shared_ptr<CqPolygonPoints> const & B ) const
 
440
    {
 
441
        return ( A );
 
442
    }
 
443
 
 
444
 
 
445
    void                OutputMesh(const char* fname, std::vector<CqLath*>* paFaces = 0);
 
446
    void                OutputInfo(const char* fname, std::vector<CqLath*>* paFaces = 0);
 
447
private:
 
448
    /// Declared private to prevent copying.
 
449
    CqSubdivision2(const CqSubdivision2&);
 
450
    /// Declared private to prevent copying.
 
451
    CqSubdivision2&     operator=(const CqSubdivision2&);
 
452
 
 
453
    /// Array of pointers to laths, one each representing each facet.
 
454
    std::vector<CqLath*>                                m_apFacets;
 
455
    /// Array of arrays of pointers to laths each array representing the total laths referencing a single vertex.
 
456
    std::vector<std::vector<CqLath*> >  m_aapVertices;
 
457
    /// Array of lath pointers, one for each lath generated.
 
458
    std::vector<CqLath*>                                m_apLaths;
 
459
    /// Map of face indices which are to be treated as holes in the surface, i.e. not rendered.
 
460
    std::map<TqInt, TqBool>                             m_mapHoles;
 
461
    /// Flag indicating whether this surface interpolates it's boundaries or not.
 
462
    TqBool                                                              m_bInterpolateBoundary;
 
463
    /// Map of sharp edges.
 
464
    std::map<CqLath*, TqFloat>                  m_mapSharpEdges;
 
465
    /// Map of sharp corners.
 
466
    std::map<CqLath*, TqFloat>                  m_mapSharpCorners;
 
467
 
 
468
 
 
469
    /// Flag indicating whether the topology structures have been finalised.
 
470
    TqBool                                                      m_fFinalised;
 
471
};
 
472
 
 
473
 
 
474
 
 
475
class CqSurfaceSubdivisionPatch : public CqBasicSurface
 
476
{
 
477
public:
 
478
    CqSurfaceSubdivisionPatch( const boost::shared_ptr<CqSubdivision2>& pTopology, CqLath* pFace)
 
479
    {
 
480
        m_pTopology = pTopology;
 
481
        m_pFace = pFace;
 
482
    }
 
483
 
 
484
    virtual     ~CqSurfaceSubdivisionPatch()
 
485
    {
 
486
        assert(m_pTopology);
 
487
    }
 
488
 
 
489
#ifdef _DEBUG
 
490
    CqString className() const { return CqString("CqSurfaceSubdivisionPatch"); }
 
491
#endif
 
492
 
 
493
    /** Get the pointer to the subdivision surface hull that this patch is part of.
 
494
     */
 
495
    boost::shared_ptr<CqSubdivision2>   pTopology() const
 
496
    {
 
497
        return( m_pTopology );
 
498
    }
 
499
 
 
500
    /** Get the index of the face on the hull that this patch refers to.
 
501
     */
 
502
    CqLath*     pFace() const
 
503
    {
 
504
        return( m_pFace );
 
505
    }
 
506
 
 
507
    virtual     IqAttributes*   pAttributes() const
 
508
    {
 
509
        return ( pTopology()->pPoints()->pAttributes() );
 
510
    }
 
511
    virtual     IqTransform*    pTransform() const
 
512
    {
 
513
        return ( pTopology()->pPoints()->pTransform() );
 
514
    }
 
515
    // Required implementations from IqSurface
 
516
    virtual void        Transform( const CqMatrix& matTx, const CqMatrix& matITTx, const CqMatrix& matRTx, TqInt iTime = 0 )
 
517
    {
 
518
        //pTopology()->pPoints( iTime )->Transform( matTx, matITTx, matRTx );
 
519
    }
 
520
    // NOTE: These should never be called.
 
521
    virtual     TqUint  cUniform() const
 
522
    {
 
523
        return ( 0 );
 
524
    }
 
525
    virtual     TqUint  cVarying() const
 
526
    {
 
527
        return ( 0 );
 
528
    }
 
529
    virtual     TqUint  cVertex() const
 
530
    {
 
531
        return ( 0 );
 
532
    }
 
533
    virtual     TqUint  cFaceVarying() const
 
534
    {
 
535
        return ( 0 );
 
536
    }
 
537
 
 
538
    // Implementations required by CqBasicSurface
 
539
    virtual     CqBound Bound() const;
 
540
    virtual     CqMicroPolyGridBase* Dice();
 
541
    virtual     TqInt   Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits );
 
542
    virtual TqBool      Diceable();
 
543
 
 
544
    virtual     CqMicroPolyGridBase* DiceExtract();
 
545
 
 
546
    /** Determine whether the passed surface is valid to be used as a
 
547
     *  frame in motion blur for this surface.
 
548
     */
 
549
    virtual TqBool      IsMotionBlurMatch( CqBasicSurface* pSurf )
 
550
    {
 
551
        return( TqFalse );
 
552
    }
 
553
 
 
554
    void StoreDice( CqMicroPolyGrid* pGrid, const boost::shared_ptr<CqPolygonPoints>& pPoints, TqInt iParam, TqInt iFVParam, TqInt iVData);
 
555
    boost::shared_ptr<CqSubdivision2> Extract( TqInt iTime );
 
556
 
 
557
private:
 
558
    boost::shared_ptr<CqSubdivision2>   m_pTopology;
 
559
    CqLath*                     m_pFace;
 
560
};
 
561
 
 
562
//----------------------------------------------------------------------
 
563
/** \class CqSurfacePointsPolygons
 
564
 * Container surface to store the polygons making up a RiPointsPolygons surface.
 
565
 */
 
566
 
 
567
class CqSurfaceSubdivisionMesh : public CqSurface
 
568
{
 
569
public:
 
570
    CqSurfaceSubdivisionMesh(const boost::shared_ptr<CqSubdivision2>& pTopology, TqInt NumFaces) :
 
571
            m_NumFaces(NumFaces),
 
572
            m_pTopology( pTopology )
 
573
    {
 
574
    }
 
575
    virtual     ~CqSurfaceSubdivisionMesh()
 
576
    {
 
577
    }
 
578
 
 
579
#ifdef _DEBUG
 
580
    CqString className() const { return CqString("CqSurfaceSubdivisionMesh"); }
 
581
#endif
 
582
 
 
583
    /** Get the gemoetric bound of this GPrim.
 
584
     */
 
585
    virtual     CqBound Bound() const;
 
586
    /** Dice this GPrim.
 
587
     * \return A pointer to a new micropolygrid..
 
588
     */
 
589
    virtual     CqMicroPolyGridBase* Dice()
 
590
    {
 
591
        return(NULL);
 
592
    }
 
593
    /** Split this GPrim into a number of other GPrims.
 
594
     * \param aSplits A reference to a CqBasicSurface array to fill in with the new GPrim pointers.
 
595
     * \return Integer count of new GPrims created.
 
596
     */
 
597
    virtual     TqInt   Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits );
 
598
    /** Determine whether this GPrim is diceable at its current size.
 
599
     */
 
600
    virtual TqBool      Diceable()
 
601
    {
 
602
        return( TqFalse );
 
603
    }
 
604
 
 
605
    virtual void        Transform( const CqMatrix& matTx, const CqMatrix& matITTx, const CqMatrix& matRTx, TqInt iTime = 0 )
 
606
    {
 
607
        assert( m_pTopology );
 
608
        m_pTopology->pPoints()->Transform( matTx, matITTx, matRTx, iTime );
 
609
    }
 
610
 
 
611
    virtual TqBool      IsMotionBlurMatch( CqBasicSurface* pSurf )
 
612
    {
 
613
        return( TqFalse );
 
614
    }
 
615
 
 
616
    virtual     TqUint  cUniform() const
 
617
    {
 
618
        return ( m_NumFaces );
 
619
    }
 
620
    virtual     TqUint  cVarying() const
 
621
    {
 
622
        assert( m_pTopology );
 
623
        assert( m_pTopology->pPoints() );
 
624
        return ( m_pTopology->pPoints()->cVarying() );
 
625
    }
 
626
    virtual     TqUint  cVertex() const
 
627
    {
 
628
        assert( m_pTopology );
 
629
        assert( m_pTopology->pPoints() );
 
630
        return ( m_pTopology->pPoints()->cVarying() );
 
631
    }
 
632
    virtual     TqUint  cFaceVarying() const
 
633
    {
 
634
        assert( m_pTopology );
 
635
        assert( m_pTopology->pPoints() );
 
636
        return ( m_pTopology->pPoints()->cFaceVarying() );
 
637
    }
 
638
 
 
639
private:
 
640
    TqInt       m_NumFaces;
 
641
    boost::shared_ptr<CqSubdivision2>   m_pTopology;            ///< Pointer to the associated CqPolygonPoints class.
 
642
};
 
643
 
 
644
 
 
645
END_NAMESPACE( Aqsis )
 
646
 
 
647
#endif  //      SUBDIVISION2_H_LOADED