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
33 changed files with 8460 additions and 240 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/
+297
View File
@@ -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);
}
}
+110
View File
@@ -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
+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);
};
+25 -5
View File
@@ -22,32 +22,32 @@
<VCProjectVersion>15.0</VCProjectVersion> <VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{42971E68-F861-4D45-9DA6-F5E163705584}</ProjectGuid> <ProjectGuid>{42971E68-F861-4D45-9DA6-F5E163705584}</ProjectGuid>
<RootNamespace>OpenWindow</RootNamespace> <RootNamespace>OpenWindow</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
@@ -115,18 +115,38 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<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="util_renderer.cpp" />
<ClCompile Include="util_window.cpp" /> <ClCompile Include="util_window.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<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="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" />
+60
View File
@@ -33,6 +33,36 @@
<ClCompile Include="renderer.cpp"> <ClCompile Include="renderer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<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>
<ItemGroup> <ItemGroup>
<ClInclude Include="util_window.h"> <ClInclude Include="util_window.h">
@@ -50,5 +80,35 @@
<ClInclude Include="renderer.h"> <ClInclude Include="renderer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<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> </ItemGroup>
</Project> </Project>
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);
};
+88 -203
View File
@@ -1,232 +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 "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
Model* 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()
{ {
Model* model = new Model("african_head.obj");
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();
model->rotate(Vec3f(0, 0, 90));
model->scale(Vec3f(0.5, 0.5, 0.5));
model->translate(Vec3f(0.5, 0.5, -1));
model->ApplyTransform();
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++)
{ {
Vec3f v = model->vert(face[j]); viewport(0, 0, screen_width, screen_height, FAR_CLIP_PLANE, NEAR_CLIP_PLANE);
Vec4f v4(v); Projection = camera.GetProjectionMatrix();
Vec3f coord(z * v4); ModelView = camera.GetModelViewMatrix();
screen_coords[j] = coord;
world_coords[j] = v;
diffuse_coords[j] = model->uv(i, j);
intensities[j] = model->normal(i, j) * light_dir;
} }
triangle(screen_coords, model, diffuse_coords, intensities, Vec3f(0, 0, 5));
} //Matrix z = ViewPort * Projection * ModelView * model->Transform;
delete model; 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, 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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+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