Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2882035b5 | |||
| 23dd149d48 | |||
| 9057c94af9 | |||
| 8b1546cb54 | |||
| 26a7e48784 |
@@ -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,20 +115,38 @@
|
||||
</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>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -36,6 +36,33 @@
|
||||
<ClCompile Include="camera.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<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">
|
||||
@@ -56,5 +83,32 @@
|
||||
<ClInclude Include="camera.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<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>
|
||||
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -79,27 +79,31 @@ void Camera::move_camera_forward() {
|
||||
void Camera::move_camera_backward() {
|
||||
position = position - forward * movement_speed;
|
||||
}
|
||||
void Camera::rise() {
|
||||
position = position + Vec3f(0, movement_speed, 0);
|
||||
}
|
||||
void Camera::fall() {
|
||||
position = position - Vec3f(0, movement_speed, 0);
|
||||
}
|
||||
|
||||
void Camera::SetMovementSpeed(float speed) {
|
||||
movement_speed = speed;
|
||||
}
|
||||
|
||||
void Camera::ApplyChanges() {
|
||||
forward = Vec3f(sin(rotation.y * DEG2RAD), -sin(rotation.x * DEG2RAD), -cosf(rotation.y*DEG2RAD) * cosf(rotation.x*DEG2RAD));
|
||||
right = Vec3f(cos(rotation.y*DEG2RAD), 0, sin(rotation.y * DEG2RAD));
|
||||
up = cross(right, forward);
|
||||
forward = Vec3f(sin(rotation.y * DEG2RAD), -sin(rotation.x * DEG2RAD), -cosf(rotation.y*DEG2RAD) * cosf(rotation.x*DEG2RAD)).normalize();
|
||||
right = Vec3f(cos(rotation.y*DEG2RAD), 0, sin(rotation.y * DEG2RAD)).normalize();
|
||||
up = cross(right, forward).normalize();
|
||||
}
|
||||
|
||||
Matrix Camera::GetModelViewMatrix() {
|
||||
Vec3f center = position + forward;
|
||||
Vec3f z = (position - center).normalize();
|
||||
Vec3f x = cross(up, z).normalize();
|
||||
Vec3f y = cross(z, x).normalize();
|
||||
Vec3f z = forward * -1;
|
||||
Matrix Minv = Matrix::identity();
|
||||
Matrix Tr = Matrix::identity();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Minv[0][i] = x[i];
|
||||
Minv[1][i] = y[i];
|
||||
Minv[0][i] = right[i];
|
||||
Minv[1][i] = up[i];
|
||||
Minv[2][i] = z[i];
|
||||
Tr[i][3] = -center[i];
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
void move_camera_right();
|
||||
void move_camera_forward();
|
||||
void move_camera_backward();
|
||||
void rise();
|
||||
void fall();
|
||||
|
||||
void ApplyChanges();
|
||||
Matrix GetModelViewMatrix();
|
||||
|
||||
@@ -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
|
||||
@@ -11,6 +11,8 @@ const int screen_height = 1000;
|
||||
int prev_mouse_x = screen_width/2;
|
||||
int prev_mouse_y = screen_height/2;
|
||||
|
||||
float TIME = 0;
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
HWND hwnd;
|
||||
@@ -52,11 +54,16 @@ bool HandleButtonPressed() {
|
||||
camera.move_camera_right();
|
||||
if (GetAsyncKeyState(VK_LEFT) & 0x8000)
|
||||
camera.move_camera_left();
|
||||
if (GetAsyncKeyState(VK_SPACE) & 0x8000)
|
||||
camera.rise();
|
||||
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
|
||||
camera.fall();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CALLBACK FixedUpdate(HWND hwnd, UINT message, UINT uInt, DWORD dWord)
|
||||
{
|
||||
TIME += 0.167;
|
||||
HandleButtonPressed();
|
||||
camera.ApplyChanges();
|
||||
render();
|
||||
|
||||
@@ -48,7 +48,7 @@ Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffus
|
||||
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
|
||||
load_texture(filename, "_diffuse.tga", diffusemap_);
|
||||
load_texture(filename, "_nm_tangent.tga", normalmap_);
|
||||
//load_texture(filename, "_spec.tga", specularmap_);
|
||||
load_texture(filename, "_spec.tga", specularmap_);
|
||||
}
|
||||
|
||||
Model::~Model() {}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
+67
-213
@@ -1,199 +1,35 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include "tgaimage.h"
|
||||
#include "model.h"
|
||||
#include "geometry.h"
|
||||
#include "model.h"
|
||||
#include "renderer.h"
|
||||
#include "util_window.h"
|
||||
#include <ctime>
|
||||
#include "camera.h"
|
||||
#include "util_renderer.h"
|
||||
#include "colladamodel.h"
|
||||
|
||||
#define HORIZONTAL_CAMERA_SPEED 0.1
|
||||
#define VERTICAL_CAMERA_SPEED 0.1
|
||||
#define HORIZONTAL_CAMERA_SPEED 0.1
|
||||
#define VERTICAL_CAMERA_SPEED 0.1
|
||||
#define VERTICAL_CAMERA_CLAMP_UP 90
|
||||
#define VERTICAL_CAMERA_CLAMP_DOWN -90
|
||||
#define NEAR_CLIP_PLANE 0
|
||||
#define FAR_CLIP_PLANE 15
|
||||
#define FAR_CLIP_PLANE 10
|
||||
#define FOV 30
|
||||
#define DEFAULT_CAMERA_POS Vec3f(0, 0, 5)
|
||||
#define DEFAULT_CAMERA_ROT Vec3f(0, 0, 0)
|
||||
#define CAMERA_MOVEMENT_SPEED 1.f
|
||||
#define CAMERA_MOVEMENT_SPEED 0.05f
|
||||
#define DEFAULT_CAMERA_POS Vec3f(0, 0, 5)
|
||||
#define DEFAULT_CAMERA_ROT Vec3f(0, 0, 0)
|
||||
#define LIGHT_INTENSITY 2.f
|
||||
|
||||
const TGAColor white = TGAColor(255, 255, 255, 255);
|
||||
const TGAColor red = TGAColor(255, 0, 0, 255);
|
||||
const TGAColor green = TGAColor(0, 255, 0, 255);
|
||||
const TGAColor blue = TGAColor(0, 0, 255, 255);
|
||||
|
||||
bool wireframe = false;
|
||||
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;
|
||||
|
||||
float* z_buffer = new float[screen_width * screen_height];
|
||||
Vec3f light_dir = Vec3f(0, 0, 1).normalize();
|
||||
|
||||
Matrix viewport(int x, int y, int w, int h) {
|
||||
Matrix m = Matrix::identity();
|
||||
m[0][3] = x + w / 2.f;
|
||||
m[1][3] = y + h / 2.f;
|
||||
m[2][3] = (FAR_CLIP_PLANE-NEAR_CLIP_PLANE) / 2.f;
|
||||
|
||||
m[0][0] = w / 2.f;
|
||||
m[1][1] = h / 2.f;
|
||||
m[2][2] = (FAR_CLIP_PLANE+NEAR_CLIP_PLANE) / 2.f;
|
||||
return m;
|
||||
}
|
||||
|
||||
void line(Vec3f p0, Vec3f p1, TGAColor color)
|
||||
{
|
||||
bool steep = false;
|
||||
|
||||
if (std::abs(p0[0] - p1[0]) < std::abs(p0[1] - p1[1])) {
|
||||
std::swap(p0[0], p0[1]);
|
||||
std::swap(p1[0], p1[1]);
|
||||
steep = true;
|
||||
|
||||
}
|
||||
|
||||
if (p0[0] > p1[0]) {
|
||||
std::swap(p0[0], p1[0]);
|
||||
std::swap(p0[1], p1[1]);
|
||||
}
|
||||
|
||||
int dx = p1[0] - p0[0];
|
||||
int dy = p1[1] - p0[1];
|
||||
int derror2 = std::abs(dy) * 2;
|
||||
int error2 = 0;
|
||||
int y = p0[1];
|
||||
int y_step = p1[1] > p0[1] ? 1 : -1;
|
||||
int dx_2 = 2 * dx;
|
||||
|
||||
for (int x = p0[0]; x <= p1[0]; x++) {
|
||||
if (steep) {
|
||||
set_pixel(y, x, color_to_int(color));
|
||||
}
|
||||
else {
|
||||
set_pixel(x, y, color_to_int(color));
|
||||
}
|
||||
error2 += derror2;
|
||||
if (error2 > dx) {
|
||||
y += (y_step);
|
||||
error2 -= dx_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f barycentric(Vec3f* pts, Vec3f P)
|
||||
{
|
||||
Vec3f u = cross(
|
||||
Vec3f(pts[2][0] - pts[0][0], pts[1][0] - pts[0][0], pts[0][0] - P[0]), // AC_x, AB_x, distance_x
|
||||
Vec3f(pts[2][1] - pts[0][1], pts[1][1] - pts[0][1], pts[0][1] - P[1]) // AC_y, AB_y, distance_y
|
||||
);
|
||||
|
||||
if (std::abs(u[2]) < 1) return Vec3f(-1, 1, 1);
|
||||
return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
|
||||
}
|
||||
|
||||
|
||||
void triangle(
|
||||
Vec3f* pts, // Needed
|
||||
Vec2f* diff_pts, // Should be removed
|
||||
Model* model,
|
||||
float* intensities)
|
||||
{
|
||||
|
||||
if (pts[0].y == pts[1].y && pts[0].y == pts[2].y) return; // i dont care about degenerate triangles
|
||||
if (pts[0].y > pts[1].y) {
|
||||
std::swap(pts[0], pts[1]);
|
||||
if(diff_pts)
|
||||
std::swap(diff_pts[0], diff_pts[1]);
|
||||
if(intensities)
|
||||
std::swap(intensities[0], intensities[1]);
|
||||
}
|
||||
if (pts[0].y > pts[2].y) {
|
||||
std::swap(pts[0], pts[2]);
|
||||
if(diff_pts)
|
||||
std::swap(diff_pts[0], diff_pts[2]);
|
||||
if(intensities)
|
||||
std::swap(intensities[0], intensities[2]);
|
||||
}
|
||||
if (pts[1].y > pts[2].y) {
|
||||
std::swap(pts[1], pts[2]);
|
||||
if(diff_pts)
|
||||
std::swap(diff_pts[1], diff_pts[2]);
|
||||
if(intensities)
|
||||
std::swap(intensities[1], intensities[2]);
|
||||
}
|
||||
|
||||
if (wireframe)
|
||||
{
|
||||
line(pts[0], pts[1], white);
|
||||
line(pts[1], pts[2], white);
|
||||
line(pts[2], pts[0], white);
|
||||
return;
|
||||
}
|
||||
|
||||
Vec2i bounding_box_min(screen_width - 1, screen_height - 1);
|
||||
Vec2i bounding_box_max(0, 0);
|
||||
Vec2i clamp(screen_width - 1, screen_height - 1);
|
||||
TGAColor color = white;
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
bounding_box_min[j] = std::fmax(0, std::fmin(bounding_box_min[j], (int)pts[i][j]));
|
||||
bounding_box_max[j] = std::fmin(clamp[j], std::fmax(bounding_box_max[j], (int)pts[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f P;
|
||||
#pragma omp parallel for
|
||||
for (P.x = bounding_box_min.x; P.x <= bounding_box_max.x; P.x++) {
|
||||
for (P.y = bounding_box_min.y; P.y <= bounding_box_max.y; P.y++) {
|
||||
Vec3f bc_coord = barycentric(pts, P);
|
||||
if (bc_coord.x < 0 || bc_coord.y < 0 || bc_coord.z < 0) continue;
|
||||
|
||||
|
||||
float intensity =
|
||||
intensities[0]
|
||||
+ (intensities[1] - intensities[0]) * bc_coord[1]
|
||||
+ (intensities[2] - intensities[0]) * bc_coord[2];
|
||||
|
||||
|
||||
// Interpolating Z using the barycentric coordinates
|
||||
P.z = 0;
|
||||
for (int i = 0; i < 3; i++) P.z += pts[i][2] * bc_coord[i];
|
||||
|
||||
// Coloring according to the Z-Buffer
|
||||
if (P.z > z_buffer[(int)(P.x + P.y * screen_width)] && P.z > 0)
|
||||
{
|
||||
z_buffer[(int)(P.x + P.y * screen_width)] = P.z;
|
||||
|
||||
// If diff_pts (Diffusemap Points) were passed, then find the
|
||||
// color of the current pixel
|
||||
if (diff_pts) {
|
||||
Vec2f diff_pt =
|
||||
diff_pts[0]
|
||||
+ (diff_pts[1] - diff_pts[0]) * bc_coord[1]
|
||||
+ (diff_pts[2] - diff_pts[0]) * bc_coord[2];
|
||||
|
||||
color = model->diffuse(diff_pt);
|
||||
}
|
||||
color = color * intensity;
|
||||
set_pixel(P.x, P.y, color_to_int(color));
|
||||
//char debugStr[200];
|
||||
//sprintf_s(debugStr, "%f\n", P.z);
|
||||
//OutputDebugString(debugStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int color_to_int(TGAColor col) {
|
||||
return (col[2] << 16) | (col[1] << 8) | col[0];
|
||||
}
|
||||
Vec3f light_dir = Vec3f(1, 1, 1).normalize();
|
||||
|
||||
void init_camera() {
|
||||
camera.SetPosition(DEFAULT_CAMERA_POS);
|
||||
@@ -212,52 +48,70 @@ void init_camera() {
|
||||
void clear_zbuffer()
|
||||
{
|
||||
for (int i = 0; i < screen_width * screen_height; i++)
|
||||
z_buffer[i] = INT_MIN;
|
||||
z_buffer[i] = 0;
|
||||
}
|
||||
|
||||
Matrix ViewPort = Matrix::identity();
|
||||
Matrix Projection = Matrix::identity();
|
||||
Matrix ModelView = Matrix::identity();
|
||||
|
||||
struct TextureShader : public IShader {
|
||||
mat<2, 3, float> varying_uv_coords;
|
||||
Matrix uniform_mit;
|
||||
Matrix uniform_m;
|
||||
|
||||
virtual Vec4f vertex(int iface, int nthvert) {
|
||||
varying_uv_coords.set_col(nthvert, model->uv(iface, nthvert));
|
||||
Vec4f gl_Vertex = embed<4>(model->vertix(iface, nthvert));
|
||||
return ViewPort * Projection * ModelView * gl_Vertex; // transform it to screen coordinates
|
||||
}
|
||||
|
||||
virtual bool fragment(Vec3f bar, TGAColor &color) {
|
||||
Vec2f uv = varying_uv_coords * bar;
|
||||
Vec3f normal = Vec3f(uniform_mit * Vec4f(model->normal(uv))).normalize();
|
||||
Vec3f light = Vec3f(uniform_m * Vec4f(light_dir)).normalize();
|
||||
Vec3f reflection = (normal * (normal*light*2.f) - light).normalize();
|
||||
float spec_intensity = pow(std::fmax(reflection.z, 0.f), model->specular(uv));
|
||||
float diff_intensity = std::fmax(0.f, (normal*light));
|
||||
TGAColor c = model->diffuse(uv);
|
||||
color = c;
|
||||
for (int i = 0; i < 3; i++)
|
||||
color[i] = std::fmin(1 + c[i] * (diff_intensity + 0.8 * spec_intensity), 255) * LIGHT_INTENSITY;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void render()
|
||||
{
|
||||
light_dir = camera.GetForward() * -1;
|
||||
ViewPort = viewport(0, 0, screen_width, screen_height);
|
||||
Projection = camera.GetProjectionMatrix();
|
||||
ModelView = camera.GetModelViewMatrix();
|
||||
{
|
||||
//light_dir = camera.GetForward().normalize() * -1;
|
||||
}
|
||||
|
||||
Matrix z = ViewPort * Projection * ModelView * model->Transform;
|
||||
{
|
||||
viewport(0, 0, screen_width, screen_height, FAR_CLIP_PLANE, NEAR_CLIP_PLANE);
|
||||
Projection = camera.GetProjectionMatrix();
|
||||
ModelView = camera.GetModelViewMatrix();
|
||||
}
|
||||
|
||||
|
||||
//Matrix z = ViewPort * Projection * ModelView * model->Transform;
|
||||
|
||||
clear_zbuffer();
|
||||
TextureShader shader;
|
||||
shader.uniform_m = (Projection);
|
||||
shader.uniform_mit = (Projection).invert_transpose();
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < model->nfaces(); i++)
|
||||
{
|
||||
std::vector<int> face = model->face(i);
|
||||
Vec3f screen_coords[3];
|
||||
Vec3f world_coords[3];
|
||||
Vec2f diffuse_coords[3];
|
||||
float intensities[3];
|
||||
for (int i = 0; i < model->nfaces(); i++) {
|
||||
Vec4f screen_coords[3];
|
||||
bool out = true;
|
||||
#pragma omp parallel for
|
||||
for (int j = 0; j < 3; j++) {
|
||||
screen_coords[j] = shader.vertex(i, j);
|
||||
Vec3f screen3(screen_coords[j]);
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
Vec3f v = model->vert(face[j]);
|
||||
Vec4f v4(v);
|
||||
Vec3f coord(z * v4);
|
||||
|
||||
if (coord.x > 0 && coord.x < screen_width
|
||||
&& coord.y > 0 && coord.y < screen_height)
|
||||
out = false;
|
||||
|
||||
screen_coords[j] = coord;
|
||||
world_coords[j] = v;
|
||||
diffuse_coords[j] = model->uv(i, j);
|
||||
intensities[j] = model->normal(i, j) * light_dir;
|
||||
if (screen3.x > 0 && screen3.x < screen_width && screen3.y > 0 && screen3.y < screen_height) out = false;
|
||||
}
|
||||
|
||||
if (out) continue;
|
||||
|
||||
triangle(screen_coords, diffuse_coords, model, intensities);
|
||||
if(!out)
|
||||
triangle(screen_coords, shader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
extern float* z_buffer;
|
||||
extern Camera camera;
|
||||
extern float TIME;
|
||||
|
||||
void init_camera();
|
||||
void render();
|
||||
|
||||
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
@@ -0,0 +1,73 @@
|
||||
#include "util_renderer.h"
|
||||
#include "util_window.h"
|
||||
|
||||
IShader::~IShader() {}
|
||||
|
||||
float* z_buffer = new float[screen_width * screen_height];
|
||||
|
||||
void viewport(int x, int y, int w, int h, int far_plane, int near_plane) {
|
||||
ViewPort[0][3] = x + w / 2.f;
|
||||
ViewPort[1][3] = y + h / 2.f;
|
||||
ViewPort[2][3] = (far_plane-near_plane) / 2.f;
|
||||
|
||||
ViewPort[0][0] = w / 2.f;
|
||||
ViewPort[1][1] = h / 2.f;
|
||||
ViewPort[2][2] = (far_plane+near_plane) / 2.f;
|
||||
}
|
||||
|
||||
int color_to_int(TGAColor col) {
|
||||
return (col[2] << 16) | (col[1] << 8) | col[0];
|
||||
}
|
||||
|
||||
Vec3f barycentric(Vec3f* pts, Vec3f P)
|
||||
{
|
||||
Vec3f u = cross(
|
||||
Vec3f(pts[2][0] - pts[0][0], pts[1][0] - pts[0][0], pts[0][0] - P[0]), // AC_x, AB_x, distance_x
|
||||
Vec3f(pts[2][1] - pts[0][1], pts[1][1] - pts[0][1], pts[0][1] - P[1]) // AC_y, AB_y, distance_y
|
||||
);
|
||||
|
||||
if (std::abs(u[2]) < 1) return Vec3f(-1, 1, 1);
|
||||
return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
|
||||
}
|
||||
|
||||
void triangle( Vec4f* pts, IShader &shader)
|
||||
{
|
||||
Vec3f pts3[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
pts3[i] = Vec3f(pts[i]);
|
||||
|
||||
if (pts3[0].y == pts3[1].y && pts3[0].y == pts3[2].y) return; // i dont care about degenerate triangles
|
||||
//if (pts3[0].y > pts3[1].y) { std::swap(pts3[0], pts3[1]); }
|
||||
//if (pts3[0].y > pts3[2].y) { std::swap(pts3[0], pts3[2]); }
|
||||
//if (pts3[1].y > pts3[2].y) { std::swap(pts3[1], pts3[2]); }
|
||||
|
||||
Vec2i bounding_box_min(screen_width - 1, screen_height - 1);
|
||||
Vec2i bounding_box_max(0, 0);
|
||||
Vec2i clamp(screen_width - 1, screen_height - 1);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 2; j++) {
|
||||
bounding_box_min[j] = std::fmax(0, std::fmin(bounding_box_min[j], (int)pts3[i][j]));
|
||||
bounding_box_max[j] = std::fmin(clamp[j], std::fmax(bounding_box_max[j], (int)pts3[i][j]));
|
||||
}
|
||||
|
||||
|
||||
Vec3i P;
|
||||
#pragma omp parallel for
|
||||
for (P.x = bounding_box_min.x; P.x <= bounding_box_max.x; P.x++) {
|
||||
for (P.y = bounding_box_min.y; P.y <= bounding_box_max.y; P.y++) {
|
||||
Vec3f bc_coord = barycentric(pts3, P);
|
||||
float frag_depth = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
frag_depth += pts3[i][2] * bc_coord[i];
|
||||
if (bc_coord.x < 0 || bc_coord.y < 0 || bc_coord.z < 0 || z_buffer[ P.x + P.y * screen_width ]>frag_depth) continue;
|
||||
TGAColor color;
|
||||
bool discard = shader.fragment(bc_coord, color);
|
||||
if (!discard) {
|
||||
z_buffer[P.x + P.y * screen_width] = frag_depth;
|
||||
set_pixel(P.x, P.y, color_to_int(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "tgaimage.h"
|
||||
#include "model.h"
|
||||
#include "geometry.h"
|
||||
|
||||
extern Matrix ModelView;
|
||||
extern Matrix ViewPort;
|
||||
extern Matrix Projection;
|
||||
|
||||
void viewport(int x, int y, int w, int h, int far, int near);
|
||||
|
||||
struct IShader {
|
||||
virtual ~IShader();
|
||||
virtual Vec4f vertex(int iface, int nthvert) = 0;
|
||||
virtual bool fragment(Vec3f bar, TGAColor &color) = 0;
|
||||
};
|
||||
|
||||
//void triangle(Vec4f *pts, IShader &shader, TGAImage &image, TGAImage &zbuffer);
|
||||
|
||||
//void triangle( Vec3f* pts, Vec2f* diff_pts, Model* model, float* intensities)
|
||||
|
||||
void triangle(Vec4f* pts, IShader &shader);
|
||||
Reference in New Issue
Block a user