Add origin vector to Transform

We need this in addition to the Matrix (which includes translation) - mainly for rotation, which should be around the translation, but not around the origin.

There may be some places left which need changes due to this - the line between the origin and translation isn't as clear yet as it should be.
This commit is contained in:
karl 2020-09-29 21:04:25 +02:00
parent 0aa41b3d66
commit 9125e7a3cc
5 changed files with 46 additions and 41 deletions

View File

@ -15,11 +15,16 @@ struct Transform {
Transform() = default; Transform() = default;
glm::mat4 matrix = glm::mat4(1.0f); // Initialize as identity glm::mat4 matrix = glm::mat4(1.0f); // Initialize as identity
glm::vec3 origin = glm::vec3(0.0f, 0.0f, 0.0f);
void translate(glm::vec3 offset) { void translate(glm::vec3 offset) {
matrix = glm::translate(matrix, offset); matrix = glm::translate(matrix, offset);
} }
glm::vec3 get_translation() {
return glm::vec3(matrix[3]);
}
void uniform_scale(float factor) { void uniform_scale(float factor) {
scale(glm::vec3(factor, factor, factor)); scale(glm::vec3(factor, factor, factor));
} }
@ -32,9 +37,8 @@ struct Transform {
matrix = glm::rotate(matrix, glm::radians(degrees), axis); matrix = glm::rotate(matrix, glm::radians(degrees), axis);
} }
void set_position(glm::vec3 position) { void set_origin(glm::vec3 position) {
glm::vec3 difference = getPosition() - position; origin = position;
translate(-difference);
} }
void set_rotation_from_quat(glm::quat quaternion) { void set_rotation_from_quat(glm::quat quaternion) {
@ -43,12 +47,10 @@ struct Transform {
matrix = glm::mat4_cast(quaternion); matrix = glm::mat4_cast(quaternion);
matrix[3] = save; matrix[3] = save;
std::cout << glm::to_string(matrix) << std::endl;
} }
glm::vec3 getPosition() const { glm::vec3 get_origin() const {
return matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); return origin;
} }
glm::vec3 forward() const { glm::vec3 forward() const {

View File

@ -135,15 +135,12 @@ class PathMoveSystem : public EntitySystem, public EventSubscriber<InputEvent> {
pathmove->time_passed); pathmove->time_passed);
// Apply // Apply
transform->set_position(point); transform->set_origin(point);
// Rotation // Rotation
// https://www.3dgep.com/understanding-quaternions/#SQUAD // https://www.3dgep.com/understanding-quaternions/#SQUAD
PathMove::Views views = pathmove->views; PathMove::Views views = pathmove->views;
transform->set_rotation_from_quat(views.views[pathmove->current_point_index]); transform->set_rotation_from_quat(views.views[pathmove->current_point_index]);
// FIXME: Debugging output
std::cout << point.x << ", " << point.y << ", " << point.z << std::endl;
}); });
} }

View File

@ -17,9 +17,9 @@ public:
void tick(World *pWorld, float deltaTime) override { void tick(World *pWorld, float deltaTime) override {
pWorld->each<Transform>([&](Entity *ent, ComponentHandle<Transform> transform) { pWorld->each<Transform>([&](Entity *ent, ComponentHandle<Transform> transform) {
std::cout << ent->getEntityId() << ": " std::cout << ent->getEntityId() << ": "
<< transform->getPosition().x << ", " << transform->get_origin().x << ", "
<< transform->getPosition().y << ", " << transform->get_origin().y << ", "
<< transform->getPosition().z << transform->get_origin().z
<< std::endl; << std::endl;
}); });
} }

View File

@ -34,9 +34,14 @@ public:
shader.setVec3("lightDirection", light->direction); shader.setVec3("lightDirection", light->direction);
}); });
glm::vec3 cameraPos = cameraTransform->get_origin();
glm::mat4 view = cameraTransform->matrix;
view[3] = glm::vec4(cameraPos, 1.0);
shader.setMat4("projection", camera->projection); shader.setMat4("projection", camera->projection);
shader.setMat4("view", glm::inverse(cameraTransform->matrix)); shader.setMat4("view", glm::inverse(view));
shader.setVec3("cameraPosition", cameraTransform->getPosition()); shader.setVec3("cameraPosition", cameraTransform->get_origin());
std::vector<RenderObject> renderObjects; std::vector<RenderObject> renderObjects;
std::vector<RenderObject> transparentRenderObjects; std::vector<RenderObject> transparentRenderObjects;
@ -45,8 +50,6 @@ public:
renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), 0)); renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), 0));
});*/ });*/
glm::vec3 cameraPos = cameraTransform->getPosition();
/*// TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism? /*// TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism?
* // TODO: Commented out because of double rendering - we only want to get objects that explicitly DON'T have a texture here! * // TODO: Commented out because of double rendering - we only want to get objects that explicitly DON'T have a texture here!
pWorld->each<ObjMesh, Transform>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform) { pWorld->each<ObjMesh, Transform>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform) {
@ -61,7 +64,7 @@ public:
// ObjMesh with textures // ObjMesh with textures
pWorld->each<ObjMesh, Transform, Texture>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform, ComponentHandle<Texture> texture) { pWorld->each<ObjMesh, Transform, Texture>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform, ComponentHandle<Texture> texture) {
// Add the object to the renderObjects to draw if the distance is within the min and max distance of the mesh // Add the object to the renderObjects to draw if the distance is within the min and max distance of the mesh
float distance = glm::distance(cameraPos, transform->getPosition()); float distance = glm::distance(cameraPos, transform->get_origin());
if (distance > mesh->minDistance && distance < mesh->maxDistance) { if (distance > mesh->minDistance && distance < mesh->maxDistance) {
// Get optional components // Get optional components
@ -73,16 +76,16 @@ public:
// Put it into the list of transparent render objects if the texture wants to be rendered transparently // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (textureComponent.isValid() && textureComponent->render_transparent) { if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh.get(), distance, material)); transparentRenderObjects.emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh.get(), distance, material));
} else { } else {
renderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh.get(), distance, material)); renderObjects.emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh.get(), distance, material));
} }
} }
}); });
// LODObjMesh with Texture // LODObjMesh with Texture
pWorld->each<LODObjMesh, Transform>([&](Entity *ent, ComponentHandle<LODObjMesh> lodMesh, ComponentHandle<Transform> transform) { pWorld->each<LODObjMesh, Transform>([&](Entity *ent, ComponentHandle<LODObjMesh> lodMesh, ComponentHandle<Transform> transform) {
float distance = glm::distance(cameraPos, transform->getPosition()); float distance = glm::distance(cameraPos, transform->get_origin());
for (const auto &mesh : lodMesh->meshes) { for (const auto &mesh : lodMesh->meshes) {
if (distance > mesh.minDistance && distance < mesh.maxDistance) { if (distance > mesh.minDistance && distance < mesh.maxDistance) {
@ -95,9 +98,9 @@ public:
// Put it into the list of transparent render objects if the texture wants to be rendered transparently // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (textureComponent.isValid() && textureComponent->render_transparent) { if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh, distance, material)); transparentRenderObjects.emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh, distance, material));
} else { } else {
renderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh, distance, material)); renderObjects.emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh, distance, material));
} }
} }
} }
@ -118,15 +121,18 @@ public:
} }
struct RenderObject { struct RenderObject {
RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh, float distance, const Material &material) RenderObject(const glm::mat4 &matrix, const glm::vec3 &origin, unsigned int textureId, const Mesh &mesh, float distance, const Material &material)
: matrix(matrix), : matrix(matrix),
origin(origin),
texture_id(textureId), texture_id(textureId),
mesh(mesh), mesh(mesh),
distance(distance), distance(distance),
material(material) {} material(material) {}
void render(Shader shader) const { void render(Shader shader) const {
shader.setMat4("model", matrix); glm::mat4 model_matrix = matrix;
model_matrix[3] = glm::vec4(origin, 1.0);
shader.setMat4("model", model_matrix);
// 0 can't be a valid texture name, so we use it for meshes without textures here // 0 can't be a valid texture name, so we use it for meshes without textures here
if (texture_id != 0) { if (texture_id != 0) {
@ -140,6 +146,7 @@ public:
} }
glm::mat4 matrix; glm::mat4 matrix;
glm::vec3 origin;
unsigned int texture_id; unsigned int texture_id;
Mesh mesh; Mesh mesh;
float distance; float distance;

View File

@ -93,24 +93,23 @@ int main() {
player->assign<Camera>(70.0f, 1280, 720, 0.1f, 100.0f); player->assign<Camera>(70.0f, 1280, 720, 0.1f, 100.0f);
player->assign<PathMove>(10.0, PathMove::Path(std::vector<glm::vec3>{ player->assign<PathMove>(10.0, PathMove::Path(std::vector<glm::vec3>{
glm::vec3(0.0, 2.0, 0.0), glm::vec3(0.0, 2.0, 0.0),
glm::vec3(0.0, 2.0, -1.0), glm::vec3(-2.0, 2.0, -1.0),
glm::vec3(2.0, 2.0, -2.0), glm::vec3(-1.0, 2.0, -2.0),
glm::vec3(1.0, 3.0, -3.0), glm::vec3(4.0, 3.0, -3.0),
glm::vec3(-2.0, 2.0, -4.0),
glm::vec3(2.0, 2.0, -4.0), glm::vec3(2.0, 2.0, -4.0),
glm::vec3(1.0, 2.0, -4.0),
glm::vec3(0.0, 2.0, -10.0) glm::vec3(0.0, 2.0, -10.0)
}), }),
PathMove::Views(std::vector<glm::quat>{ PathMove::Views(std::vector<glm::quat>{
glm::quat(0.0, 0.0, 0.0, 0.0), glm::quat(0.0, 0.0, 0.0, 0.0),
glm::angleAxis(glm::radians(-10.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(10.f), glm::vec3(0.f, 1.f, 0.f)), glm::angleAxis(glm::radians(10.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(30.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(40.f), glm::vec3(0.f, 1.f, 0.f)), glm::angleAxis(glm::radians(40.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(50.f), glm::vec3(0.f, 1.f, 0.f)), glm::angleAxis(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(70.f), glm::vec3(0.f, 1.f, 0.f)), glm::angleAxis(glm::radians(95.f), glm::vec3(0.f, 1.f, 0.f)),
glm::angleAxis(glm::radians(80.f), glm::vec3(0.f, 1.f, 0.f)) glm::angleAxis(glm::radians(180.f), glm::vec3(0.f, 1.f, 0.f))
}) })
); );
player->get<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f));
Entity *monkey = world->create(); Entity *monkey = world->create();
monkey->assign<Transform>(); monkey->assign<Transform>();
@ -119,28 +118,28 @@ int main() {
monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false)); monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false));
monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5);
monkey->assign<Material>(0.6, 0.6); monkey->assign<Material>(0.6, 0.6);
monkey->get<Transform>()->translate(glm::vec3(0.0f, 2.0f, -6.0f)); monkey->get<Transform>()->set_origin(glm::vec3(0.0f, 2.0f, -6.0f));
Entity *wall1 = world->create(); Entity *wall1 = world->create();
wall1->assign<Transform>(); wall1->assign<Transform>();
wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall1->assign<Material>(0.2, 0.8); wall1->assign<Material>(0.2, 0.8);
wall1->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -2.0f)); wall1->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -2.0f));
Entity *wall2 = world->create(); Entity *wall2 = world->create();
wall2->assign<Transform>(); wall2->assign<Transform>();
wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall2->assign<Material>(0.2, 0.8); wall2->assign<Material>(0.2, 0.8);
wall2->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -10.0f)); wall2->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -10.0f));
Entity *wall3 = world->create(); Entity *wall3 = world->create();
wall3->assign<Transform>(); wall3->assign<Transform>();
wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall3->assign<Material>(0.2, 0.8); wall3->assign<Material>(0.2, 0.8);
wall3->get<Transform>()->translate(glm::vec3(4.0f, 0.0f, -6.0f)); wall3->get<Transform>()->set_origin(glm::vec3(4.0f, 0.0f, -6.0f));
wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
Entity *wall4 = world->create(); Entity *wall4 = world->create();
@ -148,7 +147,7 @@ int main() {
wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall4->assign<Material>(0.2, 0.8); wall4->assign<Material>(0.2, 0.8);
wall4->get<Transform>()->translate(glm::vec3(-4.0f, 0.0f, -6.0f)); wall4->get<Transform>()->set_origin(glm::vec3(-4.0f, 0.0f, -6.0f));
wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
Entity *ground = world->create(); Entity *ground = world->create();
@ -156,7 +155,7 @@ int main() {
ground->assign<ObjMesh>(ObjMesh("Resources/Ground.obj", ObjMesh::Settings())); ground->assign<ObjMesh>(ObjMesh("Resources/Ground.obj", ObjMesh::Settings()));
ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true, false)); ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true, false));
ground->assign<Material>(1.0, 0.0); ground->assign<Material>(1.0, 0.0);
ground->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, 0.0f)); ground->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, 0.0f));
Entity *sun = world->create(); Entity *sun = world->create();
sun->assign<DirectionalLight>(glm::normalize(glm::vec3(1.0, 1.0, 1.0))); sun->assign<DirectionalLight>(glm::normalize(glm::vec3(1.0, 1.0, 1.0)));