0% found this document useful (0 votes)
5 views7 pages

Physicsmodel CPP

/ file PhysicsModel.cpp / author Team42, Jiawei Gu. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited.

Uploaded by

api-316663272
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views7 pages

Physicsmodel CPP

/ file PhysicsModel.cpp / author Team42, Jiawei Gu. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited.

Uploaded by

api-316663272
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

/* Start Header ****************************************************************

*/
/*!
/file [Link]
/author Team42, Jiawei Gu
/e-mail [Link]@[Link]
/date 11/24/2015
/Brief Copyright (C) 2015 DigiPen Institute of Technology. Reproduction or
disclosure of this file or its contents without the prior written consent of
DigiPen Institute of Technology is prohibited.
*/
/* End Header ******************************************************************
*/
#include "PhysicsModel.h"
namespace Anime
{
StickBase::StickBase(const Vector3 & center) :
center(center),
netForce(Vector3::ZERO),
netTorque(Vector3::ZERO),
velocity(Vector3::ZERO),
angularVelocity(Vector3::ZERO)
{}
Vector3 StickBase::GetLeftEnd()
{
return center;
}
Vector3 StickBase::GetRightEnd()
{
return center;
}
Vector3 StickBase::GetCenter()
{
return center;
}
void StickBase::ResetForce()
{
netForce = Vector3::ZERO;
netTorque = Vector3::ZERO;
}
void StickBase::AddForce(const Vector3 & addForce)
{
netForce += addForce;
}
void StickBase::AddTorque(const Vector3 & addTorque)
{
netTorque += addTorque;
}
Stick::Stick(const Vector3 & center, float * length, float * mass, float
* damping) :
StickBase(center),

length(length),
rotationAngle(0),
rotationAxis(Vector3::UNIT_Z),
mass(mass),
moi((*mass) * (*length) * (*length) / 12.0f),
damping(damping)
{}
void Stick::Draw(Shader & shader)
{
Quaternion rot;
[Link](rotationAngle, rotationAxis);
Transform transform(center, rot, Vector3(*length, 1.0f, 1.0f));
glm::mat4 bias = transform.ToMatrix_glm();
glUniformMatrix4fv(glGetUniformLocation([Link](), "bi
as"), 1, GL_FALSE, glm::value_ptr(bias));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
Vector3 Stick::GetLeftEnd()
{
Quaternion rot;
[Link](rotationAngle, rotationAxis);
Transform transform(center, rot, Vector3(*length, 1.0f, 1.0f));
return [Link]() * Vector3(-0.5f, 0.0f, 0.0f);
}
Vector3 Stick::GetRightEnd()
{
Quaternion rot;
[Link](rotationAngle, rotationAxis);
Transform transform(center, rot, Vector3(*length, 1.0f, 1.0f));
return [Link]() * Vector3(0.5f, 0.0f, 0.0f);
}
Spring::Spring() : VAO(0), VBO(0){}
Spring::~Spring()
{
if (VAO != 0)
glDeleteVertexArrays(1, &VAO);
if (VBO != 0)
glDeleteBuffers(1, &VBO);
}
void Spring::Draw(Shader & shader)
{
Vector3 string[2];
string[0] = leftConnection->GetRightEnd();
string[1] = rightConnection->GetLeftEnd();
if (VAO != 0)
glDeleteVertexArrays(1, &VAO);
if (VBO != 0)
glDeleteBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(Vector3), string, GL_ST
ATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(0);
}
void Spring::CalculateForce()
{
Vector3 leftCenter = leftConnection->GetCenter();
Vector3 rightCenter = rightConnection->GetCenter();
Vector3 leftEnd = leftConnection->GetRightEnd();
Vector3 rightEnd = rightConnection->GetLeftEnd();
Vector3 direction = leftEnd - rightEnd;
Vector3 force = ([Link]() / (*normalLength) - 1.0f) *
(*k) * direction;
leftConnection->AddForce(-force);
rightConnection->AddForce(force);
Vector3 leftTorque = (leftEnd - leftCenter).CrossProduct(-force)
;
Vector3 rightTorque = (rightEnd - rightCenter).CrossProduct(forc
e);
leftConnection->AddTorque(leftTorque);
rightConnection->AddTorque(rightTorque);
}
PhysicsModel::PhysicsModel(int bodyNum) :
pinStart(Vector3(0, 0, 0)),
pinEnd(Vector3((bodyNum + 1) * 5.0f + bodyNum * 15.0f, 0.0f, 0.0
f)),
springs(bodyNum + 1),
gravity(0.0f, -100.0f, 0.0f),
damping(0.9900f),
stickLength(15.0f),
stickMass(20.0f),
springLength(5.0f),
springStrength(200.0f),
useRK4(true)
{
[Link](bodyNum);
float gap = 5.0f;
springs[0].leftConnection = &pinStart;
for (int i = 0; i < bodyNum; ++i)
{
bodies.push_back(Stick(Vector3((i + 1) * (gap + stickLen
gth) - stickLength / 2.0f, 0.0f, 0.0f), &stickLength, &stickMass, &damping));
springs[i].rightConnection = &bodies[i];
springs[i + 1].leftConnection = &bodies[i];
springs[i].k = &springStrength;
springs[i].normalLength = &springLength;

}
springs[bodyNum].rightConnection = &pinEnd;
springs[bodyNum].k = &springStrength;
springs[bodyNum].normalLength = &springLength;
}
PhysicsModel::~PhysicsModel()
{
if (VAO != 0)
glDeleteVertexArrays(1, &VAO);
if (VBO != 0)
glDeleteBuffers(1, &VBO);
}
void PhysicsModel::SetupOpenGL()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Cube::vertices), Cube::vert
ices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float
), (GLvoid*)0);
glEnableVertexAttribArray(0);
// TexCoord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float
), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
}
void PhysicsModel::DrawRigidBodies(Shader & shader)
{
glBindVertexArray(VAO);
for (auto & body : bodies)
{
[Link](shader);
}
glBindVertexArray(0);
}
void PhysicsModel::DrawSprings(Shader & shader)
{
for (auto & spring : springs)
{
[Link](shader);
}
}
void PhysicsModel::UpdateModel(float dt)
{
for (auto & body : bodies)
{
[Link]();

[Link](gravity * stickMass);
}
for (auto & spring : springs)
[Link]();
if (useRK4)
RK4Integration(dt);
else
EulerIntegration(dt);
}
void PhysicsModel::EulerIntegration(float dt)
{
for (auto & body : bodies)
{
Vector3 acc = [Link] / stickMass;
[Link] += acc * dt;
[Link] *= damping;
[Link] += [Link] * dt;
[Link] = stickMass * stickLength * stickLength / 12.0f
;
Vector3 angularAcc = [Link] / [Link];
[Link] += angularAcc * dt;
[Link] *= damping;
[Link] += [Link].z * dt;
}
}
void PhysicsModel::RK4Integration(float dt)
{
int id = -1;
float moi = stickMass * stickLength * stickLength / 12.0f;
for (auto & body : bodies)
{
//The RK4 integration algorithm.
//Explianed in [Link]
%93Kutta_methods#The_Runge.E2.80.93Kutta_method
++id;
[Link] = moi;
Vector3 force[4], torque[4], acc[4], vel[4], angAcc[4],
angVel[4], pos[4];
Radian rotAng[4];
float time[4];
force[0] = [Link];
torque[0] = [Link];
time[0] = time[3] = dt;
time[1] = time[2] = dt * 0.5f;
for (int i = 0; i < 4; ++i)
{
acc[i] = force[i] / stickMass;
vel[i] = [Link] + acc[i] * time[i];
angAcc[i] = torque[i] / moi;
angVel[i] = [Link] + angAcc[i] * t
ime[i];
pos[i] = [Link] + vel[i] * time[i];
rotAng[i] = [Link] + angVel[i].z * t

ime[i];
if (i < 3)
RecalculateForce(id, pos[i], rotAng[i],
force[i + 1], torque[i + 1]);
}
[Link] += (acc[0] + 2.0f * (acc[1] + acc[2]) + ac
c[3]) * (dt / 6.0f);
[Link] *= damping;
[Link] += (angAcc[0] + 2.0f * (angAcc[1] +
angAcc[2]) + angAcc[3]) * (dt / 6.0f);
[Link] *= damping;
[Link] += (vel[0] + 2.0f * (vel[1] + vel[2]) + vel[
3]) * (dt / 6.0f);
[Link] += ((angVel[0] + (angVel[1] + angVel[
2]) * 2.0f + angVel[3]) * (dt / 6.0f)).z;
}
}
void PhysicsModel::RecalculateForce(int id, Vector3 newPos, Radian newRo
tAng, Vector3 & force, Vector3 & torque)
{
force = Vector3::ZERO;
torque = Vector3::ZERO;
Vector3 leftStick;
Vector3 rightStick;
if (id == 0)
{
leftStick = [Link]();
rightStick = bodies[id + 1].GetLeftEnd();
}
else if (id == [Link]() - 1)
{
leftStick = bodies[id - 1].GetRightEnd();
rightStick = [Link]();
}
else
{
leftStick = bodies[id - 1].GetRightEnd();
rightStick = bodies[id + 1].GetLeftEnd();
}
Quaternion rot;
[Link](newRotAng, Vector3::UNIT_Z);
Transform transform(newPos, rot, Vector3(stickLength, 1.0f, 1.0f
));
Matrix4 matrix = [Link]();
Vector3 leftEnd = matrix * Vector3(-0.5f, 0.0f, 0.0f);
Vector3 rightEnd = matrix * Vector3(0.5f, 0.0f, 0.0f);
Vector3 leftDirection = leftStick - leftEnd;
Vector3 rightDirection = rightStick - rightEnd;
Vector3 leftForce = ([Link]() / springLength - 1.0
f) * springStrength * leftDirection;
Vector3 rightForce = ([Link]() / springLength - 1
.0f) * springStrength * rightDirection;

Vector3 leftTorque = (leftEnd - newPos).CrossProduct(leftForce);


Vector3 rightTorque = (rightEnd - newPos).CrossProduct(rightForc
e);
force += leftForce;
force += rightForce;
force += gravity * stickMass;
torque += leftTorque;
torque += rightTorque;
}
void PhysicsModel::SetPinEnd(const Vector3 & newPos)
{
[Link] = newPos;
}
void PhysicsModel::SetupEditor(EditorUnit * editor)
{
editor->AddVariableRW("Gravity", "Physics", &gravity[1], -1000.0
f, 1000.0f, 1.0f);
editor->AddVariableRW("Damping", "Physics", &damping, 0.9900f, 0
.9999f, 0.0001f);
editor->AddVariableRW("Stick Length", "Physics", &stickLength, 1
.0f, 30.0f, 1.0f);
editor->AddVariableRW("Stick Mass", "Physics", &stickMass, 1.0f,
500.0f, 1.0f);
editor->AddVariableRW("Spring Length", "Physics", &springLength,
1.0f, 30.0f, 1.0f);
editor->AddVariableRW("Spring Strength", "Physics", &springStren
gth, 1.0f, 500.0f, 1.0f);
editor->AddVariableRW("Use RK4", "Physics", &useRK4);
}
}

You might also like