Add instancing system

This commit is contained in:
Dane Johnson 2021-01-24 16:37:35 -06:00
parent 799257bfdb
commit d51528dd0f
15 changed files with 183 additions and 48 deletions

View File

@ -1,10 +1,11 @@
#ifndef CAMERA_H #ifndef CAMERA_H
#define CAMERA_H #define CAMERA_H
#include "Spatial.h" #include "Transform.h"
class Camera : public Spatial { class Camera {
public: public:
Transform transform;
Camera(); Camera();
void MakeCurrent(); void MakeCurrent();
static Camera *GetCurrentCamera(); static Camera *GetCurrentCamera();

View File

@ -2,6 +2,24 @@
Name Light::GetType() const {return "Light";} Name Light::GetType() const {return "Light";}
Light *Light::Duplicate() {
Light *light = static_cast<Light*>(Spatial::Duplicate());
light->color = color;
light->ambient = ambient;
light->diffuse = diffuse;
light->specular = specular;
return light;
}
Light *Light::Instance() {
return static_cast<Light*>(Node::Instance());
}
Light *Light::Create() {
return new Light;
}
Name DirectionalLight::GetType() const {return "DirectionalLight";} Name DirectionalLight::GetType() const {return "DirectionalLight";}
DirectionalLight::DirectionalLight() { DirectionalLight::DirectionalLight() {
@ -19,3 +37,18 @@ DirectionalLight::DirectionalLight(Vector3 direction, Vector3 color, cfloat ambi
this->diffuse = diffuse; this->diffuse = diffuse;
this->specular = specular; this->specular = specular;
} }
DirectionalLight *DirectionalLight::Create() {
return new DirectionalLight;
}
DirectionalLight *DirectionalLight::Duplicate() {
DirectionalLight *directionalLight = static_cast<DirectionalLight*>(Light::Duplicate());
directionalLight->direction = direction;
return directionalLight;
}
DirectionalLight *DirectionalLight::Instance() {
return static_cast<DirectionalLight*>(Node::Instance());
}

View File

@ -9,6 +9,9 @@ public:
Vector3 color; Vector3 color;
cfloat ambient, diffuse, specular; cfloat ambient, diffuse, specular;
virtual Name GetType() const; virtual Name GetType() const;
virtual Light *Create();
virtual Light *Duplicate();
virtual Light *Instance();
}; };
class DirectionalLight : public Light { class DirectionalLight : public Light {
@ -17,6 +20,9 @@ public:
DirectionalLight(); DirectionalLight();
DirectionalLight(Vector3 direction, Vector3 color, cfloat ambient, cfloat diffuse, cfloat specular); DirectionalLight(Vector3 direction, Vector3 color, cfloat ambient, cfloat diffuse, cfloat specular);
virtual Name GetType() const; virtual Name GetType() const;
virtual DirectionalLight *Create();
virtual DirectionalLight *Duplicate();
virtual DirectionalLight *Instance();
}; };
#endif /* LIGHT_H */ #endif /* LIGHT_H */

View File

@ -41,6 +41,16 @@ void SubMesh::Draw(Shader *shader) {
glBindVertexArray(0); glBindVertexArray(0);
} }
SubMesh *SubMesh::Duplicate() {
SubMesh* submesh = new SubMesh();
submesh->VAO = VAO;
submesh->indices = indices;
submesh->material = material;
return submesh;
}
Name Mesh::GetType() const {return "Mesh";} Name Mesh::GetType() const {return "Mesh";}
Mesh::Mesh() {} Mesh::Mesh() {}
@ -51,9 +61,24 @@ Mesh::~Mesh() {
} }
} }
Mesh *Mesh::Create() {
return new Mesh;
}
Mesh *Mesh::Duplicate() { Mesh *Mesh::Duplicate() {
Mesh *dup = new Mesh(*this); Mesh *mesh = static_cast<Mesh*>(Spatial::Duplicate());
return dup; // Duplicate submeshes
mesh->submeshes = SubMeshList();
for (SubMesh *submesh : submeshes) {
mesh->submeshes.push_back(submesh->Duplicate());
}
return mesh;
}
Mesh *Mesh::Instance() {
return static_cast<Mesh*>(Node::Instance());
} }
void Mesh::SetupMesh() { void Mesh::SetupMesh() {

View File

@ -26,6 +26,7 @@ public:
IndexList indices; IndexList indices;
Material material; Material material;
void Draw(Shader *shader); void Draw(Shader *shader);
SubMesh *Duplicate();
private: private:
Id VAO, VBO, EBO; Id VAO, VBO, EBO;
void SetupSubMesh(); void SetupSubMesh();
@ -44,7 +45,9 @@ public:
virtual bool IsDrawable() const {return true;} virtual bool IsDrawable() const {return true;}
virtual void Draw(Shader *shader); virtual void Draw(Shader *shader);
virtual Name GetType() const; virtual Name GetType() const;
Mesh *Duplicate(); virtual Mesh *Create();
virtual Mesh *Duplicate();
virtual Mesh *Instance();
protected: protected:
SubMeshList submeshes; SubMeshList submeshes;
virtual void SetupMesh(); virtual void SetupMesh();

View File

@ -1,8 +1,9 @@
#include "Node.h" #include "Node.h"
#include "Util.h"
Name Node::GetType() const {return "Node";} Name Node::GetType() const {return "Node";}
Node *Node::root = {new Node()}; Node *Node::root = {Node().Instance()};
Node *Node::GetRoot() { Node *Node::GetRoot() {
return root; return root;
} }
@ -13,6 +14,35 @@ bool Node::IsTransformable() const {
return false; return false;
} }
Node* Node::Create() {
return new Node;
}
Node* Node::Duplicate() {
return Create();
}
Node* Node::Instance() {
if (not this->isPrefab) {
Util::Die("Attempt to instance an instanced node!");
}
Node* instance = Duplicate();
instance->isPrefab = false;
instance->children = NodeList();
instance->children.isPrefabList = false;
for (Node *child : children) {
instance->children.Append(child->Instance());
}
return instance;
}
void NodeList::Append(Node *node) { void NodeList::Append(Node *node) {
if (this->isPrefabList and not node->isPrefab) {
Util::Die("Attempt to add instanced node to prefab list!");
}
if (node->isPrefab and not this->isPrefabList) {
Util::Die("Attempt to add prefab node to instanced list!");
}
push_back(node); push_back(node);
} }

View File

@ -9,6 +9,9 @@ class Node; // Forwards declare
class NodeList : public std::vector<Node*> { class NodeList : public std::vector<Node*> {
public: public:
void Append(Node *node); void Append(Node *node);
private:
bool isPrefabList = true;
friend class Node;
}; };
class Node { class Node {
@ -16,11 +19,16 @@ public:
NodeList children; NodeList children;
static Node *GetRoot(); static Node *GetRoot();
virtual bool IsDrawable() const; virtual bool IsDrawable() const;
virtual void Draw(){}; virtual void Draw() {};
virtual bool IsTransformable() const; virtual bool IsTransformable() const;
virtual Name GetType() const; virtual Name GetType() const;
virtual Node* Create();
virtual Node* Instance();
virtual Node* Duplicate();
private: private:
static Node *root; static Node *root;
bool isPrefab = true;
friend class NodeList;
}; };
#endif /* NODE_H */ #endif /* NODE_H */

View File

@ -63,6 +63,22 @@ Skybox::Skybox() {
Name Skybox::GetType() const { return "Skybox"; } Name Skybox::GetType() const { return "Skybox"; }
Skybox *Skybox::Create() {
return new Skybox;
}
Skybox *Skybox::Duplicate() {
Skybox* skybox = static_cast<Skybox*>(Node::Duplicate());
skybox->id = id;
skybox->cube = cube;
return skybox;
}
Skybox *Skybox::Instance() {
return static_cast<Skybox*>(Node::Instance());
}
Skybox *Skybox::FromFiles(const char *right, const char* left, const char* top, const char* bottom, const char* front, const char* back) { Skybox *Skybox::FromFiles(const char *right, const char* left, const char* top, const char* bottom, const char* front, const char* back) {
// HOCUS: https://learnopengl.com/Advanced-OpenGL/Cubemaps // HOCUS: https://learnopengl.com/Advanced-OpenGL/Cubemaps
Skybox *sb = new Skybox(); Skybox *sb = new Skybox();

View File

@ -11,6 +11,9 @@ class Skybox : public Node {
public: public:
Skybox(); Skybox();
virtual Name GetType() const; virtual Name GetType() const;
virtual Skybox *Create();
virtual Skybox *Duplicate();
virtual Skybox *Instance();
static Skybox *FromFiles(const char *right, const char* left, const char* top, const char* bottom, const char* front, const char* back); static Skybox *FromFiles(const char *right, const char* left, const char* top, const char* bottom, const char* front, const char* back);
void DrawSkybox(); void DrawSkybox();
Id id; Id id;

View File

@ -1,3 +1,19 @@
#include "Spatial.h" #include "Spatial.h"
Name Spatial::GetType() const {return "Spatial";} Name Spatial::GetType() const {return "Spatial";}
Spatial *Spatial::Create() {
return new Spatial;
}
Spatial *Spatial::Duplicate() {
Spatial *spatial = static_cast<Spatial*>(Node::Duplicate());
spatial->transform = transform;
return spatial;
}
Spatial *Spatial::Instance() {
return static_cast<Spatial*>(Node::Instance());
}

View File

@ -9,6 +9,9 @@ public:
Transform transform; Transform transform;
virtual bool IsTransformable() const { return true;} virtual bool IsTransformable() const { return true;}
virtual Name GetType() const; virtual Name GetType() const;
virtual Spatial *Create();
virtual Spatial *Duplicate();
virtual Spatial *Instance();
}; };
#endif /* SPATIAL_H */ #endif /* SPATIAL_H */

View File

@ -6,6 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "types.h" #include "types.h"
class Node;
#include "Node.h" #include "Node.h"
namespace Util { namespace Util {

View File

@ -1,7 +1,7 @@
local min = math.min local min = math.min
local max = math.max local max = math.max
local cube
local ball local ball
local ball1
local camera local camera
local vx = 0.0 local vx = 0.0
@ -28,15 +28,15 @@ function init()
camera:MakeCurrent() camera:MakeCurrent()
camera.transform:Translate(0.0, 0.0, 10.0) camera.transform:Translate(0.0, 0.0, 10.0)
light = couch.DirectionalLight.new() local light = couch.DirectionalLight()
light.direction = couch.Vector3(0.0, -1.0, -1.0) light.direction = couch.Vector3(0.0, -1.0, -1.0)
light.color = couch.Vector3(1.0, 1.0, 1.0) light.color = couch.Vector3(1.0, 1.0, 1.0)
light.ambient = 0.2 light.ambient = 0.2
light.diffuse = 1.0 light.diffuse = 1.0
light.specular = 0.1 light.specular = 0.1
couch.Node.GetRoot().children:Append(light) couch.Node.GetRoot().children:Append(light:Instance())
skybox = couch.Skybox.FromFiles( local skybox = couch.Skybox.FromFiles(
"skybox/px.png", "skybox/px.png",
"skybox/nx.png", "skybox/nx.png",
"skybox/py.png", "skybox/py.png",
@ -44,35 +44,37 @@ function init()
"skybox/pz.png", "skybox/pz.png",
"skybox/nz.png" "skybox/nz.png"
) )
couch.Node.GetRoot().children:Append(skybox) couch.Node.GetRoot().children:Append(skybox:Instance())
make_ground() make_ground()
ball = couch.Mesh.FromFile("cube.obj") local cube_prefab = couch.Mesh.FromFile("cube.obj")
material = ball:GetMaterial(0) material = cube_prefab:GetMaterial(0)
material.ambient = RED material.ambient = RED
material.diffuse = RED material.diffuse = RED
ball:SetMaterial(0, material) cube_prefab:SetMaterial(0, material)
couch.Node.GetRoot().children:Append(ball)
local orbiter = couch.Mesh.FromFile("ball.obj") local orbiter = couch.Mesh.FromFile("ball.obj")
orbiter.transform.scale = orbiter.transform.scale * 0.25; orbiter.transform.scale = orbiter.transform.scale * 0.25;
orbiter.transform:Translate(1.0, 0.0, 0.0) orbiter.transform:Translate(1.0, 0.0, 0.0)
ball.children:Append(orbiter) cube_prefab.children:Append(orbiter)
cube = cube_prefab:Instance()
couch.Node.GetRoot().children:Append(cube)
ball1 = couch.Mesh.FromFile("ball.obj") local ball_prefab = couch.Mesh.FromFile("ball.obj")
material = ball_prefab:GetMaterial(0)
print(material.diffuse.b) ball_prefab:SetMaterial(0, material)
material = ball1:GetMaterial(0) ball = ball_prefab:Instance()
ball1:SetMaterial(0, material) couch.Node.GetRoot().children:Append(ball)
couch.Node.GetRoot().children:Append(ball1)
ball1.transform:Translate(0.0, 3.0, 0.0) ball.transform:Translate(0.0, 3.0, 0.0)
trough = couch.TexturedMesh("trough.obj", "wood_lowres.png") local trough_prefab = couch.TexturedMesh("trough.obj", "wood_lowres.png")
trough = trough_prefab:Instance()
couch.Node.GetRoot().children:Append(trough) couch.Node.GetRoot().children:Append(trough)
trough.transform:Translate(10.0, 0.0, 0.0) trough.transform:Translate(10.0, 0.0, 0.0)
scaffold = couch.TexturedMesh("scaffold.obj", "grate_floor_lowres.png", "railing.png") local scaffold_prefab = couch.TexturedMesh("scaffold.obj", "grate_floor_lowres.png", "railing.png")
local scaffold = scaffold_prefab:Instance()
material = scaffold:GetMaterial(0) material = scaffold:GetMaterial(0)
material.alphaScissor = 0.9 material.alphaScissor = 0.9
scaffold:SetMaterial(0, material) scaffold:SetMaterial(0, material)
@ -85,7 +87,8 @@ function init()
couch.Node.GetRoot().children:Append(scaffold) couch.Node.GetRoot().children:Append(scaffold)
scaffold.transform:Translate(-3.0, 3.0, 0.0) scaffold.transform:Translate(-3.0, 3.0, 0.0)
barn = couch.TexturedMesh("barn.obj", "paintedwood.jpg", "barnroof_lowres.png", "wood_lowres.png") local barn_prefab = couch.TexturedMesh("barn.obj", "paintedwood.jpg", "barnroof_lowres.png", "wood_lowres.png")
local barn = barn_prefab:Instance()
material = barn:GetMaterial(0) material = barn:GetMaterial(0)
material.cullBack = false material.cullBack = false
barn:SetMaterial(0, material) barn:SetMaterial(0, material)
@ -109,16 +112,16 @@ function update(delta)
camera.transform.rotation.x = min(max(camera.transform.rotation.x, -3.14 / 2.0), 3.14 / 2.0) camera.transform.rotation.x = min(max(camera.transform.rotation.x, -3.14 / 2.0), 3.14 / 2.0)
cam_rot_y = 0.0 cam_rot_y = 0.0
local loc = ball1.transform.position local loc = ball.transform.position
if loc.y > 4.0 then if loc.y > 4.0 then
ballvy = -1.0 ballvy = -1.0
elseif loc.y < 2.0 then elseif loc.y < 2.0 then
ballvy = 1.0 ballvy = 1.0
end end
ball1.transform.position.y = ball1.transform.position.y + ballvy * delta ball.transform.position.y = ball.transform.position.y + ballvy * delta
ball.transform.rotation.y = ball.transform.rotation.y + 2.0 * delta; cube.transform.rotation.y = cube.transform.rotation.y + 2.0 * delta;
ball.transform.rotation.z = ball.transform.rotation.z + 1.0 * delta; cube.transform.rotation.z = cube.transform.rotation.z + 1.0 * delta;
end end
function action_dir(key, action, pos, neg, curr) function action_dir(key, action, pos, neg, curr)
@ -155,12 +158,12 @@ function make_ground()
ground_prefab.transform.position = couch.Vector3(0.0, -2.0, 0.0) 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.transform.scale = couch.Vector3(3.0, 1.0, 3.0)
ground = couch.Spatial.new() ground = couch.Spatial():Instance()
couch.Node.GetRoot().children:Append(ground) couch.Node.GetRoot().children:Append(ground)
for x = -20, 20, 1 do for x = -20, 20, 1 do
for z = -20, 20, 1 do for z = -20, 20, 1 do
local piece = ground_prefab:Duplicate() local piece = ground_prefab:Instance()
piece.transform.position = couch.Vector3(6.0 * x, -2.0, 6.0 * z) piece.transform.position = couch.Vector3(6.0 * x, -2.0, 6.0 * z)
ground.children:Append(piece) ground.children:Append(piece)
end end

View File

@ -74,3 +74,4 @@ Yeah sure let's do physics
- [ ] Static, Kinematic and Rigidbodies - [ ] Static, Kinematic and Rigidbodies
- [ ] Collision areas - [ ] Collision areas
- [ ] Ray tracing - [ ] Ray tracing
- [ ] Axis pinning

View File

@ -18,8 +18,6 @@
#include "Skybox.h" #include "Skybox.h"
%} %}
%rename("%(strip:[script_])s") "";
typedef float cfloat; typedef float cfloat;
%ignore "cfloat"; %ignore "cfloat";
@ -40,18 +38,6 @@ public:
} }
%ignore "Vector3"; %ignore "Vector3";
%extend Spatial {
static Spatial* script_new() {
return new Spatial();
}
}
%extend DirectionalLight {
static DirectionalLight* script_new() {
return new DirectionalLight();
}
}
%include "types.h" %include "types.h"
%include "constants.h" %include "constants.h"
%include "Node.h" %include "Node.h"