9 Commits

Author SHA1 Message Date
Youssef Assem c2882035b5 rest of animation coding
animation , animator , keyframe & quaterions
compiling but not debuged at all
2019-12-17 04:48:20 +02:00
Youssef Assem 23dd149d48 importing data 2019-12-16 02:06:28 +02:00
Youssef Assem 9057c94af9 Joint & Model 2019-12-15 18:43:27 +02:00
mo7sen 8b1546cb54 Added Specular map to the shader 2019-12-10 13:47:08 +02:00
mo7sen 26a7e48784 Adding Shaders and a 'Time' Variable 2019-12-10 01:25:24 +02:00
mo7sen b936db0ce9 Fixing Camera bugs 2019-12-09 12:24:34 +02:00
mo7sen b51c63ea0c Adding a buggy FPS Camera with position and rotation 2019-12-09 05:46:30 +02:00
mo7sen ad56096eb3 Editing the Projection Matrix 2019-12-08 20:57:18 +02:00
mo7sen 2f5437396c Added messed up low performance camera rotation 2019-12-08 18:47:16 +02:00
32 changed files with 2943 additions and 420 deletions
-3
View File
@@ -13,9 +13,6 @@
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
# Mono auto generated files
mono_crash.*
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
+131 -12
View File
@@ -6,7 +6,7 @@
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846
#define DEG2RAD PI/180 #define DEG2RAD PI/180
ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normals_() ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normals_(), rootjoint()
{ {
Transform = Matrix::identity(); Transform = Matrix::identity();
Rotation = Matrix::identity(); Rotation = Matrix::identity();
@@ -15,11 +15,14 @@ ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normal
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
doc.LoadFile(filename); doc.LoadFile(filename);
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////faces////////////////////////////////////////////////// ////////////////////////////////////////////////faces//////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
face_count = 0; face_count = 0;
tinyxml2::XMLElement* xml_face = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("triangles"); tinyxml2::XMLElement* xml_face = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement()->FirstChildElement()->FirstChildElement("triangles");
xml_face->QueryIntAttribute("count", &face_count); //get count xml_face->QueryIntAttribute("count", &face_count); //get count
std::stringstream str_triangle(xml_face->FirstChildElement("p")->GetText()); //get values as a string std::stringstream str_triangle(xml_face->FirstChildElement("p")->GetText()); //get values as a string
@@ -54,7 +57,7 @@ ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normal
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////normal//////////////////////////////////////////////////// /////////////////////////////////////////////normal////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
normal_count = 0; int normal_count = 0;
tinyxml2::XMLElement* xml_normal = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("source")->NextSiblingElement()->FirstChildElement("float_array"); 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); xml_normal->QueryIntAttribute("count", &normal_count);
std::stringstream str_normal(xml_normal->GetText()); std::stringstream str_normal(xml_normal->GetText());
@@ -68,9 +71,9 @@ ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normal
normals_.push_back(temp); normals_.push_back(temp);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////textcoord/////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////// int texcoord_count = 0;
texcoord_count = 0;
tinyxml2::XMLElement* xml_texture = doc.FirstChildElement("COLLADA")->FirstChildElement("library_geometries")->FirstChildElement("geometry")->FirstChildElement("mesh")->FirstChildElement("source")->NextSiblingElement()->NextSiblingElement()->FirstChildElement("float_array"); 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); xml_texture->QueryIntAttribute("count", &texcoord_count);
std::stringstream str_texcoord(xml_texture->GetText()); std::stringstream str_texcoord(xml_texture->GetText());
@@ -80,20 +83,105 @@ ColladaModel::ColladaModel(const char* filename) : faces_(), vertices_(), normal
Vec2f temp; Vec2f temp;
str_texcoord >> temp.x; str_texcoord >> temp.x;
str_texcoord >> temp.y; str_texcoord >> temp.y;
textureco_.push_back(temp); 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);
} }
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
} }
//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() { ColladaModel::~ColladaModel() {
} }
void ColladaModel::ApplyTransform() { void ColladaModel::ApplyTransform() {
Transform = Translation * Scale * Rotation; Transform = Translation * Scale * Rotation;
} }
void ColladaModel::translate(Vec3f tr) { void ColladaModel::translate(Vec3f tr) {
Translation[0][3] += tr.x; Translation[0][3] += tr.x;
Translation[1][3] += tr.y; Translation[1][3] += tr.y;
@@ -130,11 +218,9 @@ std::vector<int> ColladaModel::face(int idx) {
for (int i = 0; i < (int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]); for (int i = 0; i < (int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
return face; return face;
} }
Vec3f ColladaModel::vertix(int i) { Vec3f ColladaModel::vertix(int i) {
return vertices_[i]; return vertices_[i];
} }
Vec3f ColladaModel::vertix(int iface, int nthvert) { Vec3f ColladaModel::vertix(int iface, int nthvert) {
return vertices_[faces_[iface][nthvert][0]]; return vertices_[faces_[iface][nthvert][0]];
} }
@@ -164,7 +250,7 @@ Vec3f ColladaModel::normal(Vec2f uvf) {
} }
Vec2f ColladaModel::uv(int iface, int nthvert) { Vec2f ColladaModel::uv(int iface, int nthvert) {
return textureco_[faces_[iface][nthvert][2]]; return texturecos_[faces_[iface][nthvert][2]];
} }
float ColladaModel::specular(Vec2f uvf) { float ColladaModel::specular(Vec2f uvf) {
@@ -176,3 +262,36 @@ Vec3f ColladaModel::normal(int iface, int nthvert) {
int idx = faces_[iface][nthvert][1]; int idx = faces_[iface][nthvert][1];
return normals_[idx].normalize(); 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);
}
}
+47 -3
View File
@@ -6,6 +6,9 @@
#include "tinyxml2.h" #include "tinyxml2.h"
#include "geometry.h" #include "geometry.h"
#include "tgaimage.h" #include "tgaimage.h"
#include "joint.h"
#include "animator.h"
#include "animation.h"
#include <cerrno> #include <cerrno>
#include <cstdlib> #include <cstdlib>
@@ -21,13 +24,41 @@ class ColladaModel {
private: private:
int face_count; int face_count;
int vertex_count; int vertex_count;
int normal_count; int joint_count;
int texcoord_count;
Joint rootjoint;
int rootindex=0;
char* rootname;
Matrix root_transform;
//Animator animator;
std::vector<std::vector<Vec3i> > faces_; //vertex/normal/uv std::vector<std::vector<Vec3i> > faces_; //vertex/normal/uv
std::vector<Vec3f> vertices_; std::vector<Vec3f> vertices_;
std::vector<Vec3f> normals_; std::vector<Vec3f> normals_;
std::vector<Vec2f> textureco_; 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 diffusemap_;
TGAImage normalmap_; TGAImage normalmap_;
@@ -35,6 +66,7 @@ private:
void load_texture(std::string filename, const char* suffix, TGAImage& img); void load_texture(std::string filename, const char* suffix, TGAImage& img);
public: public:
ColladaModel() = default;
ColladaModel(const char* filename); ColladaModel(const char* filename);
~ColladaModel(); ~ColladaModel();
@@ -50,6 +82,7 @@ public:
Vec2f uv(int iface, int nthvert); Vec2f uv(int iface, int nthvert);
Matrix Transform; Matrix Transform;
Matrix Rotation; Matrix Rotation;
Matrix Scale; Matrix Scale;
Matrix Translation; Matrix Translation;
@@ -62,5 +95,16 @@ public:
TGAColor diffuse(Vec2f uv); TGAColor diffuse(Vec2f uv);
float specular(Vec2f uv); float specular(Vec2f uv);
std::vector<int> face(int idx); 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 #endif
+36
View File
@@ -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);
}
}
+28
View File
@@ -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);
};
+18 -2
View File
@@ -115,22 +115,38 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ColladaModel.cpp" /> <ClCompile Include="animation.cpp" />
<ClCompile Include="animator.cpp" />
<ClCompile Include="camera.cpp" />
<ClCompile Include="colladamodel.cpp" />
<ClCompile Include="geometry.cpp" /> <ClCompile Include="geometry.cpp" />
<ClCompile Include="joint.cpp" />
<ClCompile Include="jointtransform.cpp" />
<ClCompile Include="keyframe.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="model.cpp" /> <ClCompile Include="model.cpp" />
<ClCompile Include="quaternion.cpp" />
<ClCompile Include="renderer.cpp" /> <ClCompile Include="renderer.cpp" />
<ClCompile Include="tgaimage.cpp" /> <ClCompile Include="tgaimage.cpp" />
<ClCompile Include="tinyxml2.cpp" /> <ClCompile Include="tinyxml2.cpp" />
<ClCompile Include="util_renderer.cpp" />
<ClCompile Include="util_window.cpp" /> <ClCompile Include="util_window.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ColladaModel.h" /> <ClInclude Include="animation.h" />
<ClInclude Include="animator.h" />
<ClInclude Include="colladamodel.h" />
<ClInclude Include="geometry.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="model.h" />
<ClInclude Include="quaternion.h" />
<ClInclude Include="renderer.h" /> <ClInclude Include="renderer.h" />
<ClInclude Include="tgaimage.h" /> <ClInclude Include="tgaimage.h" />
<ClInclude Include="tinyxml2.h" /> <ClInclude Include="tinyxml2.h" />
<ClInclude Include="util_renderer.h" />
<ClInclude Include="util_window.h" /> <ClInclude Include="util_window.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+50 -2
View File
@@ -33,12 +33,36 @@
<ClCompile Include="renderer.cpp"> <ClCompile Include="renderer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ColladaModel.cpp"> <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> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="tinyxml2.cpp"> <ClCompile Include="tinyxml2.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </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>
<ItemGroup> <ItemGroup>
<ClInclude Include="util_window.h"> <ClInclude Include="util_window.h">
@@ -56,11 +80,35 @@
<ClInclude Include="renderer.h"> <ClInclude Include="renderer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ColladaModel.h"> <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> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="tinyxml2.h"> <ClInclude Include="tinyxml2.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </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> </ItemGroup>
</Project> </Project>
File diff suppressed because one or more lines are too long
Binary file not shown.
+17
View File
@@ -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_;
}
+16
View File
@@ -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();
};
+108
View File
@@ -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 (&current_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;
}
+46
View File
@@ -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);
}
}
+121
View File
@@ -0,0 +1,121 @@
#include "camera.h"
Camera::Camera()
{
fov = 30;
position = Vec3f(0, 0, 0);
rotation = Vec3f(0, 0, 0);
up = Vec3f(0, 0, 0);
right = Vec3f(0, 0, 0);
forward = Vec3f(0, 0, 0);
near_plane = 0;
far_plane = 15;
horizontal_camera_speed = 0.5;
vertical_camera_speed = 0.5;
vertical_camera_clamp_up = 90;
vertical_camera_clamp_down = -90;
movement_speed = 1.f;
}
Vec3f Camera::GetForward() {
return forward;
}
void Camera::Move(Vec3f move_vec) {
position = position + move_vec;
}
void Camera::SetPosition(Vec3f pos) {
position = pos;
}
void Camera::Rotate(Vec3f rot_vec) {
rotation = rotation + rot_vec;
}
void Camera::SetRotation(Vec3f rot) {
rotation = rot;
}
void Camera::SetFOV(int angle) {
fov = angle;
}
void Camera::SetVerticalRotSpeed(float speed) {
vertical_camera_speed = speed;
}
void Camera::SetHorizontalRotSpeed(float speed) {
horizontal_camera_speed = speed;
}
void Camera::SetClampRotUp(float angle) {
vertical_camera_clamp_up = angle;
}
void Camera::SetClampRotDown(float angle) {
vertical_camera_clamp_down = angle;
}
void Camera::SetNearPlane(float near_val) {
near_plane = near_val;
}
void Camera::SetFarPlane(float far_val) {
far_plane = far_val;
}
void Camera::rotate_hor(float d_angle) {
rotation.y += d_angle * horizontal_camera_speed;
}
void Camera::rotate_ver(float d_angle) {
rotation.x += d_angle * vertical_camera_speed;
rotation.x = std::fmin(rotation.x, vertical_camera_clamp_up);
rotation.x = std::fmax(rotation.x, vertical_camera_clamp_down);
}
void Camera::move_camera_left() {
position = position - right * movement_speed;
}
void Camera::move_camera_right() {
position = position + right * movement_speed;
}
void Camera::move_camera_forward() {
position = position + forward * movement_speed;
}
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)).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 = forward * -1;
Matrix Minv = Matrix::identity();
Matrix Tr = Matrix::identity();
for (int i = 0; i < 3; i++) {
Minv[0][i] = right[i];
Minv[1][i] = up[i];
Minv[2][i] = z[i];
Tr[i][3] = -center[i];
}
return Minv * Tr;
}
Matrix Camera::GetProjectionMatrix() {
Matrix Projection = Matrix::identity();
Projection[0][0] = 1 / tan(fov * DEG2RAD);
Projection[1][1] = 1 / tan(fov * DEG2RAD);
Projection[2][2] = (far_plane + near_plane) / (far_plane - near_plane);
Projection[2][3] = (-2 * far_plane * near_plane) / (far_plane - near_plane);
Projection[3][2] = -1;
return Projection;
}
+50
View File
@@ -0,0 +1,50 @@
#ifndef __CAMERA_HEADER__
#define __CAMERA_HEADER__
#include "geometry.h"
class Camera {
private:
Vec3f position;
Vec3f rotation;
Vec3f up;
Vec3f right;
Vec3f forward;
float fov;
float near_plane;
float far_plane;
float horizontal_camera_speed;
float vertical_camera_speed;
float vertical_camera_clamp_up;
float vertical_camera_clamp_down;
float movement_speed;
public:
Camera();
void SetPosition(Vec3f pos);
void SetRotation(Vec3f rot);
void Move(Vec3f move_vec);
void Rotate(Vec3f rot_vec);
void SetFOV(int angle);
void SetNearPlane(float near_val);
void SetFarPlane(float far_val);
void SetVerticalRotSpeed(float speed);
void SetHorizontalRotSpeed(float speed);
void SetClampRotUp(float angle);
void SetClampRotDown(float angle);
void SetMovementSpeed(float speed);
Vec3f GetForward();
void rotate_hor(float d_angle);
void rotate_ver(float d_angle);
void move_camera_left();
void move_camera_right();
void move_camera_forward();
void move_camera_backward();
void rise();
void fall();
void ApplyChanges();
Matrix GetModelViewMatrix();
Matrix GetProjectionMatrix();
};
#endif
+3
View File
@@ -1,10 +1,13 @@
#ifndef __GEOMETRY_H__ #ifndef __GEOMETRY_H__
#define __GEOMETRY_H__ #define __GEOMETRY_H__
#define _USE_MATH_DEFINES
#include <cmath> #include <cmath>
#include <vector> #include <vector>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#define DEG2RAD M_PI/180
template<size_t DimCols,size_t DimRows,typename T> class mat; template<size_t DimCols,size_t DimRows,typename T> class mat;
template <size_t DIM, typename T> struct vec { template <size_t DIM, typename T> struct vec {
+34
View File
@@ -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);
}
+24
View File
@@ -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);
};
+17
View File
@@ -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_;
}
+23
View File
@@ -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
+51 -11
View File
@@ -3,26 +3,29 @@
#include "renderer.h" #include "renderer.h"
#include "ctime" #include "ctime"
const int width = 800; const int screen_width = 1000;
const int height = 800; const int screen_height = 1000;
#define TARGET_FRAMERATE 30
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) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ {
HWND hwnd; HWND hwnd;
MSG Msg; MSG Msg;
hwnd = create_window(width, height, hInstance); hwnd = create_window(hInstance);
ShowCursor(false);
ShowWindow(hwnd, nCmdShow); ShowWindow(hwnd, nCmdShow);
char debug_str[100]; init_camera();
clock_t first_time = clock();
render();
clock_t end_time = clock();
Update();
sprintf_s(debug_str, "%f\n", (double)(end_time - first_time) / CLOCKS_PER_SEC); SetTimer(hwnd, NULL, 1000 / TARGET_FRAMERATE, (TIMERPROC)FixedUpdate);
OutputDebugString(debug_str);
while (GetMessage(&Msg, NULL, 0, 0)) while (GetMessage(&Msg, NULL, 0, 0))
{ {
@@ -32,14 +35,51 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return Msg.wParam; return Msg.wParam;
} }
void HandleMouseMovement() {
POINT point;
GetCursorPos(&point);
camera.rotate_hor(point.x - prev_mouse_x);
camera.rotate_ver(point.y - prev_mouse_y);
SetCursorPos(prev_mouse_x, prev_mouse_y);
}
bool HandleButtonPressed() {
if (GetAsyncKeyState(VK_UP) & 0x8000)
camera.move_camera_forward();
if (GetAsyncKeyState(VK_DOWN) & 0x8000)
camera.move_camera_backward();
if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
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();
Update();
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
switch (message) switch (message)
{ {
case WM_MOUSEMOVE:
HandleMouseMovement();
break;
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
break; break;
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
Update();
break; break;
case WM_CLOSE: case WM_CLOSE:
DestroyWindow(hwnd); DestroyWindow(hwnd);
+4 -4
View File
@@ -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; 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, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_); load_texture(filename, "_nm_tangent.tga", normalmap_);
//load_texture(filename, "_spec.tga", specularmap_); load_texture(filename, "_spec.tga", specularmap_);
} }
Model::~Model() {} Model::~Model() {}
@@ -58,9 +58,9 @@ void Model::ApplyTransform() {
} }
void Model::translate(Vec3f tr) { void Model::translate(Vec3f tr) {
Translation[0][3] += tr.x; Translation[0][3] = tr.x;
Translation[1][3] += tr.y; Translation[1][3] = tr.y;
Translation[2][3] += tr.z; Translation[2][3] = tr.z;
} }
void Model::rotate(Vec3f rot) { void Model::rotate(Vec3f rot) {
rot = rot * DEG2RAD; rot = rot * DEG2RAD;
Binary file not shown.
+104
View File
@@ -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;
}
+17
View File
@@ -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);
};
+90 -196
View File
@@ -1,223 +1,117 @@
#define _USE_MATH_DEFINES #include "model.h"
#include <vector>
#include <algorithm>
#include <limits>
#include "tgaimage.h"
#include "model.h"
#include "geometry.h"
#include "renderer.h" #include "renderer.h"
#include "util_window.h" #include "util_window.h"
#include <ctime> #include "camera.h"
#include "ColladaModel.h" #include "util_renderer.h"
#include "colladamodel.h"
#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 10
#define FOV 30
#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 white = TGAColor(255, 255, 255, 255);
const TGAColor red = TGAColor(255, 0, 0, 255); const TGAColor red = TGAColor(255, 0, 0, 255);
const TGAColor green = TGAColor(0, 255, 0, 255); const TGAColor green = TGAColor(0, 255, 0, 255);
const TGAColor blue = TGAColor(0, 0, 255, 255); const TGAColor blue = TGAColor(0, 0, 255, 255);
const int depth = 255; Matrix ViewPort = Matrix::identity();
Matrix ModelView = Matrix::identity();
Matrix Projection = Matrix::identity();
float* z_buffer; ColladaModel* model = new ColladaModel("sssssssssssss.dae");
Vec3f light_dir = Vec3f(0, 0, 1).normalize(); Camera camera;
Vec3f eye(0, 0, 3);
Vec3f center(0, 0, 0);
Matrix viewport(int x, int y, int w, int h) { Vec3f light_dir = Vec3f(1, 1, 1).normalize();
Matrix m = Matrix::identity();
m[0][3] = x + w / 2.f;
m[1][3] = y + h / 2.f;
m[2][3] = depth / 2.f;
m[0][0] = w / 2.f; void init_camera() {
m[1][1] = h / 2.f; camera.SetPosition(DEFAULT_CAMERA_POS);
m[2][2] = depth / 2.f; camera.SetRotation(DEFAULT_CAMERA_ROT);
return m; camera.SetFOV(FOV);
camera.SetNearPlane(NEAR_CLIP_PLANE);
camera.SetFarPlane(FAR_CLIP_PLANE);
camera.SetClampRotDown(VERTICAL_CAMERA_CLAMP_DOWN);
camera.SetClampRotUp(VERTICAL_CAMERA_CLAMP_UP);
camera.SetHorizontalRotSpeed(HORIZONTAL_CAMERA_SPEED);
camera.SetVerticalRotSpeed(VERTICAL_CAMERA_SPEED);
camera.SetMovementSpeed(CAMERA_MOVEMENT_SPEED);
camera.ApplyChanges();
} }
void line(Vec2i p0, Vec2i p1, TGAImage &image, TGAColor color) void clear_zbuffer()
{ {
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) {
image.set(y, x, color);
}
else {
image.set(x, y, 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
ColladaModel* model, // Should be removed
Vec2f* diff_pts, // Should be removed
float* intensities,
Vec3f camera_pos) // Not really sure yet
{
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]);
std::swap(diff_pts[0], diff_pts[1]);
std::swap(intensities[0], intensities[1]);
}
if (pts[0].y > pts[2].y) {
std::swap(pts[0], pts[2]);
std::swap(diff_pts[0], diff_pts[2]);
std::swap(intensities[0], intensities[2]);
}
if (pts[1].y > pts[2].y) {
std::swap(pts[1], pts[2]);
std::swap(diff_pts[1], diff_pts[2]);
std::swap(intensities[1], intensities[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);
TGAColor color = white;
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;
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)])
{
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));
}
}
}
}
int color_to_int(TGAColor col) {
return (col[2] << 16) | (col[1] << 8) | col[0];
}
void init_zbuffer()
{
z_buffer = new float[screen_width*screen_height];
for (int i = 0; i < screen_width * screen_height; i++) for (int i = 0; i < screen_width * screen_height; i++)
z_buffer[i] = INT_MIN; z_buffer[i] = 0;
} }
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) {
Vec3f z = (eye - center).normalize(); struct TextureShader : public IShader {
Vec3f x = cross(up, z).normalize(); mat<2, 3, float> varying_uv_coords;
Vec3f y = cross(z, x).normalize(); Matrix uniform_mit;
Matrix Minv = Matrix::identity(); Matrix uniform_m;
Matrix Tr = Matrix::identity();
for (int i = 0; i < 3; i++) { virtual Vec4f vertex(int iface, int nthvert) {
Minv[0][i] = x[i]; varying_uv_coords.set_col(nthvert, model->uv(iface, nthvert));
Minv[1][i] = y[i]; Vec4f gl_Vertex = embed<4>(model->vertix(iface, nthvert));
Minv[2][i] = z[i]; return ViewPort * Projection * ModelView * gl_Vertex; // transform it to screen coordinates
Tr[i][3] = -center[i];
} }
return Minv * Tr;
} 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() void render()
{ {
ColladaModel* model = new ColladaModel("african_head.dae");
Matrix ViewPort = viewport(screen_width / 8, screen_height / 8, screen_width * 3 / 4, screen_height * 3 / 4);
Matrix Projection = Matrix::identity();
Matrix ModelView = lookat(eye, center, Vec3f(0, 1, 0));
Projection[3][2] = -1.f / (eye - center).norm();
Matrix z = ViewPort * Projection * ModelView * model->Transform;
init_zbuffer();
for (int i = 0; i < model->nfaces(); i++)
{ {
std::vector<int> face = model->face(i); //light_dir = camera.GetForward().normalize() * -1;
Vec3f screen_coords[3]; }
Vec3f world_coords[3];
Vec2f diffuse_coords[3];
float intensities[3];
for (int j = 0; j < 3; j++) {
{ viewport(0, 0, screen_width, screen_height, FAR_CLIP_PLANE, NEAR_CLIP_PLANE);
Vec3f v = model->vertix(face[j]); Projection = camera.GetProjectionMatrix();
Vec4f v4(v); ModelView = camera.GetModelViewMatrix();
Vec3f coord(z * v4); }
screen_coords[j] = coord;
world_coords[j] = v; //Matrix z = ViewPort * Projection * ModelView * model->Transform;
diffuse_coords[j] = model->uv(i, j);
intensities[j] = model->normal(i, j) * light_dir; 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++) {
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]);
if (screen3.x > 0 && screen3.x < screen_width && screen3.y > 0 && screen3.y < screen_height) out = false;
} }
if(!out)
triangle(screen_coords, model, diffuse_coords, intensities, Vec3f(0, 0, 5)); triangle(screen_coords, shader);
} }
} }
+7
View File
@@ -1,7 +1,14 @@
#ifndef RENDERER_HEADER #ifndef RENDERER_HEADER
#define RENDERER_HEADER #define RENDERER_HEADER
#include "tgaimage.h" #include "tgaimage.h"
#include "camera.h"
extern float* z_buffer;
extern Camera camera;
extern float TIME;
void init_camera();
void render(); void render();
int color_to_int(TGAColor col); int color_to_int(TGAColor col);
#endif #endif
File diff suppressed because one or more lines are too long
+73
View File
@@ -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));
}
}
}
}
+22
View File
@@ -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);
+13 -7
View File
@@ -8,8 +8,6 @@ BITMAPINFO info;
HBITMAP hbm; HBITMAP hbm;
const int BITCOUNT_PER_PIXEL = 24; const int BITCOUNT_PER_PIXEL = 24;
const int title_height = 39; const int title_height = 39;
int screen_width = 0;
int screen_height = 0;
long long bytes_per_row; long long bytes_per_row;
bool screen_changed = false; bool screen_changed = false;
HDC hdc; HDC hdc;
@@ -17,15 +15,13 @@ HDRAWDIB hdd;
HDC bitmap_dc; HDC bitmap_dc;
HGDIOBJ old_obj; HGDIOBJ old_obj;
HWND create_window(int width, int height, HINSTANCE &hInstance) { HWND create_window(HINSTANCE &hInstance) {
HWND hWnd; HWND hWnd;
WNDCLASSEX wnd_class = { 0 }; WNDCLASSEX wnd_class = { 0 };
init_wnd_class(wnd_class, hInstance); init_wnd_class(wnd_class, hInstance);
RegisterClassEx(&wnd_class); RegisterClassEx(&wnd_class);
screen_width = width;
screen_height = height;
create_hwnd(hWnd, hInstance); create_hwnd(hWnd, hInstance);
init(hWnd); init(hWnd);
@@ -107,6 +103,16 @@ void set_pixel(unsigned int x, unsigned int y, unsigned int color) {
screen_changed = true; screen_changed = true;
} }
void Update() { void clear_screen() {
DrawDibDraw(hdd, hdc, 0, 0, screen_width, screen_height, &info.bmiHeader, pixels, 0, 0, screen_width, screen_height, 0); for (int x = 0; x < screen_width; x++)
for (int y = 0; y < screen_height; y++)
set_pixel(x, y, 0);
}
void Update() {
if (screen_changed) {
DrawDibDraw(hdd, hdc, 0, 0, screen_width, screen_height, &info.bmiHeader, pixels, 0, 0, screen_width, screen_height, 0);
clear_screen();
screen_changed = false;
}
} }
+4 -3
View File
@@ -18,18 +18,19 @@ extern HDC hdc;
extern HDRAWDIB hdd; extern HDRAWDIB hdd;
extern HDC bitmap_dc; extern HDC bitmap_dc;
extern HGDIOBJ old_obj; extern HGDIOBJ old_obj;
extern int screen_width; extern const int screen_width;
extern int screen_height; extern const int screen_height;
void init(HWND &hWnd); void init(HWND &hWnd);
void destroy_window(); void destroy_window();
HWND create_window(int width, int height, HINSTANCE &hInstance); HWND create_window(HINSTANCE &hInstance);
void create_hwnd(HWND &hwnd, HINSTANCE &hInstance); void create_hwnd(HWND &hwnd, HINSTANCE &hInstance);
void init_wnd_class(WNDCLASSEX &wndClass, HINSTANCE &hInstance); void init_wnd_class(WNDCLASSEX &wndClass, HINSTANCE &hInstance);
void set_pixel(unsigned int x, unsigned int y, unsigned int color); void set_pixel(unsigned int x, unsigned int y, unsigned int color);
void Update(); void Update();
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void CALLBACK FixedUpdate(HWND hwnd, UINT message, UINT uInt, DWORD dWord);
#endif #endif