2525
2626#include " cinder/TriMesh.h"
2727#include " cinder/Exception.h"
28+ #include " cinder/Log.h"
2829#if defined( CINDER_ANDROID )
2930 #include " cinder/android/CinderAndroid.h"
3031#endif
@@ -80,7 +81,7 @@ void TriMeshGeomTarget::copyIndices( geom::Primitive primitive, const uint32_t *
8081// TriMesh::Format
8182TriMesh::Format::Format ()
8283{
83- mPositionsDims = mNormalsDims = mTangentsDims = mBitangentsDims = mColorsDims = 0 ;
84+ mPositionsDims = mNormalsDims = mTangentsDims = mBitangentsDims = mBoneIndicesDims = mBoneWeightsDims = mColorsDims = 0 ;
8485 mTexCoords0Dims = mTexCoords1Dims = mTexCoords2Dims = mTexCoords3Dims = 0 ;
8586}
8687
@@ -110,6 +111,8 @@ void TriMesh::loadFromSource( const geom::Source &source )
110111 if ( mNormalsDims ) attribs.insert ( geom::Attrib::NORMAL );
111112 if ( mTangentsDims ) attribs.insert ( geom::Attrib::TANGENT );
112113 if ( mBitangentsDims ) attribs.insert ( geom::Attrib::BITANGENT );
114+ if ( mBoneIndicesDims ) attribs.insert ( geom::Attrib::BONE_INDEX );
115+ if ( mBoneWeightsDims ) attribs.insert ( geom::Attrib::BONE_WEIGHT );
113116 if ( mColorsDims ) attribs.insert ( geom::Attrib::COLOR );
114117 if ( mTexCoords0Dims ) attribs.insert ( geom::Attrib::TEX_COORD_0 );
115118 if ( mTexCoords1Dims ) attribs.insert ( geom::Attrib::TEX_COORD_1 );
@@ -130,6 +133,8 @@ void TriMesh::initFromFormat( const TriMesh::Format &format )
130133 mNormalsDims = format.mNormalsDims ;
131134 mTangentsDims = format.mTangentsDims ;
132135 mBitangentsDims = format.mBitangentsDims ;
136+ mBoneIndicesDims = format.mBoneIndicesDims ;
137+ mBoneWeightsDims = format.mBoneWeightsDims ;
133138 mColorsDims = format.mColorsDims ;
134139 mTexCoords0Dims = format.mTexCoords0Dims ;
135140 mTexCoords1Dims = format.mTexCoords1Dims ;
@@ -157,6 +162,14 @@ TriMesh::Format TriMesh::formatFromSource( const geom::Source &source )
157162 if ( source.getAttribDims ( geom::Attrib::BITANGENT ) > 0 )
158163 result.mBitangentsDims = 3 ;
159164
165+ // bone indices
166+ if ( source.getAttribDims ( geom::Attrib::BONE_INDEX ) > 0 )
167+ result.mBoneIndicesDims = 4 ;
168+
169+ // bone weights
170+ if ( source.getAttribDims ( geom::Attrib::BONE_WEIGHT ) > 0 )
171+ result.mBoneWeightsDims = 4 ;
172+
160173 // colors
161174 if ( source.getAttribDims ( geom::Attrib::COLOR ) > 0 )
162175 result.mColorsDims = source.getAttribDims ( geom::Attrib::COLOR );
@@ -208,6 +221,8 @@ void TriMesh::clear()
208221 mNormals .clear ();
209222 mTangents .clear ();
210223 mBitangents .clear ();
224+ mBoneIndices .clear ();
225+ mBoneWeights .clear ();
211226 mColors .clear ();
212227 mTexCoords0 .clear ();
213228 mTexCoords1 .clear ();
@@ -257,6 +272,18 @@ void TriMesh::appendBitangents( const vec3 *bitangents, size_t num )
257272 mBitangents .insert ( mBitangents .end (), bitangents, bitangents + num );
258273}
259274
275+ void TriMesh::appendBoneIndices ( const vec4 *boneIndices, size_t num )
276+ {
277+ assert ( mBoneIndicesDims == 4 );
278+ mBoneIndices .insert ( mBoneIndices .end (), boneIndices, boneIndices + num );
279+ }
280+
281+ void TriMesh::appendBoneWeights ( const vec4 *boneWeights, size_t num )
282+ {
283+ assert ( mBoneWeightsDims == 4 );
284+ mBoneWeights .insert ( mBoneWeights .end (), boneWeights, boneWeights + num );
285+ }
286+
260287void TriMesh::appendColors ( const Color *rgbs, size_t num )
261288{
262289 assert ( mColorsDims == 3 );
@@ -390,6 +417,22 @@ void TriMesh::getTriangleBitangents( size_t idx, vec3 *a, vec3 *b, vec3 *c ) con
390417 *c = mBitangents [mIndices [idx * 3 + 2 ]];
391418}
392419
420+ void TriMesh::getTriangleBoneIndices ( size_t idx, vec4* a, vec4* b, vec4* c ) const
421+ {
422+ assert ( mBoneIndicesDims == 4 );
423+ *a = mBoneIndices [mIndices [idx * 3 + 0 ]];
424+ *b = mBoneIndices [mIndices [idx * 3 + 1 ]];
425+ *c = mBoneIndices [mIndices [idx * 3 + 2 ]];
426+ }
427+
428+ void TriMesh::getTriangleBoneWeights ( size_t idx, vec4* a, vec4* b, vec4* c ) const
429+ {
430+ assert ( mBoneIndicesDims == 4 );
431+ *a = mBoneWeights [mIndices [idx * 3 + 0 ]];
432+ *b = mBoneWeights [mIndices [idx * 3 + 1 ]];
433+ *c = mBoneWeights [mIndices [idx * 3 + 2 ]];
434+ }
435+
393436AxisAlignedBox TriMesh::calcBoundingBox () const
394437{
395438 assert ( mPositionsDims == 3 );
@@ -513,6 +556,8 @@ void TriMesh::write( const DataTargetRef &dataTarget, uint32_t writeMask ) const
513556 writeAttrib ( toMask ( geom::TEX_COORD_3 ), mTexCoords3Dims , mTexCoords3 .size (), mTexCoords3 .data () );
514557 writeAttrib ( toMask ( geom::TANGENT ), mTangentsDims , mTangents .size () * 3 , mTangents .data () );
515558 writeAttrib ( toMask ( geom::BITANGENT ), mBitangentsDims , mBitangents .size () * 3 , mBitangents .data () );
559+ writeAttrib ( toMask ( geom::BONE_INDEX ), mBoneIndicesDims , mBoneIndices .size () * 4 , mBoneIndices .data () );
560+ writeAttrib ( toMask ( geom::BONE_WEIGHT ), mBoneWeightsDims , mBoneWeights .size () * 4 , mBoneWeights .data () );
516561}
517562
518563// used in 0.9.0
@@ -542,6 +587,18 @@ void TriMesh::readImplV2( const IStreamRef &in )
542587 in->readData ( data->data (), sizeInFloats * sizeof ( float ) );
543588 };
544589
590+ auto readAttribVec4f = [in]( uint8_t *dims, std::vector<vec4> *data ) {
591+ if ( in->isEof () ) return ;
592+
593+ in->readLittle ( dims );
594+
595+ uint32_t sizeInFloats;
596+ in->readLittle ( &sizeInFloats );
597+
598+ data->resize ( sizeInFloats * sizeof ( float ) / sizeof ( vec4 ) );
599+ in->readData ( data->data (), sizeInFloats * sizeof ( float ) );
600+ };
601+
545602 // indices
546603 uint32_t numIndices;
547604 in->readLittle ( &numIndices );
@@ -583,6 +640,12 @@ void TriMesh::readImplV2( const IStreamRef &in )
583640 case geom::BITANGENT:
584641 readAttribVec3f ( &mBitangentsDims , &mBitangents );
585642 break ;
643+ case geom::BONE_INDEX:
644+ readAttribVec4f ( &mBoneIndicesDims , &mBoneIndices );
645+ break ;
646+ case geom::BONE_WEIGHT:
647+ readAttribVec4f ( &mBoneWeightsDims , &mBoneWeights );
648+ break ;
586649 default :
587650 throw Exception ( " TriMesh::read() error: Invalid file contents." );
588651 break ;
@@ -757,6 +820,8 @@ bool TriMesh::recalculateBitangents()
757820// ! TODO: optimize memory allocations
758821void TriMesh::subdivide ( int division, bool normalize )
759822{
823+ if ( hasBoneIndices () || hasBoneWeights () )
824+ CI_LOG_W ( " TriMesh::subdivide does not currently support bone indices or bone weights" );
760825 if ( division < 2 )
761826 return ;
762827
@@ -1011,6 +1076,8 @@ uint8_t TriMesh::getAttribDims( geom::Attrib attr ) const
10111076 case geom::Attrib::NORMAL: return mNormalsDims ;
10121077 case geom::Attrib::TANGENT: return mTangentsDims ;
10131078 case geom::Attrib::BITANGENT: return mBitangentsDims ;
1079+ case geom::Attrib::BONE_INDEX: return mBoneIndicesDims ;
1080+ case geom::Attrib::BONE_WEIGHT: return mBoneWeightsDims ;
10141081 default :
10151082 return 0 ;
10161083 }
@@ -1029,6 +1096,8 @@ geom::AttribSet TriMesh::getAvailableAttribs() const
10291096 if ( mNormalsDims ) result.insert ( geom::Attrib::NORMAL );
10301097 if ( mTangentsDims ) result.insert ( geom::Attrib::TANGENT );
10311098 if ( mBitangentsDims ) result.insert ( geom::Attrib::BITANGENT );
1099+ if ( mBoneIndicesDims ) result.insert ( geom::Attrib::BONE_INDEX );
1100+ if ( mBoneWeightsDims ) result.insert ( geom::Attrib::BONE_WEIGHT );
10321101
10331102 return result;
10341103}
@@ -1045,52 +1114,62 @@ void TriMesh::getAttribPointer( geom::Attrib attr, const float **resultPtr, size
10451114 case geom::Attrib::NORMAL: *resultPtr = (const float *)mNormals .data (); *resultStrideBytes = 0 ; *resultDims = mNormalsDims ; break ;
10461115 case geom::Attrib::TANGENT: *resultPtr = (const float *)mTangents .data (); *resultStrideBytes = 0 ; *resultDims = mTangentsDims ; break ;
10471116 case geom::Attrib::BITANGENT: *resultPtr = (const float *)mBitangents .data (); *resultStrideBytes = 0 ; *resultDims = mBitangentsDims ; break ;
1117+ case geom::Attrib::BONE_INDEX: *resultPtr = (const float *)mBoneIndices .data (); *resultStrideBytes = 0 ; *resultDims = mBoneIndicesDims ; break ;
1118+ case geom::Attrib::BONE_WEIGHT: *resultPtr = (const float *)mBoneWeights .data (); *resultStrideBytes = 0 ; *resultDims = mBoneWeightsDims ; break ;
10481119 default :
10491120 *resultPtr = nullptr ; *resultStrideBytes = 0 ; *resultDims = 0 ;
10501121 }
10511122}
10521123
1053- void TriMesh::copyAttrib ( geom::Attrib attr, uint8_t dims, size_t /* stride */ , const float *srcData, size_t numVertices )
1124+ void TriMesh::copyAttrib ( geom::Attrib attr, uint8_t dims, size_t strideBytes , const float *srcData, size_t numVertices )
10541125{
10551126 if ( getAttribDims ( attr ) == 0 )
10561127 return ;
10571128
10581129 switch ( attr ) {
10591130 case geom::Attrib::POSITION:
10601131 mPositions .resize ( mPositionsDims * numVertices );
1061- geom::copyData ( dims, srcData, numVertices, mPositionsDims , 0 , mPositions .data () );
1132+ geom::copyData ( dims, strideBytes, srcData, numVertices, mPositionsDims , 0 , mPositions .data () );
10621133 break ;
10631134 case geom::Attrib::COLOR:
10641135 mColors .resize ( mColorsDims * numVertices );
1065- geom::copyData ( dims, srcData, numVertices, mColorsDims , 0 , mColors .data () );
1136+ geom::copyData ( dims, strideBytes, srcData, numVertices, mColorsDims , 0 , mColors .data () );
10661137 break ;
10671138 case geom::Attrib::TEX_COORD_0:
10681139 mTexCoords0 .resize ( mTexCoords0Dims * numVertices );
1069- geom::copyData ( dims, srcData, numVertices, mTexCoords0Dims , 0 , mTexCoords0 .data () );
1140+ geom::copyData ( dims, strideBytes, srcData, numVertices, mTexCoords0Dims , 0 , mTexCoords0 .data () );
10701141 break ;
10711142 case geom::Attrib::TEX_COORD_1:
10721143 mTexCoords1 .resize ( mTexCoords1Dims * numVertices );
1073- geom::copyData ( dims, srcData, numVertices, mTexCoords1Dims , 0 , mTexCoords1 .data () );
1144+ geom::copyData ( dims, strideBytes, srcData, numVertices, mTexCoords1Dims , 0 , mTexCoords1 .data () );
10741145 break ;
10751146 case geom::Attrib::TEX_COORD_2:
10761147 mTexCoords2 .resize ( mTexCoords2Dims * numVertices );
1077- geom::copyData ( dims, srcData, numVertices, mTexCoords2Dims , 0 , mTexCoords2 .data () );
1148+ geom::copyData ( dims, strideBytes, srcData, numVertices, mTexCoords2Dims , 0 , mTexCoords2 .data () );
10781149 break ;
10791150 case geom::Attrib::TEX_COORD_3:
10801151 mTexCoords3 .resize ( mTexCoords3Dims * numVertices );
1081- geom::copyData ( dims, srcData, numVertices, mTexCoords3Dims , 0 , mTexCoords3 .data () );
1152+ geom::copyData ( dims, strideBytes, srcData, numVertices, mTexCoords3Dims , 0 , mTexCoords3 .data () );
10821153 break ;
10831154 case geom::Attrib::NORMAL:
10841155 mNormals .resize ( numVertices );
1085- geom::copyData ( dims, srcData, numVertices, 3 , 0 , (float *)mNormals .data () );
1156+ geom::copyData ( dims, strideBytes, srcData, numVertices, 3 , 0 , (float *)mNormals .data () );
10861157 break ;
10871158 case geom::Attrib::TANGENT:
10881159 mTangents .resize ( numVertices );
1089- geom::copyData ( dims, srcData, numVertices, 3 , 0 , (float *)mTangents .data () );
1160+ geom::copyData ( dims, strideBytes, srcData, numVertices, 3 , 0 , (float *)mTangents .data () );
10901161 break ;
10911162 case geom::Attrib::BITANGENT:
10921163 mBitangents .resize ( numVertices );
1093- geom::copyData ( dims, srcData, numVertices, 3 , 0 , (float *)mBitangents .data () );
1164+ geom::copyData ( dims, strideBytes, srcData, numVertices, 3 , 0 , (float *)mBitangents .data () );
1165+ break ;
1166+ case geom::Attrib::BONE_INDEX:
1167+ mBoneIndices .resize ( numVertices );
1168+ geom::copyData ( dims, strideBytes, srcData, numVertices, 4 , 0 , (float *)mBoneIndices .data () );
1169+ break ;
1170+ case geom::Attrib::BONE_WEIGHT:
1171+ mBoneWeights .resize ( numVertices );
1172+ geom::copyData ( dims, strideBytes, srcData, numVertices, 4 , 0 , (float *)mBoneWeights .data () );
10941173 break ;
10951174 default :
10961175 throw geom::ExcMissingAttrib ();
@@ -1233,7 +1312,19 @@ bool TriMesh::verticesEqual( uint32_t indexA, uint32_t indexB ) const
12331312 return false ;
12341313 }
12351314
1236- // TODO: bone index and weight
1315+ if ( mBoneIndicesDims > 0 ) {
1316+ const vec4 &a = *reinterpret_cast <const vec4*>(&mBoneIndices [indexA*mBoneIndicesDims ]);
1317+ const vec4 &b = *reinterpret_cast <const vec4*>(&mBoneIndices [indexB*mBoneIndicesDims ]);
1318+ if ( distance2 ( a, b ) > FLT_EPSILON )
1319+ return false ;
1320+ }
1321+
1322+ if ( mBoneWeightsDims > 0 ) {
1323+ const vec4 &a = *reinterpret_cast <const vec4*>(&mBoneWeights [indexA*mBoneWeightsDims ]);
1324+ const vec4 &b = *reinterpret_cast <const vec4*>(&mBoneWeights [indexB*mBoneWeightsDims ]);
1325+ if ( distance2 ( a, b ) > FLT_EPSILON )
1326+ return false ;
1327+ }
12371328
12381329 return true ;
12391330}
0 commit comments