Export Collision mesh
This commit is contained in:
@@ -5,7 +5,7 @@ Export::Export()
|
||||
|
||||
}
|
||||
|
||||
bool Export::Meshes(std::string pathName, bool selectedOnly)
|
||||
bool Export::Meshes(std::string pathName, bool selectedOnly, bool isCollision)
|
||||
{
|
||||
MStatus status;
|
||||
if (pathName.empty()) {
|
||||
@@ -92,8 +92,14 @@ bool Export::Meshes(std::string pathName, bool selectedOnly)
|
||||
Objects.append(node);
|
||||
}
|
||||
}
|
||||
GetMeshData(Objects);
|
||||
WriteMeshData(pathName);
|
||||
GetMeshData(Objects, isCollision);
|
||||
|
||||
if (!isCollision) {
|
||||
WriteMeshData(pathName);
|
||||
} else {
|
||||
WriteCollisionData(pathName);
|
||||
}
|
||||
|
||||
MGlobal::displayInfo(MString() + "Enabling IKSolvers");
|
||||
status = MGlobal::executeCommand("doEnableNodeItems true all;");
|
||||
if (status != MS::kSuccess) {
|
||||
@@ -144,9 +150,9 @@ bool Export::Animations(std::string pathName, std::vector<AnimationInfo> animInf
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetMeshData(MObjectArray object)
|
||||
bool Export::GetMeshData(MObjectArray object, bool collision)
|
||||
{
|
||||
meshes = m_MeshHandler.GetMeshData(object);
|
||||
meshes = m_MeshHandler.GetMeshData(object, collision);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,6 +191,17 @@ void Export::WriteMeshData(std::string pathName)
|
||||
m_MeshFile.CloseFiles();
|
||||
}
|
||||
|
||||
void Export::WriteCollisionData(std::string pathName) {
|
||||
m_ColliFile.ASCIIFilePath(pathName + "_colli.txt");
|
||||
m_ColliFile.binaryFilePath(pathName + ".colli");
|
||||
|
||||
m_ColliFile.OpenFiles();
|
||||
|
||||
m_ColliFile.writeToFiles((OutputData*)&meshes);
|
||||
|
||||
m_ColliFile.CloseFiles();
|
||||
}
|
||||
|
||||
void Export::WriteAnimData(std::string pathName)
|
||||
{
|
||||
if (allBindPoses.size() > 0) {
|
||||
|
||||
@@ -22,18 +22,19 @@ public:
|
||||
int End;
|
||||
};
|
||||
|
||||
bool Meshes(std::string pathName, bool selectedOnly = false);
|
||||
bool Meshes(std::string pathName, bool selectedOnly = false, bool isCollision = false);
|
||||
bool Materials(std::string pathName);
|
||||
bool Animations(std::string pathName, std::vector<AnimationInfo> animInfo);
|
||||
|
||||
private:
|
||||
bool GetMeshData(MObjectArray object);
|
||||
bool GetMeshData(MObjectArray object, bool collision);
|
||||
bool GetMaterialData();
|
||||
bool GetAnimationData(AnimationInfo info);
|
||||
|
||||
void WriteMeshData(std::string pathName);
|
||||
void WriteAnimData(std::string pathName);
|
||||
void WriteMaterialData(std::string pathName);
|
||||
void WriteCollisionData(std::string pathName);
|
||||
|
||||
Material m_MaterialHandler;
|
||||
Skeleton m_SkeletonHandler;
|
||||
@@ -44,6 +45,7 @@ private:
|
||||
WriteToFile m_MeshFile;
|
||||
WriteToFile m_AnimFile;
|
||||
WriteToFile m_MtrlFile;
|
||||
WriteToFile m_ColliFile;
|
||||
|
||||
//Mesh Data
|
||||
Mesh meshes;
|
||||
|
||||
@@ -25,6 +25,7 @@ Menu::Menu(QDialog* dialog)
|
||||
m_ExportSelectedButton = new QCheckBox(tr("&Export Selected"));
|
||||
m_ExportAnimationsButton = new QCheckBox(tr("&Export Animations"));
|
||||
m_ExportMaterialButton = new QCheckBox(tr("&Export Material"));;
|
||||
m_IsCollision = new QCheckBox(tr("&Export as collision mesh"));
|
||||
|
||||
m_ExportAnimationsButton->setChecked(true);
|
||||
m_ExportMaterialButton->setChecked(true);
|
||||
@@ -32,6 +33,7 @@ Menu::Menu(QDialog* dialog)
|
||||
vbox->addWidget(m_ExportSelectedButton);
|
||||
vbox->addWidget(m_ExportAnimationsButton);
|
||||
vbox->addWidget(m_ExportMaterialButton);
|
||||
vbox->addWidget(m_IsCollision);
|
||||
|
||||
vbox->addStretch(1);
|
||||
optionsBox->setLayout(vbox);
|
||||
@@ -46,6 +48,7 @@ Menu::Menu(QDialog* dialog)
|
||||
connect(m_ExportSelectedButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_ExportAnimationsButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_ExportMaterialButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_IsCollision, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
|
||||
// Creating several layouts, adding widgets & adding them to one layout in the end
|
||||
QHBoxLayout* topLayout = new QHBoxLayout;
|
||||
@@ -163,40 +166,42 @@ void Menu::RemoveClipClicked(bool)
|
||||
|
||||
void Menu::ExportAll(bool)
|
||||
{
|
||||
if (m_ExportPath->text().isEmpty()) {
|
||||
MGlobal::displayError(MString() + "Please select a folder.");
|
||||
return;
|
||||
}
|
||||
if (m_ExportPath->text().isEmpty()) {
|
||||
MGlobal::displayError(MString() + "Please select a folder.");
|
||||
return;
|
||||
}
|
||||
|
||||
//Export meshes
|
||||
if (!m_Export.Meshes(m_ExportPath->text().toLocal8Bit().constData(), m_ExportSelectedButton->isChecked())) {
|
||||
MGlobal::displayError(MString() + "Could not export mesh");
|
||||
return;
|
||||
}
|
||||
//Export meshes
|
||||
if (!m_Export.Meshes(m_ExportPath->text().toLocal8Bit().constData(), m_ExportSelectedButton->isChecked(), m_IsCollision->isChecked())) {
|
||||
MGlobal::displayError(MString() + "Could not export mesh");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ExportMaterialButton->isChecked()) {
|
||||
if (!m_Export.Materials(m_ExportPath->text().toLocal8Bit().constData())) {
|
||||
MGlobal::displayError(MString() + "Could not export materials");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!m_IsCollision->isChecked()){
|
||||
if (m_ExportMaterialButton->isChecked()) {
|
||||
if (!m_Export.Materials(m_ExportPath->text().toLocal8Bit().constData())) {
|
||||
MGlobal::displayError(MString() + "Could not export materials");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Export::AnimationInfo> animations;
|
||||
for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) {
|
||||
Export::AnimationInfo thisClip;
|
||||
thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData());
|
||||
thisClip.Start = m_StartFrameLines[i]->text().toInt();
|
||||
thisClip.End = m_EndFrameLines[i]->text().toInt();
|
||||
std::vector<Export::AnimationInfo> animations;
|
||||
for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) {
|
||||
Export::AnimationInfo thisClip;
|
||||
thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData());
|
||||
thisClip.Start = m_StartFrameLines[i]->text().toInt();
|
||||
thisClip.End = m_EndFrameLines[i]->text().toInt();
|
||||
|
||||
animations.push_back(thisClip);
|
||||
}
|
||||
if (m_ExportAnimationsButton->isChecked()) {
|
||||
//Export Animations
|
||||
if (!m_Export.Animations(m_ExportPath->text().toLocal8Bit().constData(), animations)) {
|
||||
MGlobal::displayError(MString() + "Could not export animations");
|
||||
return;
|
||||
}
|
||||
}
|
||||
animations.push_back(thisClip);
|
||||
}
|
||||
if (m_ExportAnimationsButton->isChecked()) {
|
||||
//Export Animations
|
||||
if (!m_Export.Animations(m_ExportPath->text().toLocal8Bit().constData(), animations)) {
|
||||
MGlobal::displayError(MString() + "Could not export animations");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::CancelClicked(bool)
|
||||
|
||||
@@ -66,6 +66,7 @@ private:
|
||||
QCheckBox* m_ExportSelectedButton = nullptr;
|
||||
QCheckBox* m_ExportAnimationsButton = nullptr;
|
||||
QCheckBox* m_ExportMaterialButton = nullptr;
|
||||
QCheckBox* m_IsCollision = nullptr;
|
||||
|
||||
QLineEdit* m_ExportPath = nullptr;
|
||||
QFileDialog* m_FileDialog = nullptr;
|
||||
|
||||
@@ -94,33 +94,37 @@ MeshClass::MeshClass()
|
||||
// return weightMap;
|
||||
//}
|
||||
|
||||
Mesh MeshClass::GetMeshData(MObjectArray object)
|
||||
Mesh MeshClass::GetMeshData(MObjectArray object, bool collision)
|
||||
{
|
||||
MS status;
|
||||
Mesh newMesh;
|
||||
newMesh.isCollison = collision;
|
||||
vector<VertexLayout>& vertexList = newMesh.Vertices;
|
||||
map<string, vector<int>>& indexLists = newMesh.Indices;
|
||||
for (int ObjectID = 0; ObjectID < object.length(); ObjectID++) {
|
||||
if (!object[ObjectID].hasFn(MFn::kMesh))
|
||||
continue;
|
||||
|
||||
|
||||
MObject node = object[ObjectID];
|
||||
MFnDependencyNode thisNode(node);
|
||||
MPlugArray connections;
|
||||
thisNode.findPlug("inMesh").connectedTo(connections, true, true);
|
||||
MPlug weightList, weights;
|
||||
MObject weightListObject;
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
MFnSkinCluster skinCluster(connections[i].node());
|
||||
weightList = skinCluster.findPlug("weightList", &status);
|
||||
weightListObject = weightList.attribute();
|
||||
weights = skinCluster.findPlug("weights");
|
||||
newMesh.hasSkin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!collision) {
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
MFnSkinCluster skinCluster(connections[i].node());
|
||||
weightList = skinCluster.findPlug("weightList", &status);
|
||||
weightListObject = weightList.attribute();
|
||||
weights = skinCluster.findPlug("weights");
|
||||
newMesh.hasSkin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In here, we retrieve triangulated polygons from the mesh
|
||||
MFnMesh mesh(object[ObjectID]);
|
||||
@@ -257,62 +261,62 @@ Mesh MeshClass::GetMeshData(MObjectArray object)
|
||||
thisVertex.Pos[0] = pos.x;
|
||||
thisVertex.Pos[1] = pos.y;
|
||||
thisVertex.Pos[2] = pos.z;
|
||||
thisVertex.isCollision = collision;
|
||||
|
||||
status = faceVert.getNormal(normal, MSpace::kObject);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
if (!collision) {
|
||||
status = faceVert.getNormal(normal, MSpace::kObject);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
thisVertex.Normal[0] = normal[0];
|
||||
thisVertex.Normal[1] = normal[1];
|
||||
thisVertex.Normal[2] = normal[2];
|
||||
thisVertex.Normal[0] = normal[0];
|
||||
thisVertex.Normal[1] = normal[1];
|
||||
thisVertex.Normal[2] = normal[2];
|
||||
|
||||
MFloatVector Tangent = Tangents[faceVert.tangentId()];
|
||||
//MVector tmp = faceVert.getTangent(MSpace::kObject, NULL);
|
||||
//tmp.get(biTangent);
|
||||
thisVertex.Tangent[0] = Tangent[0];
|
||||
thisVertex.Tangent[1] = Tangent[1];
|
||||
thisVertex.Tangent[2] = Tangent[2];
|
||||
MFloatVector Tangent = Tangents[faceVert.tangentId()];
|
||||
//MVector tmp = faceVert.getTangent(MSpace::kObject, NULL);
|
||||
//tmp.get(biTangent);
|
||||
thisVertex.Tangent[0] = Tangent[0];
|
||||
thisVertex.Tangent[1] = Tangent[1];
|
||||
thisVertex.Tangent[2] = Tangent[2];
|
||||
|
||||
MFloatVector biNormal = biNormals[faceVert.tangentId()];
|
||||
//faceVert.getBinormal().get(biNormal);
|
||||
thisVertex.BiNormal[0] = biNormal[0];
|
||||
thisVertex.BiNormal[1] = biNormal[1];
|
||||
thisVertex.BiNormal[2] = biNormal[2];
|
||||
MFloatVector biNormal = biNormals[faceVert.tangentId()];
|
||||
//faceVert.getBinormal().get(biNormal);
|
||||
thisVertex.BiNormal[0] = biNormal[0];
|
||||
thisVertex.BiNormal[1] = biNormal[1];
|
||||
thisVertex.BiNormal[2] = biNormal[2];
|
||||
|
||||
status = faceVert.getUV(UV);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " faceVert.getUV() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
thisVertex.Uv[0] = UV[0];
|
||||
thisVertex.Uv[1] = UV[1];
|
||||
status = faceVert.getUV(UV);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " faceVert.getUV() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
thisVertex.Uv[0] = UV[0];
|
||||
thisVertex.Uv[1] = UV[1];
|
||||
|
||||
|
||||
if (newMesh.hasSkin) {
|
||||
thisVertex.useWeights = true;
|
||||
float totalWeight = 0.0f;
|
||||
unsigned int totalBones = 0;
|
||||
MIntArray jointIDs /* ??? */;
|
||||
weights.selectAncestorLogicalIndex(vertexIndex, weightListObject);
|
||||
weights.getExistingArrayAttributeIndices(jointIDs);
|
||||
for (unsigned int i = 0; i < jointIDs.length() && i < 4; i++) {
|
||||
if (weights[i].asFloat() > 0.001f) {
|
||||
thisVertex.BoneIndices[totalBones] = jointIDs[i];
|
||||
thisVertex.BoneWeights[totalBones] = weights[i].asFloat();
|
||||
totalWeight = totalWeight + weights[i].asFloat();
|
||||
totalBones++;
|
||||
}
|
||||
}
|
||||
if (newMesh.hasSkin) {
|
||||
thisVertex.useWeights = true;
|
||||
float totalWeight = 0.0f;
|
||||
unsigned int totalBones = 0;
|
||||
MIntArray jointIDs /* ??? */;
|
||||
weights.selectAncestorLogicalIndex(vertexIndex, weightListObject);
|
||||
weights.getExistingArrayAttributeIndices(jointIDs);
|
||||
for (unsigned int i = 0; i < jointIDs.length() && i < 4; i++) {
|
||||
if (weights[i].asFloat() > 0.001f) {
|
||||
thisVertex.BoneIndices[totalBones] = jointIDs[i];
|
||||
thisVertex.BoneWeights[totalBones] = weights[i].asFloat();
|
||||
totalWeight = totalWeight + weights[i].asFloat();
|
||||
totalBones++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
//thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight;
|
||||
}
|
||||
} else {
|
||||
thisVertex.useWeights = false;
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
//thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//float totalWeight = thisVertex.BoneWeights[0] + thisVertex.BoneWeights[1] + thisVertex.BoneWeights[2] + thisVertex.BoneWeights[3];
|
||||
//if (totalWeight > 0.0001f) {
|
||||
// thisVertex.BoneWeights[0] /= totalWeight;
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
class VertexLayout : public OutputData
|
||||
{
|
||||
public:
|
||||
bool useWeights = true;
|
||||
bool isCollision = false;
|
||||
bool useWeights = false;
|
||||
float Pos[3]{ 0 };
|
||||
float Normal[3]{ 0 };
|
||||
float Tangent[3]{ 0 };
|
||||
@@ -23,28 +24,31 @@ public:
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&Pos, sizeof(float) * 3);
|
||||
out.write((char*)&Normal, sizeof(float) * 3);
|
||||
out.write((char*)&Tangent, sizeof(float) * 3);
|
||||
out.write((char*)&BiNormal, sizeof(float) * 3);
|
||||
out.write((char*)&Uv, sizeof(float) * 2);
|
||||
if (useWeights) {
|
||||
out.write((char*)&BoneIndices, sizeof(float) * 4);
|
||||
out.write((char*)&BoneWeights, sizeof(float) * 4);
|
||||
if (!isCollision) {
|
||||
out.write((char*)&Normal, sizeof(float) * 3);
|
||||
out.write((char*)&Tangent, sizeof(float) * 3);
|
||||
out.write((char*)&BiNormal, sizeof(float) * 3);
|
||||
out.write((char*)&Uv, sizeof(float) * 2);
|
||||
if (useWeights) {
|
||||
out.write((char*)&BoneIndices, sizeof(float) * 4);
|
||||
out.write((char*)&BoneWeights, sizeof(float) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << Pos[0] << " " << Pos[1] << " " << Pos[2] << endl;
|
||||
out << Normal[0] << " " << Normal[1] << " " << Normal[2] << endl;
|
||||
out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl;
|
||||
out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl;
|
||||
out << Uv[0] << " " << Uv[1] << endl;
|
||||
if (useWeights) {
|
||||
out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl;
|
||||
out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl;
|
||||
if (!isCollision) {
|
||||
out << Normal[0] << " " << Normal[1] << " " << Normal[2] << endl;
|
||||
out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl;
|
||||
out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl;
|
||||
out << Uv[0] << " " << Uv[1] << endl;
|
||||
if (useWeights) {
|
||||
out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl;
|
||||
out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
bool operator==(const VertexLayout& right)
|
||||
{
|
||||
@@ -62,6 +66,7 @@ public:
|
||||
|
||||
class Mesh : public OutputData {
|
||||
public:
|
||||
bool isCollison = false;
|
||||
bool hasSkin = false;
|
||||
unsigned int NumVertices;
|
||||
unsigned int NumIndices;
|
||||
@@ -70,7 +75,9 @@ public:
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&hasSkin, sizeof(bool));
|
||||
if (!isCollison) {
|
||||
out.write((char*)&hasSkin, sizeof(bool));
|
||||
}
|
||||
out.write((char*)&NumVertices, sizeof(int));
|
||||
out.write((char*)&NumIndices, sizeof(int));
|
||||
for (auto aVertex : Vertices) {
|
||||
@@ -86,11 +93,13 @@ public:
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "New Mesh _ not in binary" << endl;
|
||||
out << "hasSkin: ";
|
||||
if(hasSkin)
|
||||
out << "true" << endl;
|
||||
else
|
||||
out << "false" << endl;
|
||||
if (!isCollison) {
|
||||
out << "hasSkin: ";
|
||||
if (hasSkin)
|
||||
out << "true" << endl;
|
||||
else
|
||||
out << "false" << endl;
|
||||
}
|
||||
out << "Number of vertices: " << NumVertices << endl;
|
||||
out << "number of indices: " << NumIndices << endl;
|
||||
int vertexNumber = 0;
|
||||
@@ -115,7 +124,7 @@ class MeshClass
|
||||
{
|
||||
public:
|
||||
MeshClass();
|
||||
Mesh GetMeshData(MObjectArray Object);
|
||||
Mesh GetMeshData(MObjectArray Object, bool collision = false);
|
||||
~MeshClass();
|
||||
private:
|
||||
struct WeightInfo {
|
||||
|
||||
Reference in New Issue
Block a user