Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2882035b5 | |||
| 23dd149d48 | |||
| 9057c94af9 |
@@ -0,0 +1,297 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "ColladaModel.h"
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
#define DEG2RAD PI/180
|
||||
|
||||
ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normals_(), rootjoint()
|
||||
{
|
||||
Transform = Matrix::identity();
|
||||
Rotation = Matrix::identity();
|
||||
Scale = Matrix::identity();
|
||||
Translation = Matrix::identity();
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
doc.LoadFile(filename);
|
||||
|
||||
load_texture(filename, "_diffuse.tga", diffusemap_);
|
||||
load_texture(filename, "_nm_tangent.tga", normalmap_);
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////faces//////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
face_count = 0;
|
||||
tinyxml2::XMLElement* xml_face = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement()->FirstChildElement()->FirstChildElement("triangles");
|
||||
xml_face->QueryIntAttribute("count", &face_count); //get count
|
||||
std::stringstream str_triangle(xml_face->FirstChildElement("p")->GetText()); //get values as a string
|
||||
|
||||
for (int i = 0; i < face_count; i++)
|
||||
{
|
||||
faces_.push_back(std::vector<Vec3i>());
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
Vec3i temp;
|
||||
str_triangle >> temp.x;
|
||||
str_triangle >> temp.y;
|
||||
str_triangle >> temp.z;
|
||||
faces_[i].push_back(temp);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////vertex/////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
vertex_count = 0;
|
||||
tinyxml2::XMLElement* xml_vertex = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("source")->FirstChildElement("float_array");
|
||||
xml_vertex->QueryIntAttribute("count", &vertex_count);
|
||||
std::stringstream str_vertex(xml_vertex->GetText());
|
||||
|
||||
for (int i = 0; i < vertex_count / 3; i++)
|
||||
{
|
||||
Vec3f temp;
|
||||
str_vertex >> temp.x;
|
||||
str_vertex >> temp.y;
|
||||
str_vertex >> temp.z;
|
||||
vertices_.push_back(temp);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////normal////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int normal_count = 0;
|
||||
tinyxml2::XMLElement* xml_normal = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("source")->NextSiblingElement()->FirstChildElement("float_array");
|
||||
xml_normal->QueryIntAttribute("count", &normal_count);
|
||||
std::stringstream str_normal(xml_normal->GetText());
|
||||
|
||||
for (int i = 0; i < normal_count / 3; i++)
|
||||
{
|
||||
Vec3f temp;
|
||||
str_normal >> temp.x;
|
||||
str_normal >> temp.y;
|
||||
str_normal >> temp.z;
|
||||
normals_.push_back(temp);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////textcoord/////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int texcoord_count = 0;
|
||||
tinyxml2::XMLElement* xml_texture = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("source")->NextSiblingElement()->NextSiblingElement()->FirstChildElement("float_array");
|
||||
xml_texture->QueryIntAttribute("count", &texcoord_count);
|
||||
std::stringstream str_texcoord(xml_texture->GetText());
|
||||
|
||||
for (int i = 0; i < texcoord_count / 2; i++)
|
||||
{
|
||||
Vec2f temp;
|
||||
str_texcoord >> temp.x;
|
||||
str_texcoord >> temp.y;
|
||||
texturecos_.push_back(temp);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int vertexweights_count = 0;
|
||||
tinyxml2::XMLElement* xml_vertexweights = doc.FirstChildElement("COLLADA")->FirstChildElement("library_controllers")->FirstChildElement()->FirstChildElement()->FirstChildElement("vertex_weights");
|
||||
xml_vertexweights->QueryIntAttribute("count", &vertexweights_count);
|
||||
std::stringstream str_vertexweights(xml_vertexweights->FirstChildElement("vcount")->GetText());
|
||||
std::stringstream str_vertexweights1(xml_vertexweights->FirstChildElement("v")->GetText());
|
||||
|
||||
for (int i = 0; i < vertexweights_count; i++)
|
||||
{
|
||||
int temp;
|
||||
Vec2i temp1;
|
||||
vertexweights_.push_back(std::vector<Vec2i>());
|
||||
str_vertexweights >> temp;
|
||||
|
||||
for (int j = 0; j < temp; j++)
|
||||
{
|
||||
str_vertexweights1 >> temp1.x;
|
||||
str_vertexweights1 >> temp1.y;
|
||||
vertexweights_[i].push_back(temp1);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int weight_count = 0;
|
||||
tinyxml2::XMLElement* xml_weight = doc.FirstChildElement("COLLADA")->FirstChildElement("library_controllers")->FirstChildElement()->FirstChildElement()->FirstChildElement("source")->NextSiblingElement()->NextSiblingElement()->FirstChildElement();
|
||||
xml_weight->QueryIntAttribute("count", &weight_count);
|
||||
std::stringstream str_weight(xml_weight->GetText());
|
||||
|
||||
for (int i = 0; i < weight_count; i++)
|
||||
{
|
||||
float temp;
|
||||
str_weight >> temp;
|
||||
weights_.push_back(temp);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*joint_count = 0;
|
||||
tinyxml2::XMLElement* xml_joint = doc.FirstChildElement("COLLADA")->FirstChildElement("library_controllers")->FirstChildElement()->FirstChildElement()->FirstChildElement("source")->FirstChildElement();
|
||||
xml_joint->QueryIntAttribute("count", &joint_count);
|
||||
std::stringstream str_joint(xml_joint->GetText());
|
||||
*/
|
||||
/*for (int i = 0; i < joint_count; i++)
|
||||
{
|
||||
Vec2f temp;
|
||||
str_texcoord >> temp.x;
|
||||
str_texcoord >> temp.y;
|
||||
texturecos_.push_back(temp);
|
||||
}*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//tinyxml2::XMLElement* xml_hierachy = doc.FirstChildElement("COLLADA")->FirstChildElement("library_visual_scenes")->FirstChildElement("visual_scene")->FirstChildElement("node")->FirstChildElement("node");
|
||||
//std::stringstream str_hierachy(xml_hierachy->GetText());
|
||||
|
||||
//ColladaModel::rootjoint = buildjoint(xml_hierachy);
|
||||
joint_count = 0;
|
||||
tinyxml2::XMLElement* xml_joint = doc.FirstChildElement("COLLADA")->FirstChildElement("library_controllers")->FirstChildElement("controller")->FirstChildElement("skin")->FirstChildElement("source")->FirstChildElement("Name_array");
|
||||
xml_joint->QueryIntAttribute("count", &joint_count);
|
||||
std::stringstream str_joint(xml_joint->GetText());
|
||||
|
||||
for (int i = 0; i < vertex_count / 3; i++)
|
||||
{
|
||||
std::string temp;
|
||||
str_vertex >> temp;
|
||||
|
||||
jointIDs_.push_back(temp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Joint buildjoint(tinyxml2::XMLElement* xml_hierachy)
|
||||
//{
|
||||
// const char* name;
|
||||
// xml_hierachy->QueryStringAttribute("name", &name);
|
||||
// std::stringstream str_transform(xml_hierachy->FirstChildElement("matrix")->GetText());
|
||||
// Matrix transform;
|
||||
//
|
||||
// if (xml_hierachy->FirstChildElement("node") != NULL)
|
||||
// {
|
||||
// xml_hierachy = xml_hierachy->FirstChildElement("node");
|
||||
// do
|
||||
// {
|
||||
//// buildjoint
|
||||
// } while (xml_hierachy->NextSiblingElement() != NULL);
|
||||
// }
|
||||
//}
|
||||
|
||||
ColladaModel::~ColladaModel() {
|
||||
}
|
||||
|
||||
void ColladaModel::ApplyTransform() {
|
||||
Transform = Translation * Scale * Rotation;
|
||||
}
|
||||
void ColladaModel::translate(Vec3f tr) {
|
||||
Translation[0][3] += tr.x;
|
||||
Translation[1][3] += tr.y;
|
||||
Translation[2][3] += tr.z;
|
||||
}
|
||||
void ColladaModel::rotate(Vec3f rot) {
|
||||
rot = rot * DEG2RAD;
|
||||
|
||||
Rotation[0][0] = cosf(rot.y) * cosf(rot.z);
|
||||
Rotation[0][1] = -cosf(rot.y) * sinf(rot.z);
|
||||
Rotation[0][2] = sinf(rot.y);
|
||||
Rotation[1][0] = sinf(rot.x) * sinf(rot.y) * cosf(rot.z) + cosf(rot.x) * sinf(rot.z);
|
||||
Rotation[1][1] = -sinf(rot.x) * sinf(rot.y) * sinf(rot.z) + cosf(rot.x) * cosf(rot.z);
|
||||
Rotation[1][2] = -sinf(rot.x) * cosf(rot.y);
|
||||
Rotation[2][0] = -cosf(rot.x) * sinf(rot.y) * cosf(rot.z) + sinf(rot.x) * sinf(rot.z);
|
||||
Rotation[2][1] = cosf(rot.x) * sinf(rot.y) * sinf(rot.z) + sinf(rot.x) * cosf(rot.z);
|
||||
Rotation[2][2] = cosf(rot.x) * cosf(rot.y);
|
||||
}
|
||||
void ColladaModel::scale(Vec3f scl) {
|
||||
Scale[0][0] = scl.x;
|
||||
Scale[1][1] = scl.y;
|
||||
Scale[2][2] = scl.z;
|
||||
}
|
||||
|
||||
int ColladaModel::nfaces() {
|
||||
return face_count;
|
||||
}
|
||||
int ColladaModel::nvertices() {
|
||||
return vertex_count;
|
||||
}
|
||||
|
||||
std::vector<int> ColladaModel::face(int idx) {
|
||||
std::vector<int> face;
|
||||
for (int i = 0; i < (int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
|
||||
return face;
|
||||
}
|
||||
Vec3f ColladaModel::vertix(int i) {
|
||||
return vertices_[i];
|
||||
}
|
||||
Vec3f ColladaModel::vertix(int iface, int nthvert) {
|
||||
return vertices_[faces_[iface][nthvert][0]];
|
||||
}
|
||||
|
||||
void ColladaModel::load_texture(std::string filename, const char* suffix, TGAImage& img) {
|
||||
std::string texfile(filename);
|
||||
size_t dot = texfile.find_last_of(".");
|
||||
if (dot != std::string::npos) {
|
||||
texfile = texfile.substr(0, dot) + std::string(suffix);
|
||||
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
|
||||
img.flip_vertically();
|
||||
}
|
||||
}
|
||||
|
||||
TGAColor ColladaModel::diffuse(Vec2f uvf) {
|
||||
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
|
||||
return diffusemap_.get(uv[0], uv[1]);
|
||||
}
|
||||
|
||||
Vec3f ColladaModel::normal(Vec2f uvf) {
|
||||
Vec2i uv(uvf[0] * normalmap_.get_width(), uvf[1] * normalmap_.get_height());
|
||||
TGAColor c = normalmap_.get(uv[0], uv[1]);
|
||||
Vec3f res;
|
||||
for (int i = 0; i < 3; i++)
|
||||
res[2 - i] = (float)c[i] / 255.f * 2.f - 1.f;
|
||||
return res;
|
||||
}
|
||||
|
||||
Vec2f ColladaModel::uv(int iface, int nthvert) {
|
||||
return texturecos_[faces_[iface][nthvert][2]];
|
||||
}
|
||||
|
||||
float ColladaModel::specular(Vec2f uvf) {
|
||||
Vec2i uv(uvf[0] * specularmap_.get_width(), uvf[1] * specularmap_.get_height());
|
||||
return specularmap_.get(uv[0], uv[1])[0] / 1.f;
|
||||
}
|
||||
|
||||
Vec3f ColladaModel::normal(int iface, int nthvert) {
|
||||
int idx = faces_[iface][nthvert][1];
|
||||
return normals_[idx].normalize();
|
||||
}
|
||||
|
||||
Joint ColladaModel::getrootjoint()
|
||||
{
|
||||
return rootjoint;
|
||||
}
|
||||
|
||||
void ColladaModel::doanimation(Animation animation)
|
||||
{
|
||||
//animator.doanimation(animation);
|
||||
}
|
||||
|
||||
void ColladaModel::updateanimator()
|
||||
{
|
||||
//animator.update();
|
||||
}
|
||||
|
||||
std::vector<Matrix> ColladaModel::getjointtransforms()
|
||||
{
|
||||
std::vector<Matrix> jointMat(joint_count);
|
||||
addjointtoarray(rootjoint, jointMat);
|
||||
return jointMat;
|
||||
}
|
||||
|
||||
void ColladaModel::addjointtoarray(Joint parent, std::vector<Matrix> jointMat)
|
||||
{
|
||||
jointMat[parent.index] = parent.getTransform();
|
||||
|
||||
for (auto& child : parent.children)
|
||||
{
|
||||
addjointtoarray(child, jointMat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef __MODEL_s__
|
||||
#define __MODEL_s__
|
||||
#pragma once
|
||||
|
||||
#include "ColladaModel.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "geometry.h"
|
||||
#include "tgaimage.h"
|
||||
#include "joint.h"
|
||||
#include "animator.h"
|
||||
#include "animation.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
class ColladaModel {
|
||||
private:
|
||||
int face_count;
|
||||
int vertex_count;
|
||||
int joint_count;
|
||||
|
||||
Joint rootjoint;
|
||||
int rootindex=0;
|
||||
char* rootname;
|
||||
Matrix root_transform;
|
||||
|
||||
//Animator animator;
|
||||
|
||||
std::vector<std::vector<Vec3i> > faces_; //vertex/normal/uv
|
||||
std::vector<Vec3f> vertices_;
|
||||
std::vector<Vec3f> normals_;
|
||||
std::vector<Vec2f> texturecos_;
|
||||
|
||||
// #include <map>
|
||||
// map<const char*, int> joint_names;
|
||||
// joints.add(pair<const char*, int>("TORSO", 0));
|
||||
|
||||
// {TORSO, 0}
|
||||
// {LEG, 1}
|
||||
// {HAND, 2}
|
||||
|
||||
//joint_names.get("TORSO");
|
||||
|
||||
// 1. Get jointnames and map them to ids
|
||||
// 2. get each joint and fill in the Joint class
|
||||
// 3. get inversebindtransforms
|
||||
|
||||
// Vector -> Vectors -> (joint , weight)
|
||||
std::vector<std::vector<Vec2i>> vertexweights_; //joint/weight
|
||||
std::vector<std::string> jointIDs_;
|
||||
// { TORSO , LEG, TEZ}
|
||||
// { 0, 1, 2}
|
||||
// jointIDs[0]
|
||||
std::vector<float> weights_;
|
||||
|
||||
TGAImage diffusemap_;
|
||||
TGAImage normalmap_;
|
||||
TGAImage specularmap_;
|
||||
|
||||
void load_texture(std::string filename, const char* suffix, TGAImage& img);
|
||||
public:
|
||||
ColladaModel() = default;
|
||||
ColladaModel(const char* filename);
|
||||
~ColladaModel();
|
||||
|
||||
int nfaces();
|
||||
int nvertices();
|
||||
|
||||
Vec3f vertix(int iface, int nthvert);
|
||||
Vec3f vertix(int i);
|
||||
|
||||
Vec3f normal(int iface, int nthvert);
|
||||
Vec3f normal(Vec2f uv);
|
||||
|
||||
Vec2f uv(int iface, int nthvert);
|
||||
|
||||
Matrix Transform;
|
||||
|
||||
Matrix Rotation;
|
||||
Matrix Scale;
|
||||
Matrix Translation;
|
||||
|
||||
void translate(Vec3f tr);
|
||||
void rotate(Vec3f rot);
|
||||
void scale(Vec3f scl);
|
||||
void ApplyTransform();
|
||||
|
||||
TGAColor diffuse(Vec2f uv);
|
||||
float specular(Vec2f uv);
|
||||
std::vector<int> face(int idx);
|
||||
|
||||
/////////////////////////////
|
||||
Joint getrootjoint();
|
||||
|
||||
void doanimation(Animation animation);
|
||||
|
||||
void updateanimator();
|
||||
|
||||
std::vector<Matrix> getjointtransforms();
|
||||
|
||||
void addjointtoarray(Joint parent, std::vector<Matrix>);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "Joint.h"
|
||||
|
||||
Joint::Joint(int index, Matrix transform, char* name) {
|
||||
Joint::index = index;
|
||||
_transform = transform;
|
||||
Joint::name = name;
|
||||
}
|
||||
|
||||
Joint::~Joint() {
|
||||
}
|
||||
|
||||
void Joint::addChild(Joint child) {
|
||||
children.push_back(child);
|
||||
}
|
||||
|
||||
Matrix Joint::getTransform() {
|
||||
return _transform;
|
||||
}
|
||||
|
||||
void Joint::setTransform(Matrix transform) {
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
Matrix Joint::getInverseBindTransform() {
|
||||
return _inverseBindtransform;
|
||||
}
|
||||
|
||||
void Joint::calculateInverseBindTransform(Matrix parentBindTransform) {
|
||||
Matrix bindTransform = parentBindTransform * _localBindTransform;
|
||||
_inverseBindtransform = bindTransform.invert();
|
||||
|
||||
for (auto &child : children)
|
||||
{
|
||||
child.calculateInverseBindTransform(bindTransform);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "geometry.h"
|
||||
class Joint
|
||||
{
|
||||
private:
|
||||
Matrix _transform; //model space
|
||||
Matrix _localBindTransform;
|
||||
Matrix _inverseBindtransform;
|
||||
|
||||
public:
|
||||
int index;
|
||||
char* name;
|
||||
std::vector<Joint> children;
|
||||
|
||||
Joint() = default;
|
||||
Joint(int index,Matrix transform,char* name);
|
||||
~Joint();
|
||||
|
||||
void addChild(Joint child);
|
||||
|
||||
Matrix getTransform();
|
||||
void setTransform(Matrix transform);
|
||||
|
||||
Matrix getInverseBindTransform();
|
||||
void calculateInverseBindTransform(Matrix parentBindTransform);
|
||||
};
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{42971E68-F861-4D45-9DA6-F5E163705584}</ProjectGuid>
|
||||
<RootNamespace>OpenWindow</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -115,21 +115,37 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="animation.cpp" />
|
||||
<ClCompile Include="animator.cpp" />
|
||||
<ClCompile Include="camera.cpp" />
|
||||
<ClCompile Include="colladamodel.cpp" />
|
||||
<ClCompile Include="geometry.cpp" />
|
||||
<ClCompile Include="joint.cpp" />
|
||||
<ClCompile Include="jointtransform.cpp" />
|
||||
<ClCompile Include="keyframe.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="model.cpp" />
|
||||
<ClCompile Include="quaternion.cpp" />
|
||||
<ClCompile Include="renderer.cpp" />
|
||||
<ClCompile Include="tgaimage.cpp" />
|
||||
<ClCompile Include="tinyxml2.cpp" />
|
||||
<ClCompile Include="util_renderer.cpp" />
|
||||
<ClCompile Include="util_window.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="animation.h" />
|
||||
<ClInclude Include="animator.h" />
|
||||
<ClInclude Include="colladamodel.h" />
|
||||
<ClInclude Include="geometry.h" />
|
||||
<ClInclude Include="camera.h" />
|
||||
<ClInclude Include="joint.h" />
|
||||
<ClInclude Include="jointtransform.h" />
|
||||
<ClInclude Include="keyframe.h" />
|
||||
<ClInclude Include="model.h" />
|
||||
<ClInclude Include="quaternion.h" />
|
||||
<ClInclude Include="renderer.h" />
|
||||
<ClInclude Include="tgaimage.h" />
|
||||
<ClInclude Include="tinyxml2.h" />
|
||||
<ClInclude Include="util_renderer.h" />
|
||||
<ClInclude Include="util_window.h" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -39,6 +39,30 @@
|
||||
<ClCompile Include="util_renderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="colladamodel.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tinyxml2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="joint.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="animator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="animation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="keyframe.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="jointtransform.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="quaternion.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="util_window.h">
|
||||
@@ -62,5 +86,29 @@
|
||||
<ClInclude Include="util_renderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="colladamodel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tinyxml2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="joint.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="animator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="animation.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keyframe.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="jointtransform.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="quaternion.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "animation.h"
|
||||
|
||||
Animation::Animation(float seconds, std::vector<Keyframe> keyframes)
|
||||
{
|
||||
length = seconds;
|
||||
keyframes_ = keyframes;
|
||||
}
|
||||
|
||||
float Animation::getlength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
std::vector<Keyframe> Animation::getkeyframe()
|
||||
{
|
||||
return keyframes_;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "keyframe.h"
|
||||
#include <vector>
|
||||
|
||||
class Animation {
|
||||
private:
|
||||
float length;
|
||||
std::vector<Keyframe> keyframes_;
|
||||
|
||||
public:
|
||||
Animation() = default;
|
||||
Animation(float seconds, std::vector<Keyframe> keyframes);
|
||||
float getlength();
|
||||
std::vector<Keyframe>getkeyframe();
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "animator.h"
|
||||
#include "colladamodel.h"
|
||||
|
||||
void Animator::increaseAnimationTime()
|
||||
{
|
||||
animation_time_ += (1/60.f);
|
||||
if (animation_time_ > current_animation_.getlength())
|
||||
{
|
||||
animation_time_ = (int)(animation_time_) % (int)(current_animation_.getlength());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Animator::applyPoseToJoints(std::map<std::string, Matrix> currentPose, Joint joint, Matrix parentTransform)
|
||||
{
|
||||
Matrix currentLocalTransform = currentPose.at(joint.name);
|
||||
Matrix currentTransform = parentTransform * currentLocalTransform;
|
||||
for (Joint childJoint : joint.children) {
|
||||
applyPoseToJoints(currentPose, childJoint, currentTransform);
|
||||
}
|
||||
currentTransform = currentTransform * joint.getInverseBindTransform();
|
||||
joint.setTransform(currentTransform);
|
||||
}
|
||||
|
||||
std::vector<Keyframe> Animator::getPreviousAndNextFrames()
|
||||
{
|
||||
std::vector<Keyframe> allFrames = current_animation_.getkeyframe();
|
||||
Keyframe previousFrame = allFrames[0];
|
||||
Keyframe nextFrame = allFrames[0];
|
||||
for (int i = 1; i < allFrames.capacity(); i++) {
|
||||
nextFrame = allFrames[i];
|
||||
if (nextFrame.gettimestamp() > animation_time_) {
|
||||
break;
|
||||
}
|
||||
previousFrame = allFrames[i];
|
||||
}
|
||||
return std::vector<Keyframe>{ previousFrame, nextFrame };
|
||||
}
|
||||
|
||||
float Animator::calculateProgression(Keyframe previousFrame, Keyframe nextFrame)
|
||||
{
|
||||
float totalTime = nextFrame.gettimestamp() - previousFrame.gettimestamp();
|
||||
float currentTime = animation_time_ - previousFrame.gettimestamp();
|
||||
return currentTime / totalTime;
|
||||
}
|
||||
|
||||
std::map<std::string, Matrix> Animator::interpolatePoses(Keyframe previousFrame, Keyframe nextFrame, float progression)
|
||||
{
|
||||
std::map<std::string, Matrix> currentPose ;
|
||||
std::set<std::string> key_set;
|
||||
make_key_set(previousFrame.getJointKeyFrames(), key_set);
|
||||
for (std::string jointName : key_set)
|
||||
{
|
||||
JointTransform previousTransform = previousFrame.getJointKeyFrames().at(jointName);
|
||||
JointTransform nextTransform = nextFrame.getJointKeyFrames().at(jointName);
|
||||
JointTransform currentTransform = JointTransform::interpolate(previousTransform, nextTransform, progression);
|
||||
currentPose.insert_or_assign(jointName, currentTransform.getlocationtransform());
|
||||
make_key_set(previousFrame.getJointKeyFrames(), key_set);
|
||||
}
|
||||
return currentPose;
|
||||
}
|
||||
|
||||
Animator::Animator(ColladaModel entity)
|
||||
{
|
||||
entity_ = &entity;
|
||||
}
|
||||
|
||||
void Animator::doanimation(Animation animation)
|
||||
{
|
||||
animation_time_ = 0;
|
||||
current_animation_ = animation;
|
||||
}
|
||||
|
||||
void Animator::update()
|
||||
{
|
||||
if (¤t_animation_ == NULL) {
|
||||
return;
|
||||
}
|
||||
increaseAnimationTime();
|
||||
std::map<std::string, Matrix> currentPose = calculateCurrentAnimationPose();
|
||||
applyPoseToJoints(currentPose, entity_->getrootjoint(), Matrix());
|
||||
}
|
||||
|
||||
std::map<std::string, Matrix> Animator::calculateCurrentAnimationPose()
|
||||
{
|
||||
std::vector<Keyframe> frames = getPreviousAndNextFrames();
|
||||
float progression = calculateProgression(frames[0], frames[1]);
|
||||
return interpolatePoses(frames[0], frames[1], progression);
|
||||
}
|
||||
|
||||
template<typename TK, typename TV>
|
||||
std::vector<TK> extract_keys(std::map<TK, TV> const& input_map) {
|
||||
std::vector<TK> retval;
|
||||
for (auto const& element : input_map) {
|
||||
retval.push_back(element.first);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename TK, typename TV>
|
||||
std::vector<TV> extract_values(std::map<TK, TV> const& input_map) {
|
||||
std::vector<TV> retval;
|
||||
for (auto const& element : input_map) {
|
||||
retval.push_back(element.second);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include "animation.h"
|
||||
#include "geometry.h"
|
||||
#include "keyframe.h"
|
||||
#include "jointtransform.h"
|
||||
#include "joint.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
class ColladaModel;
|
||||
|
||||
class Animator {
|
||||
private:
|
||||
ColladaModel* entity_;
|
||||
Animation current_animation_;
|
||||
float animation_time_;
|
||||
|
||||
void increaseAnimationTime();
|
||||
std::map<std::string,Matrix> calculateCurrentAnimationPose();
|
||||
void applyPoseToJoints(std::map<std::string, Matrix> currentPose, Joint joint, Matrix parentTransform);
|
||||
std::vector<Keyframe> getPreviousAndNextFrames();
|
||||
float calculateProgression(Keyframe previousFrame, Keyframe nextFrame);
|
||||
std::map<std::string, Matrix> interpolatePoses(Keyframe previousFrame, Keyframe nextFrame, float progression);
|
||||
|
||||
public:
|
||||
Animator(ColladaModel entity);
|
||||
void doanimation(Animation animation);
|
||||
void update();
|
||||
};
|
||||
|
||||
template< class Key,
|
||||
class T,
|
||||
class Comparator,
|
||||
class MapAllocator,
|
||||
class SetAllocator>
|
||||
void make_key_set(const std::map<Key, T, Comparator, MapAllocator>& map,
|
||||
std::set<Key, Comparator, SetAllocator>& set)
|
||||
{
|
||||
set.clear();
|
||||
typedef typename std::map<Key, T, Comparator, MapAllocator> map_type;
|
||||
typename map_type::const_iterator itr = map.begin();
|
||||
while (map.end() != itr)
|
||||
{
|
||||
set.insert((itr++)->first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "jointtransform.h"
|
||||
|
||||
|
||||
|
||||
JointTransform::JointTransform(Vec3f position, Quaternion rotation)
|
||||
{
|
||||
position_ = position;
|
||||
rotation_ = rotation;
|
||||
}
|
||||
|
||||
Matrix JointTransform::getlocationtransform()
|
||||
{
|
||||
Matrix matrix;
|
||||
Vec4f column = Vec4f(position_.x, position_.y, position_.z, 1);
|
||||
matrix.set_col(3, column);
|
||||
matrix = matrix * rotation_.toRotationMatrix();
|
||||
return matrix;
|
||||
}
|
||||
|
||||
JointTransform JointTransform::interpolate(JointTransform frame1, JointTransform frame2, float progression)
|
||||
{
|
||||
Vec3f pos = interpolate(frame1.position_, frame2.position_, progression);
|
||||
Quaternion rot = Quaternion::interpolate(frame1.rotation_, frame2.rotation_, progression);
|
||||
return JointTransform(pos, rot);
|
||||
}
|
||||
|
||||
Vec3f JointTransform::interpolate(Vec3f start, Vec3f end, float progression)
|
||||
{
|
||||
float x = start.x + (end.x - start.x) * progression;
|
||||
float y = start.y + (end.y - start.y) * progression;
|
||||
float z = start.z + (end.z - start.z) * progression;
|
||||
|
||||
return Vec3f(x,y,z);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "quaternion.h"
|
||||
#include "geometry.h"
|
||||
|
||||
class JointTransform
|
||||
{
|
||||
private:
|
||||
|
||||
Vec3f position_;
|
||||
|
||||
Quaternion rotation_;
|
||||
|
||||
public:
|
||||
JointTransform() = default;
|
||||
JointTransform(Vec3f position,Quaternion rotation);
|
||||
|
||||
Matrix getlocationtransform();
|
||||
|
||||
static JointTransform interpolate(JointTransform frame1, JointTransform frame2, float progression);
|
||||
|
||||
static Vec3f interpolate(Vec3f start,Vec3f end, float progression);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "keyframe.h"
|
||||
|
||||
Keyframe::Keyframe(float timestamp, std::map<std::string, JointTransform> pose)
|
||||
{
|
||||
timestamp_ = timestamp;
|
||||
pose_ = pose;
|
||||
}
|
||||
|
||||
float Keyframe::gettimestamp()
|
||||
{
|
||||
return timestamp_;
|
||||
}
|
||||
|
||||
std::map<std::string, JointTransform> Keyframe::getJointKeyFrames()
|
||||
{
|
||||
return pose_;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef HI
|
||||
#define HI
|
||||
|
||||
// your declarations (and certain types of definitions) here
|
||||
|
||||
|
||||
#include <map>
|
||||
#include "jointtransform.h"
|
||||
|
||||
|
||||
class Keyframe{
|
||||
private:
|
||||
float timestamp_;
|
||||
std::map<std::string, JointTransform> pose_;
|
||||
|
||||
public:
|
||||
Keyframe() = default;
|
||||
Keyframe(float timestamp,std::map<std::string, JointTransform> pose);
|
||||
float gettimestamp();
|
||||
std::map<std::string, JointTransform> getJointKeyFrames();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "quaternion.h"
|
||||
#include <math.h>
|
||||
|
||||
Quaternion::Quaternion(float x, float y, float z, float w)
|
||||
{
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
z_ = z;
|
||||
w_ = w;
|
||||
normalize();
|
||||
}
|
||||
|
||||
void Quaternion::normalize()
|
||||
{
|
||||
float mag = (float)sqrt(w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_);
|
||||
w_ /= mag;
|
||||
x_ /= mag;
|
||||
y_ /= mag;
|
||||
z_ /= mag;
|
||||
}
|
||||
|
||||
Matrix Quaternion::toRotationMatrix()
|
||||
{
|
||||
Matrix matrix;
|
||||
float xy = x_ * y_;
|
||||
float xz = x_ * z_;
|
||||
float xw = x_ * w_;
|
||||
float yz = y_ * z_;
|
||||
float yw = y_ * w_;
|
||||
float zw = z_ * w_;
|
||||
float xSquared = x_ * x_;
|
||||
float ySquared = y_ * y_;
|
||||
float zSquared = z_ * z_;
|
||||
|
||||
Vec4f c0 = Vec4f(1 - 2 * (ySquared + zSquared), 2 * (xy - zw), 2 * (xz + yw),0);
|
||||
Vec4f c1 = Vec4f(2 * (xy + zw), 1 - 2 * (xSquared + zSquared), 2 * (yz - xw), 0);
|
||||
Vec4f c2 = Vec4f(2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xSquared + ySquared), 0);
|
||||
Vec4f c3 = Vec4f(0,0,0,1);
|
||||
|
||||
matrix.set_col(0,c0);
|
||||
matrix.set_col(1, c1);
|
||||
matrix.set_col(2, c2);
|
||||
matrix.set_col(3, c3);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::fromMatrix(Matrix matrix)
|
||||
{
|
||||
float w_, x_, y_, z_;
|
||||
float diagonal = matrix[0][0] + matrix[1][1] + matrix[2][2];
|
||||
if (diagonal > 0) {
|
||||
float w4 = (float)(sqrt(diagonal + 1.f) * 2.f);
|
||||
w_ = w4 / 4.f;
|
||||
x_ = (matrix[2][1] - matrix[1][2]) / w4;
|
||||
y_ = (matrix[0][2] - matrix[2][0]) / w4;
|
||||
z_ = (matrix[1][0] - matrix[0][1]) / w4;
|
||||
}
|
||||
else if ((matrix[0][0] > matrix[1][1]) && (matrix[0][0] > matrix[2][2])) {
|
||||
float x4 = (float)(sqrt(1.f + matrix[0][0] - matrix[1][1] - matrix[2][2]) * 2.f);
|
||||
w_ = (matrix[2][1] - matrix[1][2]) / x4;
|
||||
x_ = x4 / 4.f;
|
||||
y_ = (matrix[0][1] + matrix[1][0]) / x4;
|
||||
z_ = (matrix[0][2] + matrix[2][0]) / x4;
|
||||
}
|
||||
else if (matrix[1][1] > matrix[2][2]) {
|
||||
float y4 = (float)(sqrt(1.f + matrix[1][1] - matrix[0][0] - matrix[2][2]) * 2.f);
|
||||
w_ = (matrix[0][2] - matrix[2][0]) / y4;
|
||||
x_ = (matrix[0][1] + matrix[1][0]) / y4;
|
||||
y_ = y4 / 4.f;
|
||||
z_ = (matrix[1][2] + matrix[2][1]) / y4;
|
||||
}
|
||||
else {
|
||||
float z4 = (float)(sqrt(1.f + matrix[2][2] - matrix[0][0] - matrix[1][1]) * 2.f);
|
||||
w_ = (matrix[1][0] - matrix[0][1]) / z4;
|
||||
x_ = (matrix[0][2] + matrix[2][0]) / z4;
|
||||
y_ = (matrix[1][2] + matrix[2][1]) / z4;
|
||||
z_ = z4 / 4.f;
|
||||
}
|
||||
return Quaternion(x_, y_, z_, w_);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::interpolate(Quaternion a, Quaternion b, float blend)
|
||||
{
|
||||
Quaternion result(0, 0, 0, 1);
|
||||
float dot = a.w_ * b.w_ + a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
|
||||
float blendI = 1.f - blend;
|
||||
if (dot < 0) {
|
||||
result.w_ = blendI * a.w_ + blend * -b.w_;
|
||||
result.x_ = blendI * a.x_ + blend * -b.x_;
|
||||
result.y_ = blendI * a.y_ + blend * -b.y_;
|
||||
result.z_ = blendI * a.z_ + blend * -b.z_;
|
||||
}
|
||||
else {
|
||||
result.w_ = blendI * a.w_ + blend * b.w_;
|
||||
result.x_ = blendI * a.x_ + blend * b.x_;
|
||||
result.y_ = blendI * a.y_ + blend * b.y_;
|
||||
result.z_ = blendI * a.z_ + blend * b.z_;
|
||||
}
|
||||
result.normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "geometry.h"
|
||||
class Quaternion
|
||||
{
|
||||
private:
|
||||
float x_, y_, z_, w_;
|
||||
|
||||
|
||||
public:
|
||||
Quaternion() = default;
|
||||
Quaternion(float x, float y, float z, float w);
|
||||
void normalize();
|
||||
Matrix toRotationMatrix();
|
||||
static Quaternion fromMatrix(Matrix matrix);
|
||||
static Quaternion interpolate(Quaternion a, Quaternion b, float blend);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "util_window.h"
|
||||
#include "camera.h"
|
||||
#include "util_renderer.h"
|
||||
#include "colladamodel.h"
|
||||
|
||||
#define HORIZONTAL_CAMERA_SPEED 0.1
|
||||
#define VERTICAL_CAMERA_SPEED 0.1
|
||||
@@ -25,7 +26,7 @@ Matrix ViewPort = Matrix::identity();
|
||||
Matrix ModelView = Matrix::identity();
|
||||
Matrix Projection = Matrix::identity();
|
||||
|
||||
Model* model = new Model("african_head.obj");
|
||||
ColladaModel* model = new ColladaModel("sssssssssssss.dae");
|
||||
Camera camera;
|
||||
|
||||
Vec3f light_dir = Vec3f(1, 1, 1).normalize();
|
||||
@@ -58,7 +59,7 @@ struct TextureShader : public IShader {
|
||||
|
||||
virtual Vec4f vertex(int iface, int nthvert) {
|
||||
varying_uv_coords.set_col(nthvert, model->uv(iface, nthvert));
|
||||
Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert));
|
||||
Vec4f gl_Vertex = embed<4>(model->vertix(iface, nthvert));
|
||||
return ViewPort * Projection * ModelView * gl_Vertex; // transform it to screen coordinates
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user