Skip to content

Commit 107abad

Browse files
committed
Adding TriMesh methods for boneIndices and boneWeights, considering strideBytes
1 parent 9c84948 commit 107abad

File tree

2 files changed

+133
-14
lines changed

2 files changed

+133
-14
lines changed

include/cinder/TriMesh.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class CI_API TriMesh : public geom::Source {
4949
Format& normals() { mNormalsDims = 3; return *this; }
5050
Format& tangents() { mTangentsDims = 3; return *this; }
5151
Format& bitangents() { mBitangentsDims = 3; return *this; }
52+
Format& boneIndices() { mBoneIndicesDims = 4; return *this; }
53+
Format& boneWeights() { mBoneWeightsDims = 4; return *this; }
5254

5355
Format& colors( uint8_t dims = 3 ) { mColorsDims = dims; return *this; }
5456
//! Enables and establishes the dimensions of texture coords for unit 0
@@ -62,7 +64,7 @@ class CI_API TriMesh : public geom::Source {
6264
//! Enables and establishes the dimensions of texture coords for unit 3
6365
Format& texCoords3( uint8_t dims = 2 ) { mTexCoords3Dims = dims; return *this; }
6466

65-
uint8_t mPositionsDims, mNormalsDims, mTangentsDims, mBitangentsDims, mColorsDims;
67+
uint8_t mPositionsDims, mNormalsDims, mTangentsDims, mBitangentsDims, mBoneIndicesDims, mBoneWeightsDims, mColorsDims;
6668
uint8_t mTexCoords0Dims, mTexCoords1Dims, mTexCoords2Dims, mTexCoords3Dims;
6769
};
6870

@@ -86,6 +88,8 @@ class CI_API TriMesh : public geom::Source {
8688
bool hasNormals() const { return ! mNormals.empty(); }
8789
bool hasTangents() const { return ! mTangents.empty(); }
8890
bool hasBitangents() const { return ! mBitangents.empty(); }
91+
bool hasBoneIndices() const { return ! mBoneIndices.empty(); }
92+
bool hasBoneWeights() const { return ! mBoneWeights.empty(); }
8993
bool hasColors() const { return ! mColors.empty(); }
9094
bool hasColorsRgb() const { return mColorsDims == 3 && ! mColors.empty(); }
9195
bool hasColorsRgba() const { return mColorsDims == 4 && ! mColors.empty(); }
@@ -124,6 +128,16 @@ class CI_API TriMesh : public geom::Source {
124128
void appendBitangent( const vec3 &bitangent ) { mBitangents.push_back( bitangent ); }
125129
//! Functions similarly to appendPositions(), appending multiple bitangents at once.
126130
void appendBitangents( const vec3 *bitangents, size_t num );
131+
132+
//! Appends a single bone index
133+
void appendBoneIndex( const vec4 &boneIndex ) { mBoneIndices.push_back( boneIndex ); }
134+
//! Functions similarly to appendPositions(), appending multiple boneIndices at once.
135+
void appendBoneIndices( const vec4 *boneIndices, size_t num );
136+
//! Appends a single bone weight
137+
void appendBoneWeight( const vec4 &boneWeight ) { mBoneWeights.push_back( boneWeight ); }
138+
//! Functions similarly to appendPositions(), appending multiple bone weights at once.
139+
void appendBoneWeights( const vec4 *boneWeights, size_t num );
140+
127141
//! Appends a single RGB color
128142
void appendColorRgb( const Color &color ) { appendColors( &color, 1 ); }
129143
//! Appends a single RGBA color
@@ -213,6 +227,10 @@ class CI_API TriMesh : public geom::Source {
213227
void getTriangleTangents( size_t idx, vec3 *a, vec3 *b, vec3 *c ) const;
214228
//! Copies the 3 bitangents of triangle number \a idx into \a a, \a b and \a c.
215229
void getTriangleBitangents( size_t idx, vec3 *a, vec3 *b, vec3 *c ) const;
230+
//! Copies the 3 bone indices of triangle number \a idx into \a a, \a b and \a c.
231+
void getTriangleBoneIndices( size_t idx, vec4 *a, vec4 *b, vec4 *c ) const;
232+
//! Copies the 3 bone weights of triangle number \a idx into \a a, \a b and \a c.
233+
void getTriangleBoneWeights( size_t idx, vec4 *a, vec4 *b, vec4 *c ) const;
216234

217235

218236
//! Returns a pointer to the positions of the mesh as vec<DIM>*. For example, for a TriMesh with 3D vertices, call getPositions<3>().
@@ -233,6 +251,14 @@ class CI_API TriMesh : public geom::Source {
233251
std::vector<vec3>& getBitangents() { return mBitangents; }
234252
//! Returns a reference to the std::vector<vec3> for the TriMesh's bitangents.
235253
const std::vector<vec3>& getBitangents() const { return mBitangents; }
254+
//! Returns a reference to the std::vector<vec4> for the TriMesh's bone indices.
255+
std::vector<vec4>& getBoneIndices() { return mBoneIndices; }
256+
//! Returns a reference to the std::vector<vec4> for the TriMesh's bone indices.
257+
const std::vector<vec4>& getBoneIndices() const { return mBoneIndices; }
258+
//! Returns a reference to the std::vector<vec4> for the TriMesh's bone weights.
259+
std::vector<vec4>& getBoneWeights() { return mBoneWeights; }
260+
//! Returns a reference to the std::vector<vec4> for the TriMesh's bone weights.
261+
const std::vector<vec4>& getBoneWeight() const { return mBoneWeights; }
236262
//! Returns a pointer to the colors of the TriMesh vec<DIM>*. For example, to get RGB colors, call getColors<3>().
237263
template<uint8_t DIM>
238264
typename COLORDIM<DIM,float>::TYPE* getColors() { assert(mColorsDims==DIM); return (typename COLORDIM<DIM,float>::TYPE*)mColors.data(); }
@@ -354,14 +380,16 @@ class CI_API TriMesh : public geom::Source {
354380
//! Converts an attribute bitmask to a geom::Attrib.
355381
static geom::Attrib fromMask( uint32_t attrib );
356382

357-
uint8_t mPositionsDims, mNormalsDims, mTangentsDims, mBitangentsDims, mColorsDims;
383+
uint8_t mPositionsDims, mNormalsDims, mTangentsDims, mBitangentsDims, mBoneIndicesDims, mBoneWeightsDims, mColorsDims;
358384
uint8_t mTexCoords0Dims, mTexCoords1Dims, mTexCoords2Dims, mTexCoords3Dims;
359385

360386
std::vector<float> mPositions;
361387
std::vector<float> mColors;
362388
std::vector<vec3> mNormals; // always dim=3
363389
std::vector<vec3> mTangents; // always dim=3
364390
std::vector<vec3> mBitangents; // always dim=3
391+
std::vector<vec4> mBoneIndices; // always dim=4
392+
std::vector<vec4> mBoneWeights; // always dim=4
365393
std::vector<float> mTexCoords0, mTexCoords1, mTexCoords2, mTexCoords3;
366394
std::vector<uint32_t> mIndices;
367395

src/cinder/TriMesh.cpp

Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
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
8182
TriMesh::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+
260287
void 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+
393436
AxisAlignedBox 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
758821
void 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

Comments
 (0)