- ( p2 - row_stride2 )->m_vertex[i] = ( p2 - row_stride2 )->m_vertex[i] + ( 2.0f * ( ( p1 )->m_vertex[i] - ( p2 - row_stride2 )->m_vertex[i] ) );
- }
- for ( std::size_t i = 0; i < 2; i++ )
- {
- ( p2 - row_stride2 )->m_texcoord[i] = ( ( p1 + 2 * row_stride )->m_texcoord[i] + ( p1 - 2 * row_stride )->m_texcoord[i] ) * 0.5f;
-
- ( p2 - row_stride2 )->m_texcoord[i] = ( p2 - row_stride2 )->m_texcoord[i] + ( 2.0f * ( ( p1 )->m_texcoord[i] - ( p2 - row_stride2 )->m_texcoord[i] ) );
- }
- }
-}
-
-void Patch::ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ){
- switch ( eType )
- {
- case eCapIBevel:
- {
- setDims( 3, 3 );
- m_ctrl[0].m_vertex = p[0];
- m_ctrl[1].m_vertex = p[1];
- m_ctrl[2].m_vertex = p[1];
- m_ctrl[3].m_vertex = p[1];
- m_ctrl[4].m_vertex = p[1];
- m_ctrl[5].m_vertex = p[1];
- m_ctrl[6].m_vertex = p[2];
- m_ctrl[7].m_vertex = p[1];
- m_ctrl[8].m_vertex = p[1];
- }
- break;
- case eCapBevel:
- {
- setDims( 3, 3 );
- Vector3 p3( vector3_added( p[2], vector3_subtracted( p[0], p[1] ) ) );
- m_ctrl[0].m_vertex = p3;
- m_ctrl[1].m_vertex = p3;
- m_ctrl[2].m_vertex = p[2];
- m_ctrl[3].m_vertex = p3;
- m_ctrl[4].m_vertex = p3;
- m_ctrl[5].m_vertex = p[1];
- m_ctrl[6].m_vertex = p3;
- m_ctrl[7].m_vertex = p3;
- m_ctrl[8].m_vertex = p[0];
- }
- break;
- case eCapEndCap:
- {
- Vector3 p5( vector3_mid( p[0], p[4] ) );
-
- setDims( 3, 3 );
- m_ctrl[0].m_vertex = p[0];
- m_ctrl[1].m_vertex = p5;
- m_ctrl[2].m_vertex = p[4];
- m_ctrl[3].m_vertex = p[1];
- m_ctrl[4].m_vertex = p[2];
- m_ctrl[5].m_vertex = p[3];
- m_ctrl[6].m_vertex = p[2];
- m_ctrl[7].m_vertex = p[2];
- m_ctrl[8].m_vertex = p[2];
- }
- break;
- case eCapIEndCap:
- {
- setDims( 5, 3 );
- m_ctrl[0].m_vertex = p[4];
- m_ctrl[1].m_vertex = p[3];
- m_ctrl[2].m_vertex = p[2];
- m_ctrl[3].m_vertex = p[1];
- m_ctrl[4].m_vertex = p[0];
- m_ctrl[5].m_vertex = p[3];
- m_ctrl[6].m_vertex = p[3];
- m_ctrl[7].m_vertex = p[2];
- m_ctrl[8].m_vertex = p[1];
- m_ctrl[9].m_vertex = p[1];
- m_ctrl[10].m_vertex = p[3];
- m_ctrl[11].m_vertex = p[3];
- m_ctrl[12].m_vertex = p[2];
- m_ctrl[13].m_vertex = p[1];
- m_ctrl[14].m_vertex = p[1];
- }
- break;
- case eCapCylinder:
- {
- std::size_t mid = ( width - 1 ) >> 1;
-
- bool degenerate = ( mid % 2 ) != 0;
-
- std::size_t newHeight = mid + ( degenerate ? 2 : 1 );
-
- setDims( 3, newHeight );
-
- if ( degenerate ) {
- ++mid;
- for ( std::size_t i = width; i != width + 2; ++i )
- {
- p[i] = p[width - 1];
- }
- }
-
- {
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t i = 0; i != m_height; ++i, pCtrl += m_width )
- {
- pCtrl->m_vertex = p[i];
- }
- }
- {
- PatchControl* pCtrl = m_ctrl.data() + 2;
- std::size_t h = m_height - 1;
- for ( std::size_t i = 0; i != m_height; ++i, pCtrl += m_width )
- {
- pCtrl->m_vertex = p[h + ( h - i )];
- }
- }
-
- Redisperse( COL );
- }
- break;
- default:
- ERROR_MESSAGE( "invalid patch-cap type" );
- return;
- }
- CapTexture();
- controlPointsChanged();
-}
-
-void Patch::ProjectTexture( int nAxis ){
- undoSave();
-
- int s, t;
-
- switch ( nAxis )
- {
- case 2:
- s = 0;
- t = 1;
- break;
- case 0:
- s = 1;
- t = 2;
- break;
- case 1:
- s = 0;
- t = 2;
- break;
- default:
- ERROR_MESSAGE( "invalid axis" );
- return;
- }
-
- float fWidth = 1 / ( m_state->getTexture().width * Texdef_getDefaultTextureScale() );
- float fHeight = 1 / ( m_state->getTexture().height * -Texdef_getDefaultTextureScale() );
-
- for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i )
- {
- ( *i ).m_texcoord[0] = ( *i ).m_vertex[s] * fWidth;
- ( *i ).m_texcoord[1] = ( *i ).m_vertex[t] * fHeight;
- }
-
- controlPointsChanged();
-}
-
-void Patch::constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ){
- setDims( width, height );
-
- int x, y, z;
- switch ( axis )
- {
- case 2: x = 0; y = 1; z = 2; break;
- case 1: x = 0; y = 2; z = 1; break;
- case 0: x = 1; y = 2; z = 0; break;
- default:
- ERROR_MESSAGE( "invalid view-type" );
- return;
- }
-
- if ( m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH ) {
- m_width = 3;
- }
- if ( m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT ) {
- m_height = 3;
- }
-
- Vector3 vStart;
- vStart[x] = aabb.origin[x] - aabb.extents[x];
- vStart[y] = aabb.origin[y] - aabb.extents[y];
- vStart[z] = aabb.origin[z];
-
- float xAdj = fabsf( ( vStart[x] - ( aabb.origin[x] + aabb.extents[x] ) ) / (float)( m_width - 1 ) );
- float yAdj = fabsf( ( vStart[y] - ( aabb.origin[y] + aabb.extents[y] ) ) / (float)( m_height - 1 ) );
-
- Vector3 vTmp;
- vTmp[z] = vStart[z];
- PatchControl* pCtrl = m_ctrl.data();
-
- vTmp[y] = vStart[y];
- for ( std::size_t h = 0; h < m_height; h++ )
- {
- vTmp[x] = vStart[x];
- for ( std::size_t w = 0; w < m_width; w++, ++pCtrl )
- {
- pCtrl->m_vertex = vTmp;
- vTmp[x] += xAdj;
- }
- vTmp[y] += yAdj;
- }
-
- NaturalTexture();
-}
-
-void Patch::ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height ){
- Vector3 vPos[3];
-
- if ( eType != ePlane ) {
- vPos[0] = vector3_subtracted( aabb.origin, aabb.extents );
- vPos[1] = aabb.origin;
- vPos[2] = vector3_added( aabb.origin, aabb.extents );
- }
-
- if ( eType == ePlane ) {
- constructPlane( aabb, axis, width, height );
- }
- else if ( eType == eSqCylinder
- || eType == eCylinder
- || eType == eDenseCylinder
- || eType == eVeryDenseCylinder
- || eType == eCone
- || eType == eSphere ) {
- unsigned char *pIndex;
- unsigned char pCylIndex[] =
- {
- 0, 0,
- 1, 0,
- 2, 0,
- 2, 1,
- 2, 2,
- 1, 2,
- 0, 2,
- 0, 1,
- 0, 0
- };
-
-
- PatchControl *pStart;
- switch ( eType )
- {
- case eSqCylinder: setDims( 9, 3 );
- pStart = m_ctrl.data();
- break;
- case eDenseCylinder:
- case eVeryDenseCylinder:
- case eCylinder:
- setDims( 9, 3 );
- pStart = m_ctrl.data() + 1;
- break;
- case eCone: setDims( 9, 3 );
- pStart = m_ctrl.data() + 1;
- break;
- case eSphere:
- setDims( 9, 5 );
- pStart = m_ctrl.data() + ( 9 + 1 );
- break;
- default:
- ERROR_MESSAGE( "this should be unreachable" );
- return;
- }
-
- for ( std::size_t h = 0; h < 3; h++, pStart += 9 )
- {
- pIndex = pCylIndex;
- PatchControl* pCtrl = pStart;
- for ( std::size_t w = 0; w < 8; w++, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
- pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
- pCtrl->m_vertex[2] = vPos[h][2];
- pIndex += 2;
- }
- }
-
- switch ( eType )
- {
- case eSqCylinder:
- {
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 )
- {
- pCtrl[8].m_vertex = pCtrl[0].m_vertex;
- }
- }
- break;
- case eDenseCylinder:
- case eVeryDenseCylinder:
- case eCylinder:
- {
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 )
- {
- pCtrl[0].m_vertex = pCtrl[8].m_vertex;
- }
- }
- break;
- case eCone:
- {
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t h = 0; h < 2; h++, pCtrl += 9 )
- {
- pCtrl[0].m_vertex = pCtrl[8].m_vertex;
- }
- }
- {
- PatchControl* pCtrl = m_ctrl.data() + 9 * 2;
- for ( std::size_t w = 0; w < 9; w++, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[1][0];
- pCtrl->m_vertex[1] = vPos[1][1];
- pCtrl->m_vertex[2] = vPos[2][2];
- }
- }
- break;
- case eSphere:
- {
- PatchControl* pCtrl = m_ctrl.data() + 9;
- for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 )
- {
- pCtrl[0].m_vertex = pCtrl[8].m_vertex;
- }
- }
- {
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t w = 0; w < 9; w++, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[1][0];
- pCtrl->m_vertex[1] = vPos[1][1];
- pCtrl->m_vertex[2] = vPos[0][2];
- }
- }
- {
- PatchControl* pCtrl = m_ctrl.data() + ( 9 * 4 );
- for ( std::size_t w = 0; w < 9; w++, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[1][0];
- pCtrl->m_vertex[1] = vPos[1][1];
- pCtrl->m_vertex[2] = vPos[2][2];
- }
- }
- break;
- default:
- ERROR_MESSAGE( "this should be unreachable" );
- return;
- }
- }
- else if ( eType == eXactCylinder ) {
- int n = ( width - 1 ) / 2; // n = number of segments
- setDims( width, height );
-
- // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
- // vPos[1] = aabb.origin;
- // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
- int i, j;
- float f = 1 / cos( M_PI / n );
- for ( i = 0; i < width; ++i )
- {
- float angle = ( M_PI * i ) / n; // 0 to 2pi
- float x = vPos[1][0] + ( vPos[2][0] - vPos[1][0] ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f );
- float y = vPos[1][1] + ( vPos[2][1] - vPos[1][1] ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f );
- for ( j = 0; j < height; ++j )
- {
- float z = vPos[0][2] + ( vPos[2][2] - vPos[0][2] ) * ( j / (float)( height - 1 ) );
- PatchControl *v;
- v = &m_ctrl.data()[j * width + i];
- v->m_vertex[0] = x;
- v->m_vertex[1] = y;
- v->m_vertex[2] = z;
- }
- }
- }
- else if ( eType == eXactCone ) {
- int n = ( width - 1 ) / 2; // n = number of segments
- setDims( width, height );
-
- // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
- // vPos[1] = aabb.origin;
- // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
- int i, j;
- float f = 1 / cos( M_PI / n );
- for ( i = 0; i < width; ++i )
- {
- float angle = ( M_PI * i ) / n;
- for ( j = 0; j < height; ++j )
- {
- float x = vPos[1][0] + ( 1.0f - ( j / (float)( height - 1 ) ) ) * ( vPos[2][0] - vPos[1][0] ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f );
- float y = vPos[1][1] + ( 1.0f - ( j / (float)( height - 1 ) ) ) * ( vPos[2][1] - vPos[1][1] ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f );
- float z = vPos[0][2] + ( vPos[2][2] - vPos[0][2] ) * ( j / (float)( height - 1 ) );
- PatchControl *v;
- v = &m_ctrl.data()[j * width + i];
- v->m_vertex[0] = x;
- v->m_vertex[1] = y;
- v->m_vertex[2] = z;
- }
- }
- }
- else if ( eType == eXactSphere ) {
- int n = ( width - 1 ) / 2; // n = number of segments (yaw)
- int m = ( height - 1 ) / 2; // m = number of segments (pitch)
- setDims( width, height );
-
- // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
- // vPos[1] = aabb.origin;
- // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
- int i, j;
- float f = 1 / cos( M_PI / n );
- float g = 1 / cos( M_PI / ( 2 * m ) );
- for ( i = 0; i < width; ++i )
- {
- float angle = ( M_PI * i ) / n;
- for ( j = 0; j < height; ++j )
- {
- float angle2 = ( M_PI * j ) / ( 2 * m );
- float x = vPos[1][0] + ( vPos[2][0] - vPos[1][0] ) * sin( angle2 ) * ( ( j & 1 ) ? g : 1.0f ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f );
- float y = vPos[1][1] + ( vPos[2][1] - vPos[1][1] ) * sin( angle2 ) * ( ( j & 1 ) ? g : 1.0f ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f );
- float z = vPos[1][2] + ( vPos[2][2] - vPos[1][2] ) * -cos( angle2 ) * ( ( j & 1 ) ? g : 1.0f );
- PatchControl *v;
- v = &m_ctrl.data()[j * width + i];
- v->m_vertex[0] = x;
- v->m_vertex[1] = y;
- v->m_vertex[2] = z;
- }
- }
- }
- else if ( eType == eBevel ) {
- unsigned char *pIndex;
- unsigned char pBevIndex[] =
- {
- 0, 0,
- 2, 0,
- 2, 2,
- };
-
- setDims( 3, 3 );
-
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t h = 0; h < 3; h++ )
- {
- pIndex = pBevIndex;
- for ( std::size_t w = 0; w < 3; w++, pIndex += 2, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
- pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
- pCtrl->m_vertex[2] = vPos[h][2];
- }
- }
- }
- else if ( eType == eEndCap ) {
- unsigned char *pIndex;
- unsigned char pEndIndex[] =
- {
- 2, 0,
- 2, 2,
- 1, 2,
- 0, 2,
- 0, 0,
- };
-
- setDims( 5, 3 );
-
- PatchControl* pCtrl = m_ctrl.data();
- for ( std::size_t h = 0; h < 3; h++ )
- {
- pIndex = pEndIndex;
- for ( std::size_t w = 0; w < 5; w++, pIndex += 2, pCtrl++ )
- {
- pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
- pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
- pCtrl->m_vertex[2] = vPos[h][2];
- }
- }
- }
-
- if ( eType == eDenseCylinder ) {
- InsertRemove( true, false, true );
- }
-
- if ( eType == eVeryDenseCylinder ) {
- InsertRemove( true, false, false );
- InsertRemove( true, false, true );
- }
-
- NaturalTexture();
-}
-
-void Patch::RenderDebug( RenderStateFlags state ) const {
- for ( std::size_t i = 0; i < m_tess.m_numStrips; i++ )
- {
- glBegin( GL_QUAD_STRIP );
- for ( std::size_t j = 0; j < m_tess.m_lenStrips; j++ )
- {
- glNormal3fv( normal3f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->normal ) );
- glTexCoord2fv( texcoord2f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->texcoord ) );
- glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->vertex ) );
- }
- glEnd();
- }
-}
-
-void RenderablePatchSolid::RenderNormals() const {
- const std::size_t width = m_tess.m_numStrips + 1;
- const std::size_t height = m_tess.m_lenStrips >> 1;
- glBegin( GL_LINES );
- for ( std::size_t i = 0; i < width; i++ )
- {
- for ( std::size_t j = 0; j < height; j++ )
- {
- {
- Vector3 vNormal(
- vector3_added(
- vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ),
- vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->normal ), 8 )
- )
- );
- glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) );
- glVertex3fv( &vNormal[0] );
- }
- {
- Vector3 vNormal(
- vector3_added(
- vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ),
- vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->tangent ), 8 )
- )
- );
- glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) );
- glVertex3fv( &vNormal[0] );
- }
- {
- Vector3 vNormal(
- vector3_added(
- vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ),
- vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->bitangent ), 8 )
- )
- );
- glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) );
- glVertex3fv( &vNormal[0] );
- }
- }
- }
- glEnd();
-}
-
-#define DEGEN_0a 0x01
-#define DEGEN_1a 0x02
-#define DEGEN_2a 0x04
-#define DEGEN_0b 0x08
-#define DEGEN_1b 0x10
-#define DEGEN_2b 0x20
-#define SPLIT 0x40
-#define AVERAGE 0x80
-
-
-unsigned int subarray_get_degen( PatchControlIter subarray, std::size_t strideU, std::size_t strideV ){
- unsigned int nDegen = 0;
- const PatchControl* p1;
- const PatchControl* p2;
-
- p1 = subarray;
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_0a;
- }
- p1 = p2;
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_0b;
- }
-
- p1 = subarray + strideV;
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_1a;
- }
- p1 = p2;
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_1b;
- }
-
- p1 = subarray + ( strideV << 1 );
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_2a;
- }
- p1 = p2;
- p2 = p1 + strideU;
- if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) {
- nDegen |= DEGEN_2b;
- }
-
- return nDegen;
-}
-
-
-inline void deCasteljau3( const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012 ){
- P01 = vector3_mid( P0, P1 );
- P12 = vector3_mid( P1, P2 );
- P012 = vector3_mid( P01, P12 );
-}
-
-inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end ){
- left = vector3_mid( start, mid );
- right = vector3_mid( mid, end );
- mid = vector3_mid( left, right );
-}
-
-inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end ){
- left[0] = float_mid( start[0], mid[0] );
- left[1] = float_mid( start[1], mid[1] );
- right[0] = float_mid( mid[0], end[0] );
- right[1] = float_mid( mid[1], end[1] );
- mid[0] = float_mid( left[0], right[0] );
- mid[1] = float_mid( left[1], right[1] );
-}
-
-
-inline Vector2& texcoord_for_index( Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<Vector2&>( vertices[index].texcoord );
-}
-
-inline Vector3& vertex_for_index( Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<Vector3&>( vertices[index].vertex );
-}
-
-inline Vector3& normal_for_index( Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<Vector3&>( vertices[index].normal );
-}
-
-inline Vector3& tangent_for_index( Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<Vector3&>( vertices[index].tangent );
-}
-
-inline Vector3& bitangent_for_index( Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<Vector3&>( vertices[index].bitangent );
-}
-
-inline const Vector2& texcoord_for_index( const Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<const Vector2&>( vertices[index].texcoord );
-}
-
-inline const Vector3& vertex_for_index( const Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<const Vector3&>( vertices[index].vertex );
-}
-
-inline const Vector3& normal_for_index( const Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<const Vector3&>( vertices[index].normal );
-}
-
-inline const Vector3& tangent_for_index( const Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<const Vector3&>( vertices[index].tangent );
-}
-
-inline const Vector3& bitangent_for_index( const Array<ArbitraryMeshVertex>& vertices, std::size_t index ){
- return reinterpret_cast<const Vector3&>( vertices[index].bitangent );
-}
-
-#include "math/curve.h"
-
-inline PatchControl QuadraticBezier_evaluate( const PatchControl* firstPoint, double t ){
- PatchControl result = { Vector3( 0, 0, 0 ), Vector2( 0, 0 ) };
- double denominator = 0;
-
- {
- double weight = BernsteinPolynomial<Zero, Two>::apply( t );
- vector3_add( result.m_vertex, vector3_scaled( firstPoint[0].m_vertex, weight ) );
- vector2_add( result.m_texcoord, vector2_scaled( firstPoint[0].m_texcoord, weight ) );
- denominator += weight;
- }
- {
- double weight = BernsteinPolynomial<One, Two>::apply( t );
- vector3_add( result.m_vertex, vector3_scaled( firstPoint[1].m_vertex, weight ) );
- vector2_add( result.m_texcoord, vector2_scaled( firstPoint[1].m_texcoord, weight ) );
- denominator += weight;
- }
- {
- double weight = BernsteinPolynomial<Two, Two>::apply( t );
- vector3_add( result.m_vertex, vector3_scaled( firstPoint[2].m_vertex, weight ) );
- vector2_add( result.m_texcoord, vector2_scaled( firstPoint[2].m_texcoord, weight ) );
- denominator += weight;
- }
-
- vector3_divide( result.m_vertex, denominator );
- vector2_divide( result.m_texcoord, denominator );
- return result;
-}
-
-inline Vector3 vector3_linear_interpolated( const Vector3& a, const Vector3& b, double t ){
- return vector3_added( vector3_scaled( a, 1.0 - t ), vector3_scaled( b, t ) );
-}
-
-inline Vector2 vector2_linear_interpolated( const Vector2& a, const Vector2& b, double t ){
- return vector2_added( vector2_scaled( a, 1.0 - t ), vector2_scaled( b, t ) );
-}
-
-void normalise_safe( Vector3& normal ){
- if ( !vector3_equal( normal, g_vector3_identity ) ) {
- vector3_normalise( normal );
- }
-}
-
-inline void QuadraticBezier_evaluate( const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right ){
- left.m_vertex = vector3_linear_interpolated( a.m_vertex, b.m_vertex, t );
- left.m_texcoord = vector2_linear_interpolated( a.m_texcoord, b.m_texcoord, t );
- right.m_vertex = vector3_linear_interpolated( b.m_vertex, c.m_vertex, t );
- right.m_texcoord = vector2_linear_interpolated( b.m_texcoord, c.m_texcoord, t );
- point.m_vertex = vector3_linear_interpolated( left.m_vertex, right.m_vertex, t );
- point.m_texcoord = vector2_linear_interpolated( left.m_texcoord, right.m_texcoord, t );
-}
-
-void Patch::TesselateSubMatrixFixed( ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3] ){
- double incrementU = 1.0 / m_subdivisions_x;
- double incrementV = 1.0 / m_subdivisions_y;
- const std::size_t width = m_subdivisions_x + 1;
- const std::size_t height = m_subdivisions_y + 1;
-
- for ( std::size_t i = 0; i != width; ++i )
- {
- double tU = ( i + 1 == width ) ? 1 : i * incrementU;
- PatchControl pointX[3];
- PatchControl leftX[3];
- PatchControl rightX[3];
- QuadraticBezier_evaluate( *subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0] );
- QuadraticBezier_evaluate( *subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1] );
- QuadraticBezier_evaluate( *subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2] );
-
- ArbitraryMeshVertex* p = vertices + i * strideX;
- for ( std::size_t j = 0; j != height; ++j )
- {
- if ( ( j == 0 || j + 1 == height ) && ( i == 0 || i + 1 == width ) ) {
- }
- else
- {
- double tV = ( j + 1 == height ) ? 1 : j * incrementV;
-
- PatchControl pointY[3];
- PatchControl leftY[3];
- PatchControl rightY[3];
- QuadraticBezier_evaluate( *subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0] );
- QuadraticBezier_evaluate( *subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1] );
- QuadraticBezier_evaluate( *subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2] );
-
- PatchControl point;
- PatchControl left;
- PatchControl right;
- QuadraticBezier_evaluate( pointX[0], pointX[1], pointX[2], tV, point, left, right );
- PatchControl up;
- PatchControl down;
- QuadraticBezier_evaluate( pointY[0], pointY[1], pointY[2], tU, point, up, down );
-
- vertex3f_to_vector3( p->vertex ) = point.m_vertex;
- texcoord2f_to_vector2( p->texcoord ) = point.m_texcoord;
-
- ArbitraryMeshVertex a, b, c;
-
- a.vertex = vertex3f_for_vector3( left.m_vertex );
- a.texcoord = texcoord2f_for_vector2( left.m_texcoord );
- b.vertex = vertex3f_for_vector3( right.m_vertex );
- b.texcoord = texcoord2f_for_vector2( right.m_texcoord );
-
- if ( i != 0 ) {
- c.vertex = vertex3f_for_vector3( up.m_vertex );
- c.texcoord = texcoord2f_for_vector2( up.m_texcoord );
- }
- else
- {
- c.vertex = vertex3f_for_vector3( down.m_vertex );
- c.texcoord = texcoord2f_for_vector2( down.m_texcoord );
- }
-
- Vector3 normal = vector3_normalised( vector3_cross( right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex ) );
-
- Vector3 tangent, bitangent;
- ArbitraryMeshTriangle_calcTangents( a, b, c, tangent, bitangent );
- vector3_normalise( tangent );
- vector3_normalise( bitangent );
-
- if ( ( ( nFlagsX & AVERAGE ) != 0 && i == 0 ) || ( ( nFlagsY & AVERAGE ) != 0 && j == 0 ) ) {
- normal3f_to_vector3( p->normal ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->normal ), normal ) );
- normal3f_to_vector3( p->tangent ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->tangent ), tangent ) );
- normal3f_to_vector3( p->bitangent ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->bitangent ), bitangent ) );
- }
- else
- {
- normal3f_to_vector3( p->normal ) = normal;
- normal3f_to_vector3( p->tangent ) = tangent;
- normal3f_to_vector3( p->bitangent ) = bitangent;
- }
- }
-
- p += strideY;
- }
- }
-}
-
-void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
- std::size_t offStartX, std::size_t offStartY,
- std::size_t offEndX, std::size_t offEndY,
- std::size_t nFlagsX, std::size_t nFlagsY,
- Vector3& left, Vector3& mid, Vector3& right,
- Vector2& texLeft, Vector2& texMid, Vector2& texRight,
- bool bTranspose ){
- int newFlagsX, newFlagsY;
-
- Vector3 tmp;
- Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
- Vector2 texTmp;
- Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
-
- {
- // texcoords
-
- BezierInterpolate2( texcoord_for_index( m_tess.m_vertices, offStartX + offStartY ),
- texcoord_0_0,
- texcoord_for_index( m_tess.m_vertices, BX->index + offStartY ),
- texcoord_0_1,
- texcoord_for_index( m_tess.m_vertices, offEndX + offStartY ) );
-
-
- BezierInterpolate2( texcoord_for_index( m_tess.m_vertices, offStartX + offEndY ),
- texcoord_2_0,
- texcoord_for_index( m_tess.m_vertices, BX->index + offEndY ),
- texcoord_2_1,
- texcoord_for_index( m_tess.m_vertices, offEndX + offEndY ) );
-
- texTmp = texMid;
-
- BezierInterpolate2( texLeft,
- texcoord_1_0,
- texTmp,
- texcoord_1_1,
- texRight );
-
- if ( !BezierCurveTree_isLeaf( BY ) ) {
- texcoord_for_index( m_tess.m_vertices, BX->index + BY->index ) = texTmp;
- }
-
-
- if ( !BezierCurveTree_isLeaf( BX->left ) ) {
- texcoord_for_index( m_tess.m_vertices, BX->left->index + offStartY ) = texcoord_0_0;
- texcoord_for_index( m_tess.m_vertices, BX->left->index + offEndY ) = texcoord_2_0;