Change gltf structures representing weights and jointIds to single data structure to make code cleaner and simplify further generalization. Added array versions of AttributeDefinition and AddAttributeToPrimitive to facilitate this.

This commit is contained in:
hhalen 2019-04-18 16:20:36 -07:00
parent 467e7b2171
commit c4395b9b92
7 changed files with 164 additions and 162 deletions

View File

@ -140,10 +140,11 @@ int main(int argc, char* argv[]) {
gltfOptions.useBlendShapeTangents, gltfOptions.useBlendShapeTangents,
"Include blend shape tangents, if reported present by the FBX SDK."); "Include blend shape tangents, if reported present by the FBX SDK.");
app.add_flag( app.add_option(
"--normalize-weights", "--normalize-weights",
gltfOptions.normalizeSkinningWeights, gltfOptions.normalizeSkinningWeights,
"Normalize skinning weights."); "Normalize skinning weights.",
true);
app.add_option( app.add_option(
"--skinning-weights", "--skinning-weights",
@ -156,8 +157,7 @@ int main(int argc, char* argv[]) {
"-k,--keep-attribute", "-k,--keep-attribute",
[&](std::vector<std::string> attributes) -> bool { [&](std::vector<std::string> attributes) -> bool {
gltfOptions.keepAttribs = gltfOptions.keepAttribs =
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0 | RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1 | RAW_VERTEX_ATTRIBUTE_JOINT_INDICES | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS;
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2 | RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3;
for (std::string attribute : attributes) { for (std::string attribute : attributes) {
if (attribute == "position") { if (attribute == "position") {
gltfOptions.keepAttribs |= RAW_VERTEX_ATTRIBUTE_POSITION; gltfOptions.keepAttribs |= RAW_VERTEX_ATTRIBUTE_POSITION;

View File

@ -123,6 +123,31 @@ class GltfModel {
return accessor; return accessor;
}; };
template <class T>
std::shared_ptr<AccessorData> AddAttributeArrayToPrimitive(
BufferData& buffer,
const RawModel& surfaceModel,
PrimitiveData& primitive,
const AttributeArrayDefinition<T>& attrDef) {
// copy attribute data into vector
std::vector<T> attribArr;
surfaceModel.GetArrayAttributeArray<T>(attribArr, attrDef.rawAttributeIx, attrDef.arrayOffset);
std::shared_ptr<AccessorData> accessor;
if (attrDef.dracoComponentType != draco::DT_INVALID && primitive.dracoMesh != nullptr) {
primitive.AddDracoArrayAttrib(attrDef, attribArr);
accessor = accessors.hold(new AccessorData(attrDef.glType));
accessor->count = attribArr.size();
}
else {
auto bufferView = GetAlignedBufferView(buffer, BufferViewData::GL_ARRAY_BUFFER);
accessor = AddAccessorWithView(*bufferView, attrDef.glType, attribArr, std::string(""));
}
primitive.AddAttrib(attrDef.gltfName, *accessor);
return accessor;
};
template <class T> template <class T>
void serializeHolder(json& glTFJson, std::string key, const Holder<T> holder) { void serializeHolder(json& glTFJson, std::string key, const Holder<T> holder) {
if (!holder.ptrs.empty()) { if (!holder.ptrs.empty()) {

View File

@ -532,77 +532,31 @@ ModelData* Raw2Gltf(
draco::DT_FLOAT32); draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec2f>(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_1); gltf->AddAttributeToPrimitive<Vec2f>(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_1);
} }
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0) != 0) { if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES) != 0) {
const AttributeDefinition<Vec4i> ATTR_JOINTS( for (int i = 0; i < surfaceModel.GetGlobalWeightCount(); i += 4) {
"JOINTS_0", const AttributeArrayDefinition<Vec4i> ATTR_JOINTS(
&RawVertex::jointIndices0, std::string("JOINTS_") + std::to_string(i/4),
//"JOINTS_0",
&RawVertex::jointIndices,
GLT_VEC4I, GLT_VEC4I,
draco::GeometryAttribute::GENERIC, draco::GeometryAttribute::GENERIC,
draco::DT_UINT16); draco::DT_UINT16,
gltf->AddAttributeToPrimitive<Vec4i>(buffer, surfaceModel, *primitive, ATTR_JOINTS); i/4);
gltf->AddAttributeArrayToPrimitive<Vec4i>(buffer, surfaceModel, *primitive, ATTR_JOINTS);
}
} }
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0) != 0) { if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS) != 0) {
const AttributeDefinition<Vec4f> ATTR_WEIGHTS( for (int i = 0; i < surfaceModel.GetGlobalWeightCount(); i += 4) {
"WEIGHTS_0", const AttributeArrayDefinition<Vec4f> ATTR_WEIGHTS(
&RawVertex::jointWeights0, std::string("WEIGHTS_") + std::to_string(i/4),
//"WEIGHTS_0",
&RawVertex::jointWeights,
GLT_VEC4F, GLT_VEC4F,
draco::GeometryAttribute::GENERIC, draco::GeometryAttribute::GENERIC,
draco::DT_FLOAT32); draco::DT_FLOAT32,
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_WEIGHTS); i/4);
} gltf->AddAttributeArrayToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_WEIGHTS);
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1) != 0) { }
const AttributeDefinition<Vec4i> ATTR_JOINTS(
"JOINTS_1",
&RawVertex::jointIndices1,
GLT_VEC4I,
draco::GeometryAttribute::GENERIC,
draco::DT_UINT16);
gltf->AddAttributeToPrimitive<Vec4i>(buffer, surfaceModel, *primitive, ATTR_JOINTS);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1) != 0) {
const AttributeDefinition<Vec4f> ATTR_WEIGHTS(
"WEIGHTS_1",
&RawVertex::jointWeights1,
GLT_VEC4F,
draco::GeometryAttribute::GENERIC,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_WEIGHTS);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2) != 0) {
const AttributeDefinition<Vec4i> ATTR_JOINTS(
"JOINTS_0",
&RawVertex::jointIndices2,
GLT_VEC4I,
draco::GeometryAttribute::GENERIC,
draco::DT_UINT16);
gltf->AddAttributeToPrimitive<Vec4i>(buffer, surfaceModel, *primitive, ATTR_JOINTS);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2) != 0) {
const AttributeDefinition<Vec4f> ATTR_WEIGHTS(
"WEIGHTS_0",
&RawVertex::jointWeights2,
GLT_VEC4F,
draco::GeometryAttribute::GENERIC,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_WEIGHTS);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3) != 0) {
const AttributeDefinition<Vec4i> ATTR_JOINTS(
"JOINTS_0",
&RawVertex::jointIndices3,
GLT_VEC4I,
draco::GeometryAttribute::GENERIC,
draco::DT_UINT16);
gltf->AddAttributeToPrimitive<Vec4i>(buffer, surfaceModel, *primitive, ATTR_JOINTS);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3) != 0) {
const AttributeDefinition<Vec4f> ATTR_WEIGHTS(
"WEIGHTS_0",
&RawVertex::jointWeights3,
GLT_VEC4F,
draco::GeometryAttribute::GENERIC,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_WEIGHTS);
} }
// each channel present in the mesh always ends up a target in the primitive // each channel present in the mesh always ends up a target in the primitive

View File

@ -154,6 +154,44 @@ struct AttributeDefinition {
glType(_glType), glType(_glType),
dracoAttribute(draco::GeometryAttribute::INVALID), dracoAttribute(draco::GeometryAttribute::INVALID),
dracoComponentType(draco::DataType::DT_INVALID) {} dracoComponentType(draco::DataType::DT_INVALID) {}
AttributeDefinition(
const std::string gltfName,
const T RawVertex::*rawAttributeIx,
const GLType& _glType,
const draco::GeometryAttribute::Type dracoAttribute,
const draco::DataType dracoComponentType,
const int arrayOffset)
: gltfName(gltfName),
rawAttributeIx(rawAttributeIx),
glType(_glType),
dracoAttribute(dracoAttribute),
dracoComponentType(dracoComponentType),
arrayOffset(arrayOffset){}
};
template <class T>
struct AttributeArrayDefinition {
const std::string gltfName;
const T (RawVertex::*rawAttributeIx)[(RawModel::MAX_SUPPORTED_WEIGHTS -1 ) / 4 + 1];
const GLType glType;
const int arrayOffset;
const draco::GeometryAttribute::Type dracoAttribute;
const draco::DataType dracoComponentType;
AttributeArrayDefinition(
const std::string gltfName,
const T (RawVertex::*rawAttributeIx)[(RawModel::MAX_SUPPORTED_WEIGHTS - 1) / 4 + 1],
const GLType& _glType,
const draco::GeometryAttribute::Type dracoAttribute,
const draco::DataType dracoComponentType,
const int arrayOffset)
: gltfName(gltfName),
rawAttributeIx(rawAttributeIx),
glType(_glType),
dracoAttribute(dracoAttribute),
dracoComponentType(dracoComponentType),
arrayOffset(arrayOffset) {}
}; };
struct AccessorData; struct AccessorData;

View File

@ -62,6 +62,32 @@ struct PrimitiveData {
dracoAttributes[attribute.gltfName] = dracoAttId; dracoAttributes[attribute.gltfName] = dracoAttId;
} }
template <class T>
void AddDracoArrayAttrib(const AttributeArrayDefinition<T> attribute, const std::vector<T>& attribArr) {
draco::PointAttribute att;
int8_t componentCount = attribute.glType.count;
att.Init(
attribute.dracoAttribute,
nullptr,
componentCount,
attribute.dracoComponentType,
false,
componentCount * draco::DataTypeLength(attribute.dracoComponentType),
0);
const int dracoAttId = dracoMesh->AddAttribute(att, true, attribArr.size());
draco::PointAttribute* attPtr = dracoMesh->attribute(dracoAttId);
std::vector<uint8_t> buf(sizeof(T));
for (uint32_t ii = 0; ii < attribArr.size(); ii++) {
uint8_t* ptr = &buf[0];
attribute.glType.write(ptr, attribArr[ii]);
attPtr->SetAttributeValue(attPtr->mapped_index(draco::PointIndex(ii)), ptr);
}
dracoAttributes[attribute.gltfName] = dracoAttId;
}
void NoteDracoBuffer(const BufferViewData& data); void NoteDracoBuffer(const BufferViewData& data);
const int indices; const int indices;

View File

@ -27,10 +27,7 @@ bool RawVertex::operator==(const RawVertex& other) const {
return (position == other.position) && (normal == other.normal) && (tangent == other.tangent) && return (position == other.position) && (normal == other.normal) && (tangent == other.tangent) &&
(binormal == other.binormal) && (color == other.color) && (uv0 == other.uv0) && (binormal == other.binormal) && (color == other.color) && (uv0 == other.uv0) &&
(uv1 == other.uv1) && (uv1 == other.uv1) &&
(jointWeights0 == other.jointWeights0) && (jointWeights1 == other.jointWeights1) && (jointWeights == other.jointWeights) && (jointIndices == other.jointIndices) &&
(jointWeights2 == other.jointWeights2) && (jointWeights3 == other.jointWeights3) &&
(jointIndices0 == other.jointIndices0) && (jointIndices1 == other.jointIndices1) &&
(jointIndices2 == other.jointIndices2) && (jointIndices3 == other.jointIndices3) &&
(polarityUv0 == other.polarityUv0) && (polarityUv0 == other.polarityUv0) &&
(blendSurfaceIx == other.blendSurfaceIx) && (blends == other.blends); (blendSurfaceIx == other.blendSurfaceIx) && (blends == other.blends);
} }
@ -59,17 +56,8 @@ size_t RawVertex::Difference(const RawVertex& other) const {
attributes |= RAW_VERTEX_ATTRIBUTE_UV1; attributes |= RAW_VERTEX_ATTRIBUTE_UV1;
} }
// Always need both or neither. // Always need both or neither.
if (jointIndices0 != other.jointIndices0 || jointWeights0 != other.jointWeights0) { if (jointIndices != other.jointIndices || jointWeights != other.jointWeights) {
attributes |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0; attributes |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS;
}
if (jointIndices1 != other.jointIndices1 || jointWeights1 != other.jointWeights1) {
attributes |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1;
}
if (jointIndices2 != other.jointIndices2 || jointWeights2 != other.jointWeights2) {
attributes |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2;
}
if (jointIndices3 != other.jointIndices3 || jointWeights3 != other.jointWeights3) {
attributes |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3;
} }
return attributes; return attributes;
} }
@ -409,7 +397,7 @@ void RawModel::Condense(const int maxSkinningWeights, const bool normalizeWeight
} }
{ {
int globalMaxWeights = 0; globalMaxWeights = 0;
for (auto& vertex: vertices) { for (auto& vertex: vertices) {
// Sort from largest to smallest weight. // Sort from largest to smallest weight.
@ -432,26 +420,15 @@ void RawModel::Condense(const int maxSkinningWeights, const bool normalizeWeight
} }
if (globalMaxWeights > 0) { if (globalMaxWeights > 0) {
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0); AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_INDICES);
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0); AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS);
}
if (globalMaxWeights > 1) {
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1);
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1);
}
if (globalMaxWeights > 2) {
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2);
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2);
}
if (globalMaxWeights > 3) {
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3);
AddVertexAttribute(RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3);
} }
assert(globalMaxWeights <= RawModel::MAX_SUPPORTED_WEIGHTS); assert(globalMaxWeights <= RawModel::MAX_SUPPORTED_WEIGHTS);
// Copy to gltf friendly structure // Copy to gltf friendly structure
for (auto& vertex : vertices) { for (auto& vertex : vertices) {
for (int i = 0; i < globalMaxWeights; i += 4) { // Ensure all vertices have the same number of streams for (int i = 0; i < globalMaxWeights; i += 4) {
Vec4f weights{0.0}; Vec4f weights{0.0};
Vec4i jointIds{0,0,0,0}; Vec4i jointIds{0,0,0,0};
for (int j = i; j < i + 4 && j < vertex.skinningInfo.size(); j++) { for (int j = i; j < i + 4 && j < vertex.skinningInfo.size(); j++) {
@ -459,26 +436,8 @@ void RawModel::Condense(const int maxSkinningWeights, const bool normalizeWeight
jointIds[j - i] = vertex.skinningInfo[j].jointIndex; jointIds[j - i] = vertex.skinningInfo[j].jointIndex;
} }
const int vertexStream = i / 4; const int vertexStream = i / 4;
switch (vertexStream) { vertex.jointIndices[vertexStream] = jointIds;
case 0: vertex.jointWeights[vertexStream] = weights;
vertex.jointIndices0 = jointIds;
vertex.jointWeights0 = weights;
break;
case 1:
vertex.jointIndices1 = jointIds;
vertex.jointWeights1 = weights;
break;
case 2:
vertex.jointIndices2 = jointIds;
vertex.jointWeights2 = weights;
break;
case 3:
vertex.jointIndices3 = jointIds;
vertex.jointWeights3 = weights;
break;
default:
assert(0);
}
} }
} }
} }
@ -631,6 +590,7 @@ void RawModel::CreateMaterialModels(
surfaces[sortedTriangles[i - 1].surfaceIndex].discrete))) { surfaces[sortedTriangles[i - 1].surfaceIndex].discrete))) {
materialModels.resize(materialModels.size() + 1); materialModels.resize(materialModels.size() + 1);
model = &materialModels[materialModels.size() - 1]; model = &materialModels[materialModels.size() - 1];
model->globalMaxWeights = globalMaxWeights;
} }
// FIXME: will have to unlink from the nodes, transform both surfaces into a // FIXME: will have to unlink from the nodes, transform both surfaces into a
@ -658,8 +618,7 @@ void RawModel::CreateMaterialModels(
if (keepAttribs != -1) { if (keepAttribs != -1) {
int keep = keepAttribs; int keep = keepAttribs;
if ((keepAttribs & RAW_VERTEX_ATTRIBUTE_POSITION) != 0) { if ((keepAttribs & RAW_VERTEX_ATTRIBUTE_POSITION) != 0) {
keep |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0 | RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1 | keep |= RAW_VERTEX_ATTRIBUTE_JOINT_INDICES | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS;
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2 | RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3 | RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3;
} }
if ((keepAttribs & RAW_VERTEX_ATTRIBUTE_AUTO) != 0) { if ((keepAttribs & RAW_VERTEX_ATTRIBUTE_AUTO) != 0) {
keep |= RAW_VERTEX_ATTRIBUTE_POSITION; keep |= RAW_VERTEX_ATTRIBUTE_POSITION;
@ -700,29 +659,13 @@ void RawModel::CreateMaterialModels(
if ((keep & RAW_VERTEX_ATTRIBUTE_UV1) == 0) { if ((keep & RAW_VERTEX_ATTRIBUTE_UV1) == 0) {
vertex.uv1 = defaultVertex.uv1; vertex.uv1 = defaultVertex.uv1;
} }
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0) == 0) { if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES) == 0) {
vertex.jointIndices0 = defaultVertex.jointIndices0; for (int i = 0; i < RawModel::MAX_SUPPORTED_WEIGHTS ; i++)
vertex.jointIndices[i] = defaultVertex.jointIndices[i];
} }
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0) == 0) { if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS) == 0) {
vertex.jointWeights0 = defaultVertex.jointWeights0; for (int i = 0; i < RawModel::MAX_SUPPORTED_WEIGHTS; i++)
} vertex.jointWeights[i] = defaultVertex.jointWeights[i];
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1) == 0) {
vertex.jointIndices1 = defaultVertex.jointIndices1;
}
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1) == 0) {
vertex.jointWeights1 = defaultVertex.jointWeights1;
}
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2) == 0) {
vertex.jointIndices2 = defaultVertex.jointIndices2;
}
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2) == 0) {
vertex.jointWeights2 = defaultVertex.jointWeights2;
}
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3) == 0) {
vertex.jointIndices3 = defaultVertex.jointIndices3;
}
if ((keep & RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3) == 0) {
vertex.jointWeights3 = defaultVertex.jointWeights3;
} }
} }

View File

@ -15,6 +15,8 @@
#include "FBX2glTF.h" #include "FBX2glTF.h"
#define MAX_SKINNING_WEIGHTS 32
enum RawVertexAttribute { enum RawVertexAttribute {
RAW_VERTEX_ATTRIBUTE_POSITION = 1 << 0, RAW_VERTEX_ATTRIBUTE_POSITION = 1 << 0,
RAW_VERTEX_ATTRIBUTE_NORMAL = 1 << 1, RAW_VERTEX_ATTRIBUTE_NORMAL = 1 << 1,
@ -23,14 +25,8 @@ enum RawVertexAttribute {
RAW_VERTEX_ATTRIBUTE_COLOR = 1 << 4, RAW_VERTEX_ATTRIBUTE_COLOR = 1 << 4,
RAW_VERTEX_ATTRIBUTE_UV0 = 1 << 5, RAW_VERTEX_ATTRIBUTE_UV0 = 1 << 5,
RAW_VERTEX_ATTRIBUTE_UV1 = 1 << 6, RAW_VERTEX_ATTRIBUTE_UV1 = 1 << 6,
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES0 = 1 << 7, RAW_VERTEX_ATTRIBUTE_JOINT_INDICES = 1 << 7,
RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS0 = 1 << 8, RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS = 1 << 8,
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES1 = 1 << 9,
RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS1 = 1 << 10,
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES2 = 1 << 11,
RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS2 = 1 << 12,
RAW_VERTEX_ATTRIBUTE_JOINT_INDICES3 = 1 << 13,
RAW_VERTEX_ATTRIBUTE_JOINT_WEIGHTS3 = 1 << 14,
RAW_VERTEX_ATTRIBUTE_AUTO = 1 << 31 RAW_VERTEX_ATTRIBUTE_AUTO = 1 << 31
}; };
@ -65,14 +61,9 @@ struct RawVertex {
Vec4f color{0.0f}; Vec4f color{0.0f};
Vec2f uv0{0.0f}; Vec2f uv0{0.0f};
Vec2f uv1{0.0f}; Vec2f uv1{0.0f};
Vec4i jointIndices0{0,0,0,0}; Vec4i jointIndices[(MAX_SKINNING_WEIGHTS - 1) / 4 + 1];
Vec4i jointIndices1{0,0,0,0}; Vec4f jointWeights[(MAX_SKINNING_WEIGHTS - 1) / 4 + 1];
Vec4i jointIndices2{0,0,0,0};
Vec4i jointIndices3{0,0,0,0};
Vec4f jointWeights0{0.0f};
Vec4f jointWeights1{0.0f};
Vec4f jointWeights2{0.0f};
Vec4f jointWeights3{0.0f};
std::vector<RawVertexSkinningInfo> skinningInfo; std::vector<RawVertexSkinningInfo> skinningInfo;
// end of members that directly correspond to vertex attributes // end of members that directly correspond to vertex attributes
@ -381,7 +372,7 @@ struct RawNode {
class RawModel { class RawModel {
public: public:
static const int MAX_SUPPORTED_WEIGHTS = 16; static const int MAX_SUPPORTED_WEIGHTS = MAX_SKINNING_WEIGHTS;
RawModel(); RawModel();
@ -460,6 +451,11 @@ class RawModel {
int GetVertexCount() const { int GetVertexCount() const {
return (int)vertices.size(); return (int)vertices.size();
} }
int GetGlobalWeightCount() const{
return globalMaxWeights;
}
const RawVertex& GetVertex(const int index) const { const RawVertex& GetVertex(const int index) const {
return vertices[index]; return vertices[index];
} }
@ -542,6 +538,14 @@ class RawModel {
void GetAttributeArray(std::vector<_attrib_type_>& out, const _attrib_type_ RawVertex::*ptr) void GetAttributeArray(std::vector<_attrib_type_>& out, const _attrib_type_ RawVertex::*ptr)
const; const;
// Create individual attribute arrays, with the source as an array.
// Returns true if the vertices store the particular attribute.
template <typename _attrib_type_>
void GetArrayAttributeArray(std::vector<_attrib_type_>& out,
const _attrib_type_ (RawVertex::*ptr)[(RawModel::MAX_SUPPORTED_WEIGHTS - 1) / 4 + 1],
const int arrayOffset)
const;
// Create an array with a raw model for each material. // Create an array with a raw model for each material.
// Multiple surfaces with the same material will turn into a single model. // Multiple surfaces with the same material will turn into a single model.
// However, surfaces that are marked as 'discrete' will turn into separate models. // However, surfaces that are marked as 'discrete' will turn into separate models.
@ -556,6 +560,7 @@ class RawModel {
long rootNodeId; long rootNodeId;
int vertexAttributes; int vertexAttributes;
int globalMaxWeights;
std::unordered_map<RawVertex, int, VertexHasher> vertexHash; std::unordered_map<RawVertex, int, VertexHasher> vertexHash;
std::vector<RawVertex> vertices; std::vector<RawVertex> vertices;
std::vector<RawTriangle> triangles; std::vector<RawTriangle> triangles;
@ -577,3 +582,14 @@ void RawModel::GetAttributeArray(
out[i] = vertices[i].*ptr; out[i] = vertices[i].*ptr;
} }
} }
template <typename _attrib_type_>
void RawModel::GetArrayAttributeArray(
std::vector<_attrib_type_>& out,
const _attrib_type_ (RawVertex::*ptr)[(RawModel::MAX_SUPPORTED_WEIGHTS - 1) / 4 + 1],
const int arrayOffset) const {
out.resize(vertices.size());
for (size_t i = 0; i < vertices.size(); i++) {
out[i] = (vertices[i].*ptr)[arrayOffset];
}
}