Refactor spatial, add documentation

This commit is contained in:
Dane Johnson 2021-01-26 23:28:20 -06:00
parent 62059079cd
commit d6db1c16c7
9 changed files with 293 additions and 73 deletions

View File

@ -1,11 +1,35 @@
/**
@file
@author Dane Johnson <dane@danejohnson.org>
@section LICENSE
Couch Copyright (C) 2021 Dane Johnson
This program comes with ABSOLUTELY NO WARRANTY; without event the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details at
https://www.gnu.org/licenses/gpl-3.0.html
This is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
@section DESCRIPTION
This file defines the cameras that can be used to render the scene
*/
#ifndef CAMERA_H
#define CAMERA_H
#include "Transform.h"
#include "Spatial.h"
class Camera {
/**
The common 3D camera
*/
class Camera : public Spatial {
public:
Transform transform;
Camera();
void MakeCurrent();
static Camera *GetCurrentCamera();

View File

@ -1,8 +1,7 @@
/**
@file
@author Dane Johnson <dane@danejohnson.org>
/*
Dane Johnson <dane@danejohnson.org>
@section LICENSE
LICENSE
Couch Copyright (C) 2021 Dane Johnson
@ -16,7 +15,7 @@
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
@section DESCRIPTION
DESCRIPTION
Node is the parent class for all classes that would be in the scene
tree. The root of the scene tree is always a node.

View File

@ -56,23 +56,26 @@ RigidbodyMotionState::RigidbodyMotionState(Rigidbody *rigidbody) {
}
void RigidbodyMotionState::getWorldTransform(btTransform &worldTrans) const {
Transform transform = rigidbody->GetTransform();
worldTrans.setOrigin(btVector3(
rigidbody->transform.position.x,
rigidbody->transform.position.y,
rigidbody->transform.position.z));
transform.position.x,
transform.position.y,
transform.position.z));
btQuaternion quat;
quat.setEuler(rigidbody->transform.rotation.z,
rigidbody->transform.rotation.y,
rigidbody->transform.rotation.x);
quat.setEuler(transform.rotation.z,
transform.rotation.y,
transform.rotation.x);
worldTrans.setRotation(quat);
}
void RigidbodyMotionState::setWorldTransform(const btTransform &worldTrans) {
rigidbody->transform.position = Vector3(worldTrans.getOrigin().getX(),
Transform transform = rigidbody->GetTransform();
transform.position = Vector3(worldTrans.getOrigin().getX(),
worldTrans.getOrigin().getY(),
worldTrans.getOrigin().getZ());
worldTrans.getRotation().getEulerZYX(rigidbody->transform.rotation.z,
rigidbody->transform.rotation.y,
rigidbody->transform.rotation.x);
worldTrans.getRotation().getEulerZYX(transform.rotation.z,
transform.rotation.y,
transform.rotation.x);
rigidbody->SetTransform(transform);
}

View File

@ -1,11 +1,71 @@
/*
Dane Johnson <dane@danejohnson.org>
LICENSE
Couch Copyright (C) 2021 Dane Johnson
This program comes with ABSOLUTELY NO WARRANTY; without event the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details at
https://www.gnu.org/licenses/gpl-3.0.html
This is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
DESCRIPTION
A spatial is a node with a transform property, i.e. position, scale or rotation.
They can be instanced on the scene tree as an anchor for some other nodes.
*/
#include "Spatial.h"
Name Spatial::GetType() const {return "Spatial";}
Transform Spatial::GetTransform() {
return transform;
}
void Spatial::SetTransform(Transform transform) {
this->transform = transform;
}
Spatial *Spatial::Create() {
return new Spatial;
}
void Spatial::Translate(Vector3 offset) {
Transform t = this->GetTransform();
t.position += offset;
this->SetTransform(t);
}
void Spatial::RotateX(cfloat phi) {
Transform t = this->GetTransform();
t.rotation.x += phi;
this->SetTransform(t);
}
void Spatial::RotateY(cfloat phi) {
Transform t = this->GetTransform();
t.rotation.y += phi;
this->SetTransform(t);
}
void Spatial::RotateZ(cfloat phi) {
Transform t = this->GetTransform();
t.rotation.z += phi;
this->SetTransform(t);
}
void Spatial::UniformScale(cfloat scale) {
Transform t = this->GetTransform();
t.scale *= scale;
this->SetTransform(t);
}
Spatial *Spatial::Duplicate() {
Spatial *spatial = static_cast<Spatial*>(Node::Duplicate());
spatial->transform = transform;

View File

@ -1,17 +1,83 @@
/**
@file
@author Dane Johnson <dane@danejohnson.org>
@section LICENSE
Couch Copyright (C) 2021 Dane Johnson
This program comes with ABSOLUTELY NO WARRANTY; without event the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details at
https://www.gnu.org/licenses/gpl-3.0.html
This is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
@section DESCRIPTION
A spatial is a node with a transform property, i.e. position, scale or rotation.
They can be instanced on the scene tree as an anchor for some other nodes.
*/
#ifndef SPATIAL_H
#define SPATIAL_H
#include "types.h"
#include "Node.h"
#include "Transform.h"
/**
Spatial nodes have a transform property. They can be subclassed or instanced
as an anchor for their children.
*/
class Spatial : public Node {
public:
Transform transform;
virtual bool IsTransformable() const { return true;}
virtual Name GetType() const;
/**
Gets the transform property of this spatial
@return The transform
*/
Transform GetTransform();
/**
Sets the transform property of this spatial.
@param transform The transform property
*/
void SetTransform(Transform transform);
/**
Directly translates the spatial by offset
@param offset The offset of the transform operation
*/
void Translate(Vector3 offset);
/**
Rotates the Camera phi radians about the X axis
@param phi The amount to rotate in radians
*/
void RotateX(cfloat phi);
/**
Rotates the Camera phi radians about the Y axis
@param phi The amount to rotate in radians
*/
void RotateY(cfloat phi);
/**
Rotates the Camera phi radians about the Z axis
@param phi The amount to rotate in radians
*/
void RotateZ(cfloat phi);
/**
Scales the spatial by scale uniformly
@param scale The amount to scale by.
*/
void UniformScale(cfloat scale);
virtual Spatial *Create();
virtual Spatial *Duplicate();
virtual Spatial *Instance();
private:
Transform transform;
};
#endif /* SPATIAL_H */

View File

@ -1,4 +1,26 @@
/*
Dane Johnson <dane@danejohnson.org>
LICENSE
Couch Copyright (C) 2021 Dane Johnson
This program comes with ABSOLUTELY NO WARRANTY; without event the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details at
https://www.gnu.org/licenses/gpl-3.0.html
This is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
DESCRIPTION
A transform represents various aspects of 3d space.
*/
#include "Transform.h"
#include <glm/gtc/matrix_transform.hpp>
Transform::Transform() {
position = Vector3(0.0f);
@ -19,21 +41,6 @@ Transform::Transform(Vector3 position, Vector3 rotation, Vector3 scale) {
}
void Transform::Translate(cfloat x, cfloat y, cfloat z) {
position = position + Vector3(x, y, z);
}
Matrix Transform::RotationMatrix() {
Matrix mat(1.0f);
mat = glm::rotate(mat, this->rotation.z, Vector3(0.0f, 0.0f, 1.0f));
mat = glm::rotate(mat, this->rotation.y, Vector3(0.0f, 1.0f, 0.0f));
mat = glm::rotate(mat, this->rotation.x, Vector3(1.0f, 0.0f, 0.0f));
return mat;
}
Vector3 Transform::Forward() {
return glm::vec3(RotationMatrix() * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f));
}
@ -45,3 +52,13 @@ Vector3 Transform::Up() {
Vector3 Transform::Right() {
return glm::vec3(RotationMatrix() * glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
}
Matrix Transform::RotationMatrix() {
Matrix mat(1.0f);
mat = glm::rotate(mat, this->rotation.z, Vector3(0.0f, 0.0f, 1.0f));
mat = glm::rotate(mat, this->rotation.y, Vector3(0.0f, 1.0f, 0.0f));
mat = glm::rotate(mat, this->rotation.x, Vector3(1.0f, 0.0f, 0.0f));
return mat;
}

View File

@ -1,21 +1,65 @@
/**
@file
@author Dane Johnson <dane@danejohnson.org>
@section LICENSE
Couch Copyright (C) 2021 Dane Johnson
This program comes with ABSOLUTELY NO WARRANTY; without event the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details at
https://www.gnu.org/licenses/gpl-3.0.html
This is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
@section DESCRIPTION
A transform represents various aspects of 3d space.
*/
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include <glm/gtc/matrix_transform.hpp>
#include "types.h"
/**
A Transform represents a position, rotation, and scale in 3D space.
*/
struct Transform {
Transform();
Transform(Vector3 position, Vector3 rotation);
Transform(Vector3 position, Vector3 rotation, Vector3 scale);
/**
The position, according to the left-hand rule
*/
Vector3 position;
/**
The rotation, in Euler angles
*/
Vector3 rotation;
/**
Scaling along the specified axis
*/
Vector3 scale;
void Translate(cfloat x, cfloat y, cfloat z);
/**
Returns a vector that is -Z, rotated by @ref rotation.
*/
Vector3 Forward();
/**
Returns a vector that is +X, rotated by @ref rotation.
*/
Vector3 Right();
/**
Returns a vector that is +Y, rotated by @ref rotation.
*/
Vector3 Up();
/**
Returns a matrix that, when multiplied by a @ref Vector3
gives a Vector rotated by @ref rotation
*/
Matrix RotationMatrix();
};

View File

@ -43,11 +43,12 @@ Node *root;
void render(Node *curr, Shader *shader, Matrix model) {
Spatial *spatial = dynamic_cast<Spatial*>(curr);
if (spatial) {
model = glm::rotate(model, spatial->transform.rotation.x, Vector3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, spatial->transform.rotation.y, Vector3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, spatial->transform.rotation.z, Vector3(0.0f, 0.0f, 1.0f));
model = glm::translate(model, spatial->transform.position);
model = glm::scale(model, spatial->transform.scale);
Transform transform = spatial->GetTransform();
model = glm::rotate(model, transform.rotation.x, Vector3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, transform.rotation.y, Vector3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, transform.rotation.z, Vector3(0.0f, 0.0f, 1.0f));
model = glm::translate(model, transform.position);
model = glm::scale(model, transform.scale);
shader->UpdateModel(model);
shader->UpdateNormal(glm::mat3(glm::transpose(glm::inverse(model))));
}
@ -126,10 +127,11 @@ int main() {
shader->UpdateProjection(projection);
Matrix view(1.0f);
Camera *camera = Camera::GetCurrentCamera();
view = glm::rotate(view, -camera->transform.rotation.x, Vector3(1.0f, 0.0f, 0.0f));
view = glm::rotate(view, -camera->transform.rotation.y, Vector3(0.0f, 1.0f, 0.0f));
view = glm::rotate(view, -camera->transform.rotation.z, Vector3(0.0f, 0.0f, 1.0f));
view = glm::translate(view, -camera->transform.position);
Transform camera_transform = camera->GetTransform();
view = glm::rotate(view, -camera_transform.rotation.x, Vector3(1.0f, 0.0f, 0.0f));
view = glm::rotate(view, -camera_transform.rotation.y, Vector3(0.0f, 1.0f, 0.0f));
view = glm::rotate(view, -camera_transform.rotation.z, Vector3(0.0f, 0.0f, 1.0f));
view = glm::translate(view, -camera_transform.position);
shader->UpdateView(view);
// Find the lights

View File

@ -27,10 +27,11 @@ local light
function init()
local material
local transform
camera = couch.Camera()
camera:MakeCurrent()
camera.transform:Translate(0.0, 0.0, 10.0)
camera:Translate(couch.Vector3(0.0, 0.0, 10.0))
local light = couch.DirectionalLight()
light.direction = couch.Vector3(0.0, -1.0, -1.0)
@ -38,7 +39,6 @@ function init()
light.ambient = 0.2
light.diffuse = 1.0
light.specular = 0.1
print(couch.Node.GetRoot().GetChildren)
couch.Node.GetRoot():AddChild(light:Instance())
local skybox = couch.Skybox.FromFiles(
@ -58,7 +58,7 @@ function init()
material.diffuse = BLUE
physics_ball_mesh:SetMaterial(0, material)
physics_ball_prefab:AddChild(physics_ball_mesh);
physics_ball_prefab.transform.position = couch.Vector3(0.0, 30.0, -10.0)
physics_ball_prefab:Translate(couch.Vector3(0.0, 30.0, -10.0))
physics_ball = physics_ball_prefab:Instance()
couch.Node.GetRoot():AddChild(physics_ball)
@ -75,7 +75,7 @@ function init()
character_body:SetCollisionShape(couch.CapsuleCollisionShape(1.0, 1.0))
character_body:SetCharacter(true)
character_body:AddChild(character_prefab)
character_body.transform.position = couch.Vector3(0.0, 3.0, 0.0)
character_body:Translate(couch.Vector3(0.0, 3.0, 0.0))
character = character_body:Instance()
couch.Node.GetRoot():AddChild(character)
@ -85,8 +85,8 @@ function init()
material.diffuse = RED
cube_prefab:SetMaterial(0, material)
local orbiter = couch.Mesh.FromFile("ball.obj")
orbiter.transform.scale = orbiter.transform.scale * 0.25;
orbiter.transform:Translate(1.0, 0.0, 0.0)
orbiter:UniformScale(0.25);
orbiter:Translate(couch.Vector3(1.0, 0.0, 0.0))
cube_prefab:AddChild(orbiter)
cube = cube_prefab:Instance()
couch.Node.GetRoot():AddChild(cube)
@ -97,12 +97,12 @@ function init()
ball = ball_prefab:Instance()
couch.Node.GetRoot():AddChild(ball)
ball.transform:Translate(0.0, 3.0, 0.0)
ball:Translate(couch.Vector3(0.0, 3.0, 0.0))
local trough_prefab = couch.TexturedMesh("trough.obj", "wood_lowres.png")
trough = trough_prefab:Instance()
couch.Node.GetRoot():AddChild(trough)
trough.transform:Translate(10.0, 0.0, 0.0)
trough:Translate(couch.Vector3(10.0, 0.0, 0.0))
local scaffold_prefab = couch.TexturedMesh("scaffold.obj", "grate_floor_lowres.png", "railing.png")
local scaffold = scaffold_prefab:Instance()
@ -116,7 +116,7 @@ function init()
material.alphaScissor = 0.1
scaffold:SetMaterial(1, material)
couch.Node.GetRoot():AddChild(scaffold)
scaffold.transform:Translate(-3.0, 3.0, 0.0)
scaffold:Translate(couch.Vector3(-3.0, 3.0, 0.0))
local barn_prefab = couch.TexturedMesh("barn.obj", "paintedwood.jpg", "barnroof_lowres.png", "wood_lowres.png")
local barn = barn_prefab:Instance()
@ -127,35 +127,37 @@ function init()
material.cullBack = false
barn:SetMaterial(1, material)
couch.Node.GetRoot():AddChild(barn)
barn.transform:Translate(-15.0, 0.0, 0.0)
barn:Translate(couch.Vector3(-15.0, 0.0, 0.0))
end
function update(delta)
local move_vec = couch.Vector3()
move_vec = camera.transform.position + camera.transform:Forward() * delta * vz * SPEED
move_vec = move_vec + camera.transform:Right() * delta * vx * SPEED
move_vec = move_vec + camera.transform:Up() * delta * vy * SPEED
camera.transform.position = move_vec
local camera_transform = camera:GetTransform()
move_vec = camera_transform.position + camera_transform:Forward() * delta * vz * SPEED
move_vec = move_vec + camera_transform:Right() * delta * vx * SPEED
move_vec = move_vec + camera_transform:Up() * delta * vy * SPEED
camera_transform.position = move_vec
camera.transform.rotation.y = camera.transform.rotation.y - cam_rot_x * delta
camera_transform.rotation.y = camera_transform.rotation.y - cam_rot_x * delta
cam_rot_x = 0.0
camera.transform.rotation.x = camera.transform.rotation.x - cam_rot_y * delta
camera.transform.rotation.x = min(max(camera.transform.rotation.x, -3.14 / 2.0), 3.14 / 2.0)
camera_transform.rotation.x = camera_transform.rotation.x - cam_rot_y * delta
camera_transform.rotation.x = min(max(camera_transform.rotation.x, -3.14 / 2.0), 3.14 / 2.0)
cam_rot_y = 0.0
local loc = ball.transform.position
camera:SetTransform(camera_transform)
local loc = ball:GetTransform().position
if loc.y > 4.0 then
ballvy = -1.0
elseif loc.y < 2.0 then
ballvy = 1.0
end
ball.transform.position.y = ball.transform.position.y + ballvy * delta
ball:Translate(couch.Vector3(ballvy * delta, 0.0, 0.0))
cube.transform.rotation.y = cube.transform.rotation.y + 2.0 * delta;
cube.transform.rotation.z = cube.transform.rotation.z + 1.0 * delta;
cube:RotateY(2.0 * delta)
cube:RotateZ(1.0 * delta)
character:ApplyForce(character_move_vec * 10.0)
print(character_move_vec.z)
end
function action_dir(key, action, pos, neg, curr)
@ -189,8 +191,11 @@ end
function make_ground()
local ground_prefab = couch.TexturedMesh("ground.obj", "grass_lowres.png")
ground_prefab.transform.position = couch.Vector3(0.0, -2.0, 0.0)
ground_prefab.transform.scale = couch.Vector3(3.0, 1.0, 3.0)
local ground_prefab_transform = ground_prefab:GetTransform()
ground_prefab_transform.position = couch.Vector3(0.0, -2.0, 0.0)
ground_prefab_transform.scale = couch.Vector3(3.0, 1.0, 3.0)
ground_prefab:SetTransform(ground_prefab_transform)
ground = couch.Spatial():Instance()
couch.Node.GetRoot():AddChild(ground)
@ -199,13 +204,13 @@ function make_ground()
local ground_shape_prefab = couch.Rigidbody()
ground_shape_prefab.mass = 0.0
ground_shape_prefab:SetCollisionShape(couch.BoxCollisionShape(180.0, 1.0, 180.0))
ground_shape_prefab.transform:Translate(0.0, -2.5, 0.0)
ground_shape_prefab:Translate(couch.Vector3(0.0, -2.5, 0.0))
ground:AddChild(ground_shape_prefab:Instance())
for x = -20, 20, 1 do
for z = -20, 20, 1 do
local piece = ground_prefab:Instance()
piece.transform.position = couch.Vector3(6.0 * x, -2.0, 6.0 * z)
piece:Translate(couch.Vector3(6.0 * x, -2.0, 6.0 * z))
ground:AddChild(piece)
end
end