@@ -1,17 +1,20 @@
#include "Animator.h"


#include "AssortedUtils.h"

Animator::Animator(AnimatedModel* pModel)
{
m_pModel = pModel;
m_currentMatrices.resize(m_pModel->m_Skeleton.m_joints.size());
m_jointCount = m_pModel->m_Skeleton.m_joints.size();
m_currentMatrices = new glm::mat4[m_jointCount];
m_modelSpaceTransforms = new glm::mat4[m_jointCount];
m_currentTime = 0;
}


Animator::~Animator()
{
delete m_currentMatrices;
}

//void Animator::PlayAnimation(string name, maybe enum, bool loop, speed?);
@@ -29,27 +32,91 @@ void Animator::GetNextPose()
{
// current animation
Animation anim = m_pModel->m_Skeleton.m_animations[0];
anim.loop = true;
m_currentTime = fmodf(m_currentTime, anim.duration);

// Get closest 2 keyframes from animation
//TODO handle 1 frame and past duration!

int prev = 0;
int next = 1;
while (next < anim.keyframes.size())
if (anim.keyframes.size() < 2)
{
if (anim.keyframes[prev].timestamp < m_currentTime && anim.keyframes[next].timestamp > m_currentTime)
break;

prev++;
next++;
std::cout << "one frame animation - should do something about this" << std::endl;
next = 0;
}
else
{
while (prev < anim.keyframes.size() - 1)
{
if (m_currentTime < anim.keyframes[prev+1].timestamp)
break;

prev++;
}
next = prev + 1;
if (anim.loop)
next = next % anim.keyframes.size();

}
//if (next > anim.keyframes.size())
//{
// // animation is complete
// next = anim.keyframes.size() - 1;
// prev = anim.keyframes.size() - 1; // this is wrong i think
//}

// Interploate between 2 keyframes across all joint poses
float difference = anim.keyframes[next].timestamp - anim.keyframes[prev].timestamp;
float t = m_currentTime - anim.keyframes[prev].timestamp;



// create array of matrices from joint poses
float alpha = t / difference;

for (int i = 0; i < m_jointCount; i++)
{
glm::mat4 jointTransform; // the local transform for this joint
if (anim.jointsUsed[i])
{

glm::vec3 interpos = anim.keyframes[prev].jointPoses[i].position * (1 - alpha)
+ anim.keyframes[next].jointPoses[i].position * alpha;

glm::vec3 interscale = anim.keyframes[prev].jointPoses[i].scale * (1 - alpha)
+ anim.keyframes[next].jointPoses[i].scale * alpha;

glm::quat interrot = glm::lerp(anim.keyframes[prev].jointPoses[i].rotation,
anim.keyframes[next].jointPoses[i].rotation,
alpha);

glm::mat4 transMat = glm::translate(glm::mat4(1.0f), interpos);
glm::mat4 rotationMat = glm::mat4_cast(interrot);
glm::mat4 scaleMat = glm::scale(glm::mat4(1.0f), interscale);

jointTransform = transMat * rotationMat * scaleMat;
}
else
{
// this joint isn't included in the animation, so it's just bind pose
jointTransform = m_pModel->m_Skeleton.m_joints[i].m_localBindTransform;
}

int parentIndex = m_pModel->m_Skeleton.m_joints[i].m_parentIndex;
glm::mat4 parentMat;
if (parentIndex >= 0)
parentMat = m_modelSpaceTransforms[parentIndex];
else
parentMat = glm::mat4(1.0f);

m_modelSpaceTransforms[i] = parentMat * jointTransform;

glm::mat4 finalTransform = m_pModel->m_Skeleton.m_globalInverseBindTransform
* m_modelSpaceTransforms[i]
* m_pModel->m_Skeleton.m_joints[i].m_modelBindTransform;

//std::cout << "used: " << anim.jointsUsed[i] << " ";
//print_matrix(to_string(i).c_str(), finalTransform);


m_currentMatrices[i] = finalTransform;
}

// draw something with the matrices
}
@@ -15,7 +15,8 @@ class Animator
AnimatedModel* m_pModel;
map<std::string, int> m_animationMap;

vector<glm::mat4> m_currentMatrices;
int m_jointCount;
glm::mat4* m_currentMatrices;

Animator(AnimatedModel* pModel);
~Animator();
@@ -24,6 +25,6 @@ class Animator

private:
float m_currentTime;

glm::mat4* m_modelSpaceTransforms;
void GetNextPose();
};
@@ -6,43 +6,11 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp>
//#include <glm/gtx/matrix_decompose.hpp>

#include <assimp/scene.h>


// copy from Row-major to Column major matrix
// i.e. from aiMatrix4x4 to glm::mat4
template <typename RM, typename CM>
void AssToGlmMat4(const RM& from, CM& to)
{
to[0][0] = from.a1; to[1][0] = from.a2;
to[2][0] = from.a3; to[3][0] = from.a4;
to[0][1] = from.b1; to[1][1] = from.b2;
to[2][1] = from.b3; to[3][1] = from.b4;
to[0][2] = from.c1; to[1][2] = from.c2;
to[2][2] = from.c3; to[3][2] = from.c4;
to[0][3] = from.d1; to[1][3] = from.d2;
to[2][3] = from.d3; to[3][3] = from.d4;
}
glm::mat4 GetGlmMat4FromAssimp(aiMatrix4x4 from);

void print_matrix(std::string name, glm::mat4 mat)
{
float dArray[16] = { 0.0 };
const float *pSource = (const float*)glm::value_ptr(mat);
for (int i = 0; i < 16; ++i)
dArray[i] = pSource[i];

std::cout << name << ":" << std::endl;
std::cout << std::fixed;
std::cout << std::setprecision(2);
for (int i = 0; i < 4; i++)
{
std::cout << "[ ";
for (int j = 0; j < 4; j++)
{
if (pSource[i + j * 4] >= 0)
std::cout << " ";
std::cout << pSource[i + j * 4] << " ";
}
std::cout << "]" << std::endl;
}
}
void print_matrix(std::string name, glm::mat4 mat);
@@ -19,7 +19,7 @@ Camera::~Camera()
}

// premultiply model by this matrix
glm::mat4 Camera::GetViewProjectionMatrix()
glm::mat4 Camera::GetProjectionViewMatrix()
{
glm::mat4 view = glm::lookAt(transform.position, transform.position + transform.Forward(), WORLD_UP);
glm::mat4 projection;
@@ -38,6 +38,6 @@ class Camera
Camera(bool orthographic = false);
~Camera();

glm::mat4 GetViewProjectionMatrix();
glm::mat4 GetProjectionViewMatrix();
};

@@ -17,7 +17,10 @@ namespace ngine
const GLchar* fragmentShaderPath = "./Shaders/shader.fs";

const GLchar* lightingTestVertexShaderPath = "./Shaders/lightingTestShader.vs";
const GLchar* lightingTestFragmentShaderPath = "./Shaders/lightingtestShader.fs";
const GLchar* lightingTestFragmentShaderPath = "./Shaders/lightingTestShader.fs";

const GLchar* animVertexShaderPath = "./Shaders/animShader.vs";
// anim fragment shader is just lightingTestFShader for now

const GLchar* lightVertexShaderPath = "./Shaders/lightShader.vs";
const GLchar* lightFragmentShaderPath = "./Shaders/lightShader.fs";
@@ -28,7 +31,7 @@ namespace ngine

const char* bearPath = "./Models/bear/bear.fbx";
//const char* bearPath = "./Models/bear/mayabear.obj";
const char* bninjaPath = "./Models/bninja/bnin_baked-tran_optimized-anim.dae";
const char* bninjaPath = "./Models/bninja/bnin_full-body-anim_WITH-relative-path.dae";

const char* cubeModelPath = "./Models/cube/cube.obj";
//const char* modelPath = "./Models/nanosuit/nanosuit.obj";
@@ -80,6 +80,12 @@ class Shader
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}

void SetMat4Array(const std::string &name, const glm::mat4 &mat, GLsizei count) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), count, GL_FALSE, &mat[0][0]);
}

#pragma endregion setter_functions

};
@@ -6,6 +6,7 @@

#include "EngineGlobals.h"
#include "GameTime.h"
#include "AssortedUtils.h"

#include "Display.h"
#include "EventHandler.h"
@@ -21,6 +22,7 @@
#include "AnimatedModel.h"
#include "Animator.h"


// Macro for indexing vertex buffer (just forwards the value you give it)
#define BUFFER_OFFSET(i) ((char *)NULL + (i))

@@ -174,6 +176,7 @@ int main(int argc, char* argv[])
Shader shader(vertexShaderPath, fragmentShaderPath);
Shader lightingTestShader(lightingTestVertexShaderPath, lightingTestFragmentShaderPath);
Shader lightShader(lightVertexShaderPath, lightFragmentShaderPath);
Shader animShader(animVertexShaderPath, lightingTestFragmentShaderPath);

SATexture otherTexture(otherTexturePath);
SATexture myTexture(texturePath);
@@ -250,19 +253,12 @@ int main(int argc, char* argv[])
#pragma region camera_init

Camera mainCamera;
mainCamera.farClipDistance = 100000;
CameraController camController(&mainCamera, &input);

//mainCamera.orthographic = true;
//camController.constrainPitch = false;

Camera cam2;
cam2.orthographic = true;
Camera cam3;
cam3.fov = 120.0f;

Camera cam4;

cam2.orthographic = true;


#pragma endregion camera_init
@@ -352,7 +348,7 @@ int main(int argc, char* argv[])

glPolygonMode(GL_FRONT, GL_FILL);

glm::mat4 pv = mainCamera.GetViewProjectionMatrix();
glm::mat4 pv = mainCamera.GetProjectionViewMatrix();

// Draw the light
lightShader.Use();
@@ -382,7 +378,7 @@ int main(int argc, char* argv[])
mvp = pv * floor.GetMatrix();
lightingTestShader.SetMat4("mvp", mvp);
lightingTestShader.SetMat4("model", floor.GetMatrix());
//cube.Draw(lightingTestShader);
cube.Draw(lightingTestShader);

lightingTestShader.SetVec3("material.ambient", 0.1f, 0.1f, 0.4f);
// rotating cube
@@ -399,26 +395,59 @@ int main(int argc, char* argv[])
//bninjaModel.Draw(lightingTestShader);

Transform scaler;
scaler.scale *= 0.01f;
scaler.scale *= 0.001f;
scaler.position = glm::vec3(0.2f, 0.0f, 0.0f);
// ANIMATION

animShader.Use();
animShader.SetVec3("light.ambient", 0.2f, 0.2f, 0.2f);
animShader.SetVec3("light.diffuse", 0.5f, 0.5f, 0.5f); // darken the light a bit to fit the scene
animShader.SetVec3("light.specular", 1.0f, 1.0f, 1.0f);
animShader.SetVec3("light.position", lightTransform.position);

animShader.SetVec3("viewPos", mainCamera.transform.position);

// all materials are the same for now
animShader.SetVec3("material.ambient", 1, 1, 1);
animShader.SetVec3("material.diffuse", 1, 1, 1);
animShader.SetVec3("material.specular", 1, 1, 1);
animShader.SetFloat("material.shininess", 10.0f);


// investigating skellies
lightingTestShader.SetVec3("material.ambient", 1, 1, 1);
lightingTestShader.SetVec3("material.diffuse", 1, 1, 1);
lightingTestShader.SetVec3("material.specular", 1, 1, 1);


for (int i = 0; i < animModel.m_Skeleton.m_jointCount; i++)
animator.Tick(0.05f);//gameclock.deltaTime);
//animShader.SetMat4Array("joints", animator.m_currentMatrices[0], (GLsizei)animator.m_currentMatrices.size());
for (int i = 0; i < animator.m_jointCount; i++)
{
glm::mat4 modmat = animModel.m_Skeleton.GetModelSpaceBindMatrix(i);
string uniformName = "joints[" + to_string(i) + "]";
int location = glGetUniformLocation(animShader.ID, uniformName.c_str());
glUniformMatrix4fv(location, 1, GL_FALSE, &animator.m_currentMatrices[i][0][0]);


//print_matrix(to_string(i).c_str(), animator.m_currentMatrices[i]);

modmat = modmat * scaler.GetMatrix();
lightingTestShader.SetMat4("mvp", pv * modmat);
lightingTestShader.SetMat4("model", modmat);
cube.Draw(lightingTestShader);
}

animShader.SetMat4("projectionview", pv);
animShader.SetMat4("model", octobeartran.GetMatrix());
animModel.Render();

//for (int i = 0; i < animator.m_jointCount; i++)
//{
// //glm::mat4 modmat = animModel.m_Skeleton.GetModelSpaceBindMatrix(i);
// glm::mat4 modmat = animator.m_currentMatrices[i];
//
// int parentIndex = animModel.m_Skeleton.m_joints[i].m_parentIndex;
// if (parentIndex > -1)
// modmat = animator.m_currentMatrices[parentIndex] * modmat;
//
// animModel.m_Skeleton.m_globalInverseBindTransform;
// modmat = modmat *scaler.GetMatrix();
// animShader.SetMat4("projectionview", pv);
// animShader.SetMat4("model", modmat);
// cube.Draw(animShader);
//}


if (input.GetButton("b_Forward"))
octobeartran.position += octobeartran.Forward() * 0.01f;
@@ -441,10 +470,10 @@ int main(int argc, char* argv[])
nin.rotation.y = -octobeartran.rotation.y + 90.0f;
nin.rotation.x = -octobeartran.rotation.x;// +90.0f;


lightingTestShader.Use();
lightingTestShader.SetMat4("mvp", pv * nin.GetMatrix());
lightingTestShader.SetMat4("model", nin.GetMatrix());
bearModel.Draw(lightingTestShader);
//bearModel.Draw(lightingTestShader);



@@ -473,7 +502,7 @@ int main(int argc, char* argv[])
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // (or whatever buffer you want to clear)
//glDisable(GL_SCISSOR_TEST);

pv = cam4.GetViewProjectionMatrix();
pv = cam4.GetProjectionViewMatrix();

Transform staticLight;
staticLight.position = glm::vec3(0, 0, 0);
@@ -501,7 +530,7 @@ int main(int argc, char* argv[])
mvp = pv * b.GetMatrix();
lightingTestShader.SetMat4("mvp", mvp);
lightingTestShader.SetMat4("model", b.GetMatrix());
bearModel.Draw(lightingTestShader);
//bearModel.Draw(lightingTestShader);

}