WIP camera stuff. Missing some useful quaternion helpers.

This commit is contained in:
Ben Visness
2018-06-11 15:40:31 -05:00
parent 3a382212f9
commit 88d583e6ac
3 changed files with 114 additions and 11 deletions

View File

@@ -23,7 +23,40 @@ public:
RenderComponent *renderComponent = NULL; RenderComponent *renderComponent = NULL;
struct CameraInfo {
float fov = 90.0f;
float aspect = 1024.0f / 768.0f;
float near = 0.1f;
float far = 100.0f;
};
CameraInfo camera;
hmm_mat4 projectionMatrix() {
return HMM_Perspective(camera.fov, camera.aspect, camera.near, camera.far);
}
hmm_mat4 viewMatrix() {
return HMM_LookAt(worldPosition(), worldPosition() + forward(), up());
}
hmm_vec3 worldPosition() {
return (modelMatrix * HMM_Vec4(0.0f, 0.0f, 0.0f, 1.0f)).XYZ;
}
hmm_vec3 up() {
return (modelMatrix * HMM_Vec4(0.0f, 1.0f, 0.0f, 1.0f)).XYZ - worldPosition();
}
hmm_vec3 forward() {
return (modelMatrix * HMM_Vec4(1.0f, 0.0f, 0.0f, 1.0f)).XYZ - worldPosition();
}
hmm_vec3 right() {
return (modelMatrix * HMM_Vec4(0.0f, 0.0f, 1.0f, 1.0f)).XYZ - worldPosition();
}
// Context for rendering and stuff // Context for rendering and stuff
hmm_mat4 parentModelMatrix;
hmm_mat4 modelMatrix; hmm_mat4 modelMatrix;
}; };

58
example/src/FollowCam.h Normal file
View File

@@ -0,0 +1,58 @@
#include <stdio.h>
#ifndef HMME_FOLLOWCAM_H
#define HMME_FOLLOWCAM_H
#include "Entity.h"
#include "HandmadeMath.h"
class FollowCam : public Entity {
public:
Entity *target;
FollowCam(Entity *t) {
target = t;
}
// HI BEN HERE IS YOUR STREAM OF CONSCIOUSNESS
//
// Up is wonky. Really this whole thing is a little wonky, although it's
// gotten pretty close. You need to figure out how to directly calculate the
// axis and angle so you don't have to do this in two steps. Then it should
// Just Work.
//
// Although you may have to figure out how to make the camera keep a consistent up vector.
//
// Actually that shouldn't be too hard, because once you have a quaternion
// LookAt thing, you can just always pass world up to it.
void Tick(float deltaSeconds) override {
// rotation = HMM_QuaternionFromAxisAngle(target->worldPosition() - worldPosition(), 0.0f);
// rotation = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 1.0f, 0.0f), HMM_ToRadians(0.0f));
// rotation = HMM_Qu
hmm_vec3 fwd = (parentModelMatrix * HMM_Vec4(1.0f, 0.0f, 0.0f, 0.0f)).XYZ;
hmm_vec3 up = (parentModelMatrix * HMM_Vec4(0.0f, 1.0f, 0.0f, 0.0f)).XYZ;
hmm_vec3 to = target->worldPosition() - worldPosition();
float dot = HMM_DotVec3(fwd, HMM_NormalizeVec3(to));
if (HMM_ABS(dot - 1.0f) < 0.000001f) {
// do nothing to the rotation
} else if (HMM_ABS(dot + 1.0f) < 0.000001f) {
// rotate 180 I guess but for now do nothing
} else {
hmm_vec3 cross = HMM_Normalize(HMM_Cross(fwd, to));
rotation = HMM_QuaternionFromAxisAngle(
cross,
HMM_ACOSF(dot)
);
rotation *= HMM_QuaternionFromAxisAngle(
HMM_Vec3(1.0f, 0.0f, 0.0f),
-HMM_ACOSF(HMM_DotVec3(cross, up))
);
}
}
};
#endif

View File

@@ -11,6 +11,7 @@
#include "Entity.h" #include "Entity.h"
#include "Cube.h" #include "Cube.h"
#include "MeshRenderComponent.h" #include "MeshRenderComponent.h"
#include "FollowCam.h"
void TickTree(Entity *e, float deltaSeconds); void TickTree(Entity *e, float deltaSeconds);
void ComputeModelMatrices(Entity *ep, hmm_mat4 parentModelMatrix); void ComputeModelMatrices(Entity *ep, hmm_mat4 parentModelMatrix);
@@ -67,17 +68,27 @@ int main()
// Accept fragment if it closer to the camera than the former one // Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
Cube root = Cube(); Cube c1 = Cube();
Entity child = Entity(); Entity monkey = Entity();
child.position = HMM_Vec3(2.1f, 0.0f, 0.0f); monkey.position = HMM_Vec3(2.1f, 0.0f, 0.0f);
child.renderComponent = new MeshRenderComponent("MonkeySmooth.obj"); monkey.renderComponent = new MeshRenderComponent("MonkeySmooth.obj");
FollowCam cam = FollowCam(&monkey);
// cam.position = HMM_Vec3(3.0f, 3.0f, 4.0f);
cam.position = HMM_Vec3(3.0f, 3.0f, 5.0f);
// cam.rotation = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 1.0f, 0.0f), HMM_ToRadians(90.0f));
// Cube c = Cube(); // Cube c = Cube();
// child.position = HMM_Vec3(2.1f, 0.0f, 0.0f); // monkey.position = HMM_Vec3(2.1f, 0.0f, 0.0f);
// child.AddChild(&c); // monkey.AddChild(&c);
root.AddChild(&child);
c1.AddChild(&monkey);
Entity root = Entity();
root.AddChild(&c1);
root.AddChild(&cam);
bool hasTicked = false; bool hasTicked = false;
high_resolution_clock::time_point lastTickTime; high_resolution_clock::time_point lastTickTime;
@@ -85,10 +96,6 @@ int main()
do { do {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
hmm_mat4 projection = HMM_Perspective(90.0f, 1024.0f / 768.0f, 0.1f, 100.0f);
hmm_mat4 view = HMM_LookAt(HMM_Vec3(3.0f, 3.0f, 4.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f));
hmm_mat4 vp = projection * view;
// Tick // Tick
auto now = high_resolution_clock::now(); auto now = high_resolution_clock::now();
if (hasTicked) { if (hasTicked) {
@@ -103,6 +110,10 @@ int main()
ComputeModelMatrices(&root, HMM_Mat4d(1.0f)); ComputeModelMatrices(&root, HMM_Mat4d(1.0f));
// Render! // Render!
hmm_mat4 projection = cam.projectionMatrix();
hmm_mat4 view = cam.viewMatrix();
hmm_mat4 vp = projection * view;
auto it = EntityIterator(&root); auto it = EntityIterator(&root);
while (it.HasNext()) { while (it.HasNext()) {
Entity *e = it.Next(); Entity *e = it.Next();
@@ -142,6 +153,7 @@ void TickTree(Entity *e, float deltaSeconds) {
} }
void ComputeModelMatrices(Entity *e, hmm_mat4 parentModelMatrix) { void ComputeModelMatrices(Entity *e, hmm_mat4 parentModelMatrix) {
e->parentModelMatrix = parentModelMatrix;
e->modelMatrix = parentModelMatrix * HMM_Translate(e->position) * HMM_QuaternionToMat4(e->rotation) * HMM_Scale(e->scale); e->modelMatrix = parentModelMatrix * HMM_Translate(e->position) * HMM_QuaternionToMat4(e->rotation) * HMM_Scale(e->scale);
for (int i = 0; i < e->children.size(); i++) { for (int i = 0; i < e->children.size(); i++) {