mirror of
https://github.com/ApfelTeeSaft/vb01.git
synced 2026-08-26 19:33:45 +00:00
beginning of XML model reader
This commit is contained in:
@@ -10,3 +10,6 @@
|
|||||||
[submodule "external/assimp"]
|
[submodule "external/assimp"]
|
||||||
path = external/assimp
|
path = external/assimp
|
||||||
url = https://github.com/assimp/assimp
|
url = https://github.com/assimp/assimp
|
||||||
|
[submodule "external/tinyxml2"]
|
||||||
|
path = external/tinyxml2
|
||||||
|
url = https://github.com/leethomason/tinyxml2
|
||||||
|
|||||||
+8
-2
@@ -17,7 +17,7 @@ set(MATH quaternion.cpp vector.cpp matrix.cpp ray.cpp)
|
|||||||
set(RENDER lineRenderer.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp)
|
set(RENDER lineRenderer.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp)
|
||||||
set(ANIM animationController.cpp animationChannel.cpp animation.cpp animatable.h keyframeChannel.cpp driver.cpp)
|
set(ANIM animationController.cpp animationChannel.cpp animation.cpp animatable.h keyframeChannel.cpp driver.cpp)
|
||||||
set(ARMATURE skeleton.cpp bone.cpp ikSolver.cpp)
|
set(ARMATURE skeleton.cpp bone.cpp ikSolver.cpp)
|
||||||
set(ASSET_READERS abstractAssetReader.cpp imageReader.cpp fontReader.cpp modelReader.cpp assimpModelReader.cpp vbModelReader.cpp)
|
set(ASSET_READERS abstractAssetReader.cpp imageReader.cpp fontReader.cpp modelReader.cpp assimpModelReader.cpp vbModelReader.cpp xmlModelReader.cpp)
|
||||||
set(ASSET_MANAGER assetManager.cpp textAsset.h imageAsset.h modelAsset.h fontAsset.h)
|
set(ASSET_MANAGER assetManager.cpp textAsset.h imageAsset.h modelAsset.h fontAsset.h)
|
||||||
set(LIB_SRC ${RENDER} ${MATH} ${UTILS} ${GUI} ${ARMATURE} ${ASSET_MANAGER} ${ASSET_READERS} ${ANIM})
|
set(LIB_SRC ${RENDER} ${MATH} ${UTILS} ${GUI} ${ARMATURE} ${ASSET_MANAGER} ${ASSET_READERS} ${ANIM})
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ include_directories(external/stb)
|
|||||||
|
|
||||||
add_library(${LIB_NAME} SHARED external/glad/glad.c ${LIB_SRC})
|
add_library(${LIB_NAME} SHARED external/glad/glad.c ${LIB_SRC})
|
||||||
|
|
||||||
|
set(TINYXML2_DIR external/tinyxml2)
|
||||||
set(GLFW_DIR external/glfw)
|
set(GLFW_DIR external/glfw)
|
||||||
set(FREETYPE_DIR external/freetype)
|
set(FREETYPE_DIR external/freetype)
|
||||||
set(ASSIMP_DIR external/assimp)
|
set(ASSIMP_DIR external/assimp)
|
||||||
@@ -39,6 +40,11 @@ elseif(WIN32)
|
|||||||
message("Building for Windows")
|
message("Building for Windows")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(${TINYXML2_DIR})
|
||||||
|
set(TINYXML2_LIB_DIR build/${TINYXML2_DIR})
|
||||||
|
target_include_directories(${LIB_NAME} PUBLIC ${TINYXML2_DIR})
|
||||||
|
target_link_directories(${LIB_NAME} PUBLIC ${TINYXML2_LIB_DIR})
|
||||||
|
|
||||||
add_subdirectory(${GLFW_DIR})
|
add_subdirectory(${GLFW_DIR})
|
||||||
set(GLFW_LIB_DIR build/${GLFW_DIR}/src)
|
set(GLFW_LIB_DIR build/${GLFW_DIR}/src)
|
||||||
target_include_directories(${LIB_NAME} PUBLIC ${GLFW_DIR}/include/GLFW)
|
target_include_directories(${LIB_NAME} PUBLIC ${GLFW_DIR}/include/GLFW)
|
||||||
@@ -54,7 +60,7 @@ add_subdirectory(${FREETYPE_DIR})
|
|||||||
target_include_directories(${LIB_NAME} PUBLIC ${FREETYPE_DIR}/include)
|
target_include_directories(${LIB_NAME} PUBLIC ${FREETYPE_DIR}/include)
|
||||||
target_link_directories(${LIB_NAME} PUBLIC ${FREETYPE_LIB_DIR})
|
target_link_directories(${LIB_NAME} PUBLIC ${FREETYPE_LIB_DIR})
|
||||||
|
|
||||||
set(DEPS glfw assimp freetype ${CMAKE_DL_LIBS})
|
set(DEPS glfw assimp freetype ${CMAKE_DL_LIBS} tinyxml2)
|
||||||
|
|
||||||
target_link_libraries(${LIB_NAME} ${DEPS})
|
target_link_libraries(${LIB_NAME} ${DEPS})
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ namespace vb01{
|
|||||||
void lookAt(Vector3, Vector3);
|
void lookAt(Vector3, Vector3);
|
||||||
Vector3 getBoneSpaceRestPos(Bone*);
|
Vector3 getBoneSpaceRestPos(Bone*);
|
||||||
Vector3 getModelSpacePos();
|
Vector3 getModelSpacePos();
|
||||||
inline Bone* getIkTarget(){return ikTarget;}
|
inline Skeleton* getSkeleton(){return skeleton;}
|
||||||
inline void setIkTarget(Bone *target){this->ikTarget = target;}
|
inline std::string getIkTarget(){return ikTarget;}
|
||||||
|
inline void setIkTarget(std::string target){this->ikTarget = target;}
|
||||||
inline int getIkChainLength(){return ikChainLength;}
|
inline int getIkChainLength(){return ikChainLength;}
|
||||||
inline void setIkChainLength(int ikChainLength){this->ikChainLength = ikChainLength;}
|
inline void setIkChainLength(int ikChainLength){this->ikChainLength = ikChainLength;}
|
||||||
inline float getLength(){return length;}
|
inline float getLength(){return length;}
|
||||||
@@ -39,7 +40,7 @@ namespace vb01{
|
|||||||
virtual float getDriverValue(Driver::VariableType);
|
virtual float getDriverValue(Driver::VariableType);
|
||||||
|
|
||||||
float length;
|
float length;
|
||||||
Bone *ikTarget = nullptr;
|
std::string ikTarget = "";
|
||||||
int ikChainLength = -1;
|
int ikChainLength = -1;
|
||||||
bool ikFromTail = true;
|
bool ikFromTail = true;
|
||||||
Skeleton *skeleton = nullptr;
|
Skeleton *skeleton = nullptr;
|
||||||
|
|||||||
+1
Submodule external/tinyxml2 added at a977397684
+3
-1
@@ -1,4 +1,5 @@
|
|||||||
#include "ikSolver.h"
|
#include "ikSolver.h"
|
||||||
|
#include "skeleton.h"
|
||||||
#include "bone.h"
|
#include "bone.h"
|
||||||
|
|
||||||
namespace vb01{
|
namespace vb01{
|
||||||
@@ -7,7 +8,8 @@ namespace vb01{
|
|||||||
for(int i = 0; i < chainLength; i++)
|
for(int i = 0; i < chainLength; i++)
|
||||||
sumLengths += boneChain[i]->getLength();
|
sumLengths += boneChain[i]->getLength();
|
||||||
|
|
||||||
Bone *subBase = (Bone*)boneChain[0]->getIkTarget()->getParent();
|
Skeleton *skeleton = boneChain[0]->getSkeleton();
|
||||||
|
Bone *subBase = (Bone*)skeleton->getBone(boneChain[0]->getIkTarget())->getParent();
|
||||||
Vector3 startPos = subBase->globalToLocalPosition(boneChain[chainLength - 1]->localToGlobalPosition(Vector3::VEC_ZERO));
|
Vector3 startPos = subBase->globalToLocalPosition(boneChain[chainLength - 1]->localToGlobalPosition(Vector3::VEC_ZERO));
|
||||||
if(startPos.getDistanceFrom(targetPos) < sumLengths){
|
if(startPos.getDistanceFrom(targetPos) < sumLengths){
|
||||||
int numIterations = 500;
|
int numIterations = 500;
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ namespace vb01{
|
|||||||
boneD->lookAt(Vector3::VEC_K, Vector3::VEC_J);
|
boneD->lookAt(Vector3::VEC_K, Vector3::VEC_J);
|
||||||
|
|
||||||
boneD->setIkChainLength(chainLength);
|
boneD->setIkChainLength(chainLength);
|
||||||
boneD->setIkTarget(ikBone);
|
boneD->setIkTarget(ikBone->getName());
|
||||||
|
|
||||||
ikPos = new Vector3[chainLength];
|
ikPos = new Vector3[chainLength];
|
||||||
boneChain = new Bone*[chainLength];
|
boneChain = new Bone*[chainLength];
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "skeleton.h"
|
#include "skeleton.h"
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
#include "vbModelReader.h"
|
#include "vbModelReader.h"
|
||||||
|
#include "xmlModelReader.h"
|
||||||
#include "assimpModelReader.h"
|
#include "assimpModelReader.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -25,7 +26,9 @@ namespace vb01{
|
|||||||
string extension = path.substr(dotId + 1, string::npos);
|
string extension = path.substr(dotId + 1, string::npos);
|
||||||
ModelReader *modelReader = nullptr;
|
ModelReader *modelReader = nullptr;
|
||||||
|
|
||||||
if(extension == "vb")
|
if(extension == "xml")
|
||||||
|
modelReader = new XmlModelReader(this, path);
|
||||||
|
else if(extension == "vb")
|
||||||
modelReader = new VbModelReader(this, path);
|
modelReader = new VbModelReader(this, path);
|
||||||
else
|
else
|
||||||
modelReader = new AssimpModelReader(this, path);
|
modelReader = new AssimpModelReader(this, path);
|
||||||
|
|||||||
@@ -118,6 +118,10 @@ namespace vb01{
|
|||||||
mesh->setNode(this);
|
mesh->setNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::addSkeleton(Skeleton *skeleton){
|
||||||
|
skeletons.push_back(skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
void Node::attachParticleEmitter(ParticleEmitter *emitter){
|
void Node::attachParticleEmitter(ParticleEmitter *emitter){
|
||||||
emitters.push_back(emitter);
|
emitters.push_back(emitter);
|
||||||
emitter->setNode(this);
|
emitter->setNode(this);
|
||||||
|
|||||||
@@ -16,11 +16,14 @@ namespace vb01{
|
|||||||
class Light;
|
class Light;
|
||||||
class ParticleEmitter;
|
class ParticleEmitter;
|
||||||
class Text;
|
class Text;
|
||||||
|
class Skeleton;
|
||||||
|
class AnimationController;
|
||||||
|
|
||||||
class Node : public Animatable{
|
class Node : public Animatable{
|
||||||
public:
|
public:
|
||||||
Node(Vector3 = Vector3::VEC_ZERO, Quaternion = Quaternion::QUAT_W, Vector3 = Vector3::VEC_IJK, std::string = "");
|
Node(Vector3 = Vector3::VEC_ZERO, Quaternion = Quaternion::QUAT_W, Vector3 = Vector3::VEC_IJK, std::string = "");
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
void addSkeleton(Skeleton*);
|
||||||
void attachMesh(Mesh*);
|
void attachMesh(Mesh*);
|
||||||
void attachParticleEmitter(ParticleEmitter*);
|
void attachParticleEmitter(ParticleEmitter*);
|
||||||
virtual void update();
|
virtual void update();
|
||||||
@@ -81,6 +84,7 @@ namespace vb01{
|
|||||||
std::vector<Node*> children;
|
std::vector<Node*> children;
|
||||||
std::vector<Light*> lights;
|
std::vector<Light*> lights;
|
||||||
std::vector<Text*> texts;
|
std::vector<Text*> texts;
|
||||||
|
std::vector<Skeleton*> skeletons;
|
||||||
std::string name;
|
std::string name;
|
||||||
Node *parent = nullptr;
|
Node *parent = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ rootTag = ET.Element('model')
|
|||||||
|
|
||||||
def exportBone(armature, parentBone, parentTag, exportChildren = True):
|
def exportBone(armature, parentBone, parentTag, exportChildren = True):
|
||||||
head = parentBone.head
|
head = parentBone.head
|
||||||
tail = parentBone.tail
|
|
||||||
xAxis = parentBone.x_axis
|
xAxis = parentBone.x_axis
|
||||||
yAxis = parentBone.y_axis
|
yAxis = parentBone.y_axis
|
||||||
ikTarget = None
|
ikTarget = None
|
||||||
@@ -16,9 +15,13 @@ def exportBone(armature, parentBone, parentTag, exportChildren = True):
|
|||||||
boneTag.set('hx', str(head.x))
|
boneTag.set('hx', str(head.x))
|
||||||
boneTag.set('hy', str(head.y))
|
boneTag.set('hy', str(head.y))
|
||||||
boneTag.set('hz', str(head.z))
|
boneTag.set('hz', str(head.z))
|
||||||
boneTag.set('tx', str(tail.x))
|
boneTag.set('length', str(parentBone.length))
|
||||||
boneTag.set('ty', str(tail.y))
|
boneTag.set('xaxisx', str(xAxis.x))
|
||||||
boneTag.set('tz', str(tail.z))
|
boneTag.set('xaxisy', str(xAxis.y))
|
||||||
|
boneTag.set('xaxisz', str(xAxis.z))
|
||||||
|
boneTag.set('yaxisx', str(yAxis.x))
|
||||||
|
boneTag.set('yaxisy', str(yAxis.y))
|
||||||
|
boneTag.set('yaxisz', str(yAxis.z))
|
||||||
|
|
||||||
ikConstraint = None
|
ikConstraint = None
|
||||||
|
|
||||||
@@ -153,6 +156,9 @@ def export(node, parentTag):
|
|||||||
numShapeKeys = len(mesh.shape_keys.key_blocks) - 1
|
numShapeKeys = len(mesh.shape_keys.key_blocks) - 1
|
||||||
|
|
||||||
meshTag = ET.SubElement(nodeTag, 'mesh')
|
meshTag = ET.SubElement(nodeTag, 'mesh')
|
||||||
|
meshTag.set('num_faces', str(numFaces))
|
||||||
|
meshTag.set('num_vertex_groups', str(numGroups))
|
||||||
|
meshTag.set('num_shape_keys', str(numShapeKeys))
|
||||||
|
|
||||||
for vert in mesh.vertices:
|
for vert in mesh.vertices:
|
||||||
pos = vert.co
|
pos = vert.co
|
||||||
|
|||||||
+3
-3
@@ -21,7 +21,7 @@ namespace vb01{
|
|||||||
|
|
||||||
void Skeleton::updateIk(){
|
void Skeleton::updateIk(){
|
||||||
for(Bone *b : bones){
|
for(Bone *b : bones){
|
||||||
if(b->getIkTarget()){
|
if(b->getIkTarget() != ""){
|
||||||
const int chainLength = b->getIkChainLength();
|
const int chainLength = b->getIkChainLength();
|
||||||
Bone **boneChain = getIkBoneChain(b);
|
Bone **boneChain = getIkBoneChain(b);
|
||||||
for(int i = 0; i < chainLength; i++){
|
for(int i = 0; i < chainLength; i++){
|
||||||
@@ -33,13 +33,13 @@ namespace vb01{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(Bone *b : bones)
|
for(Bone *b : bones)
|
||||||
if(b->getIkTarget())
|
if(getBone(b->getIkTarget()))
|
||||||
solveIk(b);
|
solveIk(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skeleton::solveIk(Bone *ikBone){
|
void Skeleton::solveIk(Bone *ikBone){
|
||||||
const int chainLength = ikBone->getIkChainLength();
|
const int chainLength = ikBone->getIkChainLength();
|
||||||
Bone *ikTarget = ikBone->getIkTarget();
|
Bone *ikTarget = getBone(ikBone->getIkTarget());
|
||||||
Bone *subBase = (Bone*)ikTarget->getParent();
|
Bone *subBase = (Bone*)ikTarget->getParent();
|
||||||
|
|
||||||
Bone **boneChain = getIkBoneChain(ikBone);
|
Bone **boneChain = getIkBoneChain(ikBone);
|
||||||
|
|||||||
+1
-1
@@ -225,7 +225,7 @@ namespace vb01{
|
|||||||
for(it = ikRelationships.begin(); it != ikRelationships.end(); it++){
|
for(it = ikRelationships.begin(); it != ikRelationships.end(); it++){
|
||||||
string targetBoneName = it->first;
|
string targetBoneName = it->first;
|
||||||
string ikTargetBoneName = ikRelationships[targetBoneName];
|
string ikTargetBoneName = ikRelationships[targetBoneName];
|
||||||
skeleton->getBone(targetBoneName)->setIkTarget(skeleton->getBone(ikTargetBoneName));
|
skeleton->getBone(targetBoneName)->setIkTarget(ikTargetBoneName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
#include "xmlModelReader.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "skeleton.h"
|
||||||
|
#include "bone.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace tinyxml2;
|
||||||
|
|
||||||
|
namespace vb01{
|
||||||
|
XmlModelReader::XmlModelReader(Model *model, string path) : ModelReader(model, path){
|
||||||
|
XMLDocument *doc = new XMLDocument();
|
||||||
|
doc->LoadFile(path.c_str());
|
||||||
|
|
||||||
|
XMLNode *root = doc->FirstChild();
|
||||||
|
model->attachChild(processNode(model, (XMLElement*)root));
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh* XmlModelReader::processMesh(XMLElement *meshEl){
|
||||||
|
vector<Vector3> vertPos, vertNorm;
|
||||||
|
vector<float> weights;
|
||||||
|
const char *tagName = "vertdata";
|
||||||
|
|
||||||
|
for(XMLElement *vertEl = meshEl->FirstChildElement(tagName); vertEl && strcmp(vertEl->Name(), tagName) == 0; vertEl = vertEl->NextSiblingElement()){
|
||||||
|
float posX = atof(vertEl->Attribute("px"));
|
||||||
|
float posY = atof(vertEl->Attribute("py"));
|
||||||
|
float posZ = atof(vertEl->Attribute("pz"));
|
||||||
|
vertPos.push_back(Vector3(posX, posY, posZ));
|
||||||
|
|
||||||
|
float normX = atof(vertEl->Attribute("nx"));
|
||||||
|
float normY = atof(vertEl->Attribute("ny"));
|
||||||
|
float normZ = atof(vertEl->Attribute("nz"));
|
||||||
|
vertNorm.push_back(Vector3(normX, normY, normZ));
|
||||||
|
|
||||||
|
for(XMLElement *weightEl = vertEl->FirstChildElement("weight"); weightEl; weightEl = weightEl->NextSiblingElement())
|
||||||
|
weights.push_back(atof(weightEl->Attribute("value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
int numVertexGroups = atoi(meshEl->Attribute("num_vertex_groups"));
|
||||||
|
string *vertexGroups = new string[numVertexGroups];
|
||||||
|
tagName = "vertexgroup";
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for(XMLElement *vertGroupEl = meshEl->FirstChildElement(tagName); vertGroupEl && strcmp(vertGroupEl->Name(), tagName) == 0; vertGroupEl = vertGroupEl->NextSiblingElement(), i++)
|
||||||
|
vertexGroups[i] = (vertGroupEl->Attribute("name"));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
int numVertices = 3 * atoi(meshEl->Attribute("num_faces"));
|
||||||
|
int numBones;
|
||||||
|
Mesh::Vertex *vertices = new Mesh::Vertex[numVertices];
|
||||||
|
tagName = "vert";
|
||||||
|
vector<u32> vertIds;
|
||||||
|
u32 *indices = new u32[numVertices];
|
||||||
|
|
||||||
|
for(XMLElement *vertEl = meshEl->FirstChildElement(tagName); vertEl && strcmp(vertEl->Name(), tagName) == 0; vertEl = vertEl->NextSiblingElement(), i++){
|
||||||
|
int id = atoi(vertEl->Attribute("id"));
|
||||||
|
vertIds.push_back(id);
|
||||||
|
|
||||||
|
float uvX = atof(vertEl->Attribute("uvx"));
|
||||||
|
float uvY = atof(vertEl->Attribute("uvy"));
|
||||||
|
Vector2 uv = Vector2(uvX, uvY);
|
||||||
|
|
||||||
|
float tanX = atof(vertEl->Attribute("tx"));
|
||||||
|
float tanY = atof(vertEl->Attribute("ty"));
|
||||||
|
float tanZ = atof(vertEl->Attribute("tz"));
|
||||||
|
Vector3 tan = Vector3(tanX, tanY, tanZ);
|
||||||
|
|
||||||
|
float biTanX = atof(vertEl->Attribute("bx"));
|
||||||
|
float biTanY = atof(vertEl->Attribute("by"));
|
||||||
|
float biTanZ = atof(vertEl->Attribute("bz"));
|
||||||
|
Vector3 biTan = Vector3(biTanX, biTanY, biTanZ);
|
||||||
|
|
||||||
|
Mesh::Vertex vertex;
|
||||||
|
vertex.pos = vertPos[id];
|
||||||
|
vertex.norm = vertNorm[id];
|
||||||
|
vertex.uv = uv;
|
||||||
|
vertex.tan = tan;
|
||||||
|
vertex.biTan = biTan;
|
||||||
|
|
||||||
|
for(int j = 0, boneIndex = 0; j < numBones; j++){
|
||||||
|
if(weights[id * numBones + j] > 0){
|
||||||
|
vertex.boneIndices[boneIndex] = j;
|
||||||
|
vertex.weights[boneIndex] = weights[id * numBones + j];
|
||||||
|
boneIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indices[i] = i;
|
||||||
|
vertices[i] = vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertNorm.clear();
|
||||||
|
tagName = "shapekey";
|
||||||
|
i = 0;
|
||||||
|
int numShapeKeys = atoi(meshEl->Attribute("num_shape_keys"));
|
||||||
|
Mesh::ShapeKey *shapeKeys = new Mesh::ShapeKey[numShapeKeys];
|
||||||
|
|
||||||
|
for(XMLElement *shapeKeyEl = meshEl->FirstChildElement(tagName); shapeKeyEl && strcmp(shapeKeyEl->Name(), tagName) == 0; shapeKeyEl = shapeKeyEl->NextSiblingElement(), i++){
|
||||||
|
shapeKeys[i].name = shapeKeyEl->Attribute("name");
|
||||||
|
shapeKeys[i].minValue = atof(shapeKeyEl->Attribute("min"));
|
||||||
|
shapeKeys[i].maxValue = atof(shapeKeyEl->Attribute("max"));
|
||||||
|
|
||||||
|
XMLElement *driverEl = shapeKeyEl->FirstChildElement("driver");
|
||||||
|
|
||||||
|
vector<Vector3> shapeKeyPos;
|
||||||
|
|
||||||
|
for(XMLElement *vertEl = shapeKeyEl->FirstChildElement(tagName); vertEl; vertEl = vertEl->NextSiblingElement()){
|
||||||
|
float posX = atof(vertEl->Attribute("px"));
|
||||||
|
float posY = atof(vertEl->Attribute("py"));
|
||||||
|
float posZ = atof(vertEl->Attribute("pz"));
|
||||||
|
shapeKeyPos.push_back(Vector3(posX, posY, posZ));
|
||||||
|
|
||||||
|
for(int j = 0; j < numVertices; j++)
|
||||||
|
vertices[j].shapeKeyOffsets[i] = shapeKeyPos[vertIds[j]] - vertPos[vertIds[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh *mesh = new Mesh(vertices, indices, numVertices / 3, vertexGroups, numBones, shapeKeys, numShapeKeys);
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
Skeleton* XmlModelReader::processSkeleton(Node *root, XMLElement *skeletonEl){
|
||||||
|
XMLElement *rootBoneEl = skeletonEl->FirstChildElement("bone");
|
||||||
|
Skeleton *skeleton = new Skeleton(nullptr);
|
||||||
|
skeleton->addBone((Bone*)processNode(root, rootBoneEl, true), (Bone*)root);
|
||||||
|
|
||||||
|
return skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* XmlModelReader::processNode(Node *parent, XMLElement *xmlEl, bool bone){
|
||||||
|
Node *node = nullptr;
|
||||||
|
|
||||||
|
if(bone){
|
||||||
|
float headX = atof(xmlEl->Attribute("hx"));
|
||||||
|
float headY = atof(xmlEl->Attribute("hy"));
|
||||||
|
float headZ = atof(xmlEl->Attribute("hz"));
|
||||||
|
Vector3 head = Vector3(headX, headY, headZ);
|
||||||
|
|
||||||
|
float xAxisX = atof(xmlEl->Attribute("xaxisx"));
|
||||||
|
float xAxisY = atof(xmlEl->Attribute("xaxisy"));
|
||||||
|
float xAxisZ = atof(xmlEl->Attribute("xaxisz"));
|
||||||
|
Vector3 xAxis = Vector3(xAxisX, xAxisY, xAxisZ);
|
||||||
|
|
||||||
|
float yAxisX = atof(xmlEl->Attribute("yaxisx"));
|
||||||
|
float yAxisY = atof(xmlEl->Attribute("yaxisy"));
|
||||||
|
float yAxisZ = atof(xmlEl->Attribute("yaxisz"));
|
||||||
|
Vector3 yAxis = Vector3(yAxisX, yAxisY, yAxisZ);
|
||||||
|
|
||||||
|
string name = xmlEl->Attribute("name");
|
||||||
|
float length = atof(xmlEl->Attribute("length"));
|
||||||
|
|
||||||
|
Vector3 zAxis = xAxis.cross(yAxis).norm();
|
||||||
|
Vector3 pos = head;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(!parent){
|
||||||
|
parent = model;
|
||||||
|
swap(pos.y, pos.z);
|
||||||
|
pos.z = -pos.z;
|
||||||
|
swap(yAxis.y, yAxis.z);
|
||||||
|
yAxis.z = -yAxis.z;
|
||||||
|
swap(zAxis.y, zAxis.z);
|
||||||
|
zAxis.z = -zAxis.z;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*/
|
||||||
|
pos = pos + Vector3(0, ((Bone*)parent)->getLength(), 0);
|
||||||
|
|
||||||
|
node = new Bone(name, length, pos, Quaternion::QUAT_W, Vector3::VEC_IJK);
|
||||||
|
node->lookAt(zAxis, yAxis);
|
||||||
|
const char *ikTarget = xmlEl->Attribute("iktarget");
|
||||||
|
|
||||||
|
if(ikTarget != nullptr){
|
||||||
|
((Bone*)node)->setIkTarget(ikTarget);
|
||||||
|
int ikChainLength = atoi(xmlEl->Attribute("chainlength"));
|
||||||
|
((Bone*)node)->setIkChainLength(ikChainLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLElement *skeletonTag = xmlEl->FirstChildElement("skeleton");
|
||||||
|
|
||||||
|
if(skeletonTag)
|
||||||
|
processSkeleton(node, skeletonTag);
|
||||||
|
|
||||||
|
XMLElement *meshTag = xmlEl->FirstChildElement("mesh");
|
||||||
|
|
||||||
|
if(meshTag)
|
||||||
|
processMesh(meshTag);
|
||||||
|
|
||||||
|
XMLElement *lightTag = xmlEl->FirstChildElement("light");
|
||||||
|
|
||||||
|
for(XMLElement *el = xmlEl->FirstChildElement("node"); el; el = el->NextSiblingElement())
|
||||||
|
parent->attachChild(processNode(parent, el, bone));
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef XML_MODEL_READER_H
|
||||||
|
#define XML_MODEL_READER_H
|
||||||
|
|
||||||
|
#include "modelReader.h"
|
||||||
|
|
||||||
|
namespace tinyxml2{
|
||||||
|
class XMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace vb01{
|
||||||
|
class Node;
|
||||||
|
class Mesh;
|
||||||
|
class Skeleton;
|
||||||
|
class Bone;
|
||||||
|
|
||||||
|
class XmlModelReader : public ModelReader{
|
||||||
|
public:
|
||||||
|
XmlModelReader(Model*, std::string);
|
||||||
|
private:
|
||||||
|
Node* processNode(Node*, tinyxml2::XMLElement*, bool = false);
|
||||||
|
Mesh* processMesh(tinyxml2::XMLElement*);
|
||||||
|
Skeleton* processSkeleton(Node*, tinyxml2::XMLElement*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user