Moved source file locations for easier compiling; cleaned up Makefile; cleaned up opengl code

This commit is contained in:
2022-12-13 18:32:36 +00:00
parent 18eefd4937
commit 60bf5ca7bc
50 changed files with 47 additions and 777 deletions

View File

@@ -0,0 +1,47 @@
#include "3dphysics.h"
/*
btDefaultCollisionConfiguration *collisionConfig {
NULL};
btCollisionDispatcher *dispatcher {
NULL};
btBroadphaseInterface *overlappingPairCache {
NULL};
btSequentialImpulseConstraintSolver *solver {
NULL};
btDiscreteDynamicsWorld *dynamicsWorld {
NULL};
btRigidBody *worldFloor {
NULL};
void btUpdate()
{
// dynamicsWorld->stepSimulation(deltaT);
}
void btInit()
{
// collisionConfig = new btDefaultCollisionConfiguration();
// dispatcher = new btCollisionDispatcher(collisionConfig);
// overlappingPairCache = new btDbvtBroadphase();
// solver = new btSequentialImpulseConstraintSolver;
// dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfig);
// dynamicsWorld->setGravity(btVector3(0.f, -9.8f, 0.f));
// btDebugDrawer = new BulletDebugDrawer_OpenGL();
// dynamicsWorld->setDebugDrawer(btDebugDrawer);
//btDebugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb);
// Add camera and plane to world
// dynamicsWorld->addRigidBody(camera.body);
// camera.body->setGravity(btVector3(0.f, 0.f, 0.f));
// Create and add plane
// btStaticPlaneShape* floorShape = new btStaticPlaneShape(btVector3(0.f, 1.f, 0.f), 0.f);
// btDefaultMotionState* motionState = new btDefaultMotionState();
// btVector3 bodyInertia;
// btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(0.f, motionState, floorShape, bodyInertia);
// worldFloor = new btRigidBody(bodyCI);
// dynamicsWorld->addRigidBody(worldFloor);
}
*/

View File

@@ -0,0 +1,5 @@
#ifndef THREEDPHYSICS_H
#define THREEDPHYSICS_H
#endif

220
source/engine/3d/3pfollow.c Normal file
View File

@@ -0,0 +1,220 @@
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
#include "3pfollow.h"
#include <math.h>
// void ThirdPersonFollow::_ready() {
// Target = dynamic_cast<Spatial*>(get_node(TargetPath));
// ExternalFrame = dynamic_cast<Spatial*>(get_node(ExternalFramePath));
// }
// void ThirdPersonFollow::_process(float delta_time) {
// if (Target != nullptr) {
// // Get the frame of reference
// if (has_node(ExternalFramePath) && get_node(ExternalFramePath) != this)
// TFOR = dynamic_cast<Spatial*>(get_node(ExternalFramePath))->get_global_transform();
// else
// TFOR = Transform(Basis(glm::vec3::RIGHT(), glm::vec3::UP(), glm::vec3::FORWARD()), glm::vec3::ZERO());
// CalculateTargetOffset();
// TargetPosition = CalculatePosition();
// translate(to_local(FrameBasedVectorLerp(get_global_translation(), TargetPosition, PositionSpeeds, delta_time)));
// set_rotation_degrees(get_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// }
// // For rotation
// // TODO: Add rotation offset in properly
// //this->SetActorRotation(FMath::Lerp(this->GetActorRotation(), TargetRotation, RotationSpeed * DeltaTime));
// //this->set_rotation(glm::quat(this->get_rotation().slerp(RotationOffset, RotationSpeed * DeltaTime)).get_euler());
// //set_global_rotation_degrees(get_global_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// // TODO: Figure out how to translate rotation to a global rotation
// }
/*
glm::vec3 ThirdPersonFollow::CalculatePosition()
{
glm::vec3 p1 = CalculateCenter();
glm::vec3 p2 =
XDirPosts ? GetPostsOffset(TFOR.Right(),
FloatWidths.
x) : GetExtentsOffset(TFOR.Right(),
FloatWidths.x,
TargetOffset.x,
AnchorWidths.x);
glm::vec3 p3 =
YDirPosts ? GetPostsOffset(TFOR.Up(),
FloatWidths.
y) : GetExtentsOffset(TFOR.Up(),
FloatWidths.y,
TargetOffset.y,
AnchorWidths.y);
glm::vec3 p4 =
ZDirPosts ? GetPostsOffset(TFOR.Back(),
FloatWidths.
z) : GetExtentsOffset(TFOR.Back(),
FloatWidths.z,
TargetOffset.z,
AnchorWidths.z);
return p1 + p2 + p3 + p4;
}
glm::vec3 ThirdPersonFollow::CalculateCenter()
{
return Target->get_global_translation() +
TFOR.TransformDirection(Offset) + (mytransform->Back() * Distance);
}
glm::vec3 ThirdPersonFollow::
GetPostsOffset(const glm::vec3 & DirectionVector, float AnchorWidth)
{
float dot = glm::dot(Target->Forward(), DirectionVector);
return DirectionVector * (dot >= 0 ? AnchorWidth : AnchorWidth * -1);
}
glm::vec3 ThirdPersonFollow::
GetExtentsOffset(const glm::vec3 & DirectionVector, float AnchorWidth,
float TOffset, float Width)
{
float negated_offset_sign = ((0 <= TOffset) - (TOffset < 0)) * -1.f;
float TotalWidth = AnchorWidth + Width;
if (glm::abs(TOffset) > TotalWidth
&& !glm::epsilonEqual(glm::abs(TOffset), TotalWidth, 0.5f))
return DirectionVector * TotalWidth * negated_offset_sign;
else {
if (glm::abs(TOffset) >= AnchorWidth)
return DirectionVector * AnchorWidth * negated_offset_sign;
else
return DirectionVector * TOffset * -1.f;
}
return glm::vec3(0.f);
}
glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Speeds,
float Tick)
{
// Previously "FORTransform.TransformVector(Speeds)
glm::vec3 TSpeed = glm::abs(TFOR.TransformDirection(Speeds));
glm::vec3 TOffset = glm::abs(TFOR.TransformDirection(TargetOffset));
glm::vec3 TAnchorWidths =
glm::abs(TFOR.TransformDirection(AnchorWidths));
glm::vec3 TFloatWidths =
glm::abs(TFOR.TransformDirection(FloatWidths));
// If these are true, that means to use the anchor speed instead of the normal speed.
// True if the offset is beyond the anchor plus the width
bool bUseX = GetLerpParam(TOffset.x, TAnchorWidths.x, TFloatWidths.x);
bool bUseY = GetLerpParam(TOffset.y, TAnchorWidths.y, TFloatWidths.y);
bool bUseZ = GetLerpParam(TOffset.z, TAnchorWidths.z, TFloatWidths.z);
float xAlpha =
glm::clamp((bUseX ? AnchorSpeed : TSpeed.x) * Tick, 0.f, 1.f);
float yAlpha =
glm::clamp((bUseY ? AnchorSpeed : TSpeed.y) * Tick, 0.f, 1.f);
float zAlpha =
glm::clamp((bUseZ ? AnchorSpeed : TSpeed.z) * Tick, 0.f, 1.f);
return VectorLerpPiecewise(From, To,
glm::vec3(xAlpha, yAlpha, zAlpha));
}
int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e)
{
return fabs(a - b) < e;
}
int lerpparam(float offset, float anchorwidth, float floatwidth)
{
return (offset > (anchorwidth + floatwidth)) && !float_epsilon(anchorwidth + floatwidth, offset, 0.5f);
}
mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3])
{
from[0] = from[0] + (to[0] - from[0]) * a[0];
from[1] = from[1] + (to[1] - from[1]) * a[1];
from[2] = from[2] + (to[2] - from[2]) * a[2];
}
void follow_calctargets()
{
}
void ThirdPersonFollow::CalculateTargets()
{
// For translation
TargetPosition = CalculatePosition();
// For rotation
// TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation
TargetRotation =
RemoveLockedRotation(glm::quat
(mytransform->
get_global_transform()->get_origin() -
Target->
get_global_transform()->get_origin()));
}
follow_removelockedrot()
{
}
glm::quat ThirdPersonFollow::
RemoveLockedRotation(const glm::quat & CurrentRotation)
{
glm::vec3 NewRotator;
glm::vec3 CurrentRotator = glm::eulerAngles(CurrentRotation);
//
NewRotator.x =
LockRoll ? mytransform->get_rotation().x : CurrentRotator.x;
NewRotator.y =
LockPitch ? mytransform->get_rotation().y : CurrentRotator.y;
NewRotator.z =
LockYaw ? mytransform->get_rotation().z : CurrentRotator.z;
return glm::quat(NewRotator);
}
// The target offset is the value of where the target is compared to where he "should" be based on where
// the camera is. It is what the camera needs to move to be centered on the target
void ThirdPersonFollow::CalculateTargetOffset()
{
glm::vec3 p1 =
(mytransform->Forward() * Distance) +
TFOR.TransformDirection(Offset) +
mytransform->get_global_translation();
glm::vec3 p2 =
TFOR.InverseTransformDirection(Target->get_global_translation());
glm::vec3 p3 = TFOR.InverseTransformDirection(p1);
TargetOffset = p2 - p3;
}
void follow_targetoffset()
{
mfloat_t p1[3], p2[3], p3[3] = {0};
}
*/

189
source/engine/3d/3pfollow.h Normal file
View File

@@ -0,0 +1,189 @@
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
#ifndef THIRDPERSONFOLLOW_H
#define THIRDPERSONFOLLOW_H
#include "transform.h"
struct follow {
float distance;
mfloat_t target_rot[4];
};
mfloat_t *follow_calccenter();
mfloat_t *follow_postoffset();
mfloat_t *extentsoffset();
mfloat_t *framebasedveclerp();
int lerpparam(float offset, float anchorwidth, float floatwidth);
mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3]);
void follow_calctargets();
mfloat_t *follow_removelockedrot();
void follow_targetoffset(struct follow *follow);
int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e);
/*
//////////////////////////////////////////////////////////////////////////
// A good camera.
//////////////////////////////////////////////////////////////////////////
class ThirdPersonFollow {
public:
enum CameraType {
STATIONARY,
TRANSLATING,
ROTATING,
SPLINE
};
enum CameraTransition {
NONE,
CROSSDISSOLVE,
WIPE,
DIP
};
enum FrameOfReference {
LOCAL,
WORLD,
EXTERNAL
};
ThirdPersonFollow() {
// Rotation
RotationSpeed = 10.0f;
LockPitch = LockYaw = LockRoll = true;
XDirPosts = false;
YDirPosts = false;
ZDirPosts = false;
// Translation
//FloatWidths = AnchorWidths = CenterVector = glm::vec3(0, 0, 0);
PositionSpeeds = glm::vec3(2.f, 2.f, 2.f);
//TranslationScales = glm::vec3(1, 1, 1);
// Frame settings
Offset = glm::vec3(0.f, 0.f, 0.f);
Distance = 10;
AnchorSpeed = 80;
} ~ThirdPersonFollow() {
}
Transform *mytransform;
// An actor that can be given for the camera to base its movement around
// instead of itself. Makes most sense for this to be stationary
Transform *ExternalFrame = nullptr;
void SetExternalFrame(Transform * val) {
ExternalFrame = val;
}
// The target the camera "looks" at, used for calculations
Transform *Target = nullptr;
void SetTarget(Transform * val) {
Target = val;
}
// Offset from the target
glm::vec3 Offset;
// How far away should the camera act from the target
float Distance;
///////////////////////////////////////////////////////////////////////////
// Translation variables. In this mode, the camera doesn't rotate to look
// at the target, it only moves around the world.
///////////////////////////////////////////////////////////////////////////
/// "Posts" for each direction in 3D space. These are items that the target
/// is allowed to move within without the camera following along.
bool XDirPosts;
bool YDirPosts;
bool ZDirPosts;
/// The range in ecah direction the camera floats. While within this range,
/// the camera will smoothly glide to the desired position.
glm::vec3 FloatWidths;
/// The clamp range for each direction. If the camera reaches this range,
/// it will stick and not move any further.
glm::vec3 AnchorWidths;
/// When floating to the target, the speed to float.
glm::vec3 PositionSpeeds;
//////////////////////////////////////////////////////////////////////////
// Rotation variables. Used for the camera's rotation mode, where it
// follows the Target without translating.
//////////////////////////////////////////////////////////////////////////
/// Variables to lock its rotation in any of the three directions
bool LockRoll;
bool LockPitch;
bool LockYaw;
glm::vec3 RotationOffset;
/// The speed of rotation
float RotationSpeed;
private:
void CalculateTargetOffset();
// Transform of frame of reference
Transform TFOR;
/// The calculated offset based on frames of reference
glm::vec3 TargetOffset;
glm::vec3 TargetPosition;
glm::quat TargetRotation;
void CalculateTargets();
// Calculates
glm::vec3 CalculatePosition();
glm::vec3 CalculateCenter();
/// Given a direction and width, find the offsets.
glm::vec3 GetPostsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth);
/// Given anchors, what's the anchor width?
glm::vec3 GetExtentsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth, float TOffset,
float Width);
glm::quat RemoveLockedRotation(const glm::quat & CurrentRotation);
glm::vec3 FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Speeds, float Tick);
glm::vec3 VectorLerpPiecewise(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Alpha);
bool GetLerpParam(const float Offst, const float AnchorWidth,
const float FloatWidth);
/// Set to a value that gives good clamping, smoothly. Activates when
/// the target is out of range.
float AnchorSpeed;
};
*/
#endif

202
source/engine/3d/light.c Normal file
View File

@@ -0,0 +1,202 @@
#include "light.h"
#include <stdbool.h>
/*
void Light::serialize(FILE * file)
{
GameObject::serialize(file);
SerializeFloat(file, &strength);
SerializeVec3(file, (float *) &color);
SerializeBool(file, &dynamic);
}
void Light::deserialize(FILE * file)
{
GameObject::deserialize(file);
DeserializeFloat(file, &strength);
DeserializeVec3(file, (float *) &color);
DeserializeBool(file, &dynamic);
}
static const mfloat_t dlight_init_rot[3] = { 80.f, 120.f, 165.f };
struct mDirectionalLight *dLight = NULL;
struct mDirectionalLight *MakeDLight()
{
if (dLight != NULL) {
dLight =
(struct mDirectionalLight *)
malloc(sizeof(struct mDirectionalLight));
quat_from_euler(dLight->light.obj.transform.rotation,
dlight_init_rot);
return dLight;
}
return dLight;
}
void dlight_prepshader(struct mDirectionalLight *light,
struct shader *shader)
{
mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform);
shader_setvec3(shader, "dirLight.direction", fwd);
shader_setvec3(shader, "dirLight.color", light->light.color);
shader_setfloat(shader, "dirLight.strength", light->light.strength);
}
static struct mPointLight *pointLights[4];
static int numLights = 0;
struct mPointLight *MakePointlight()
{
if (numLights < 4) {
struct mPointLight *light =
(struct mPointLight *) malloc(sizeof(struct mPointLight));
pointLights[numLights++] = light;
light->light.strength = 0.2f;
light->constant = 1.f;
light->linear = 0.9f;
light->quadratic = 0.032f;
return light;
}
return NULL;
}
static void prepstring(char *buffer, char *prepend, const char *append)
{
snprintf(buffer, 100, "%s%s", prepend, append);
}
void pointlights_prepshader(struct shader *shader)
{
for (int i = 0; i < numLights; i++)
pointlight_prepshader(pointLights[i], shader, i);
}
void pointlight_prepshader(struct mPointLight *light,
struct shader *shader, int num)
{
shader_use(shader);
char prepend[100] = { '\0' };
snprintf(prepend, 100, "%s%d%s", "pointLights[", num, "].");
char str[100] = { '\0' };
prepstring(str, prepend, "position");
shader_setvec3(shader, str, light->light.obj.transform.position);
prepstring(str, prepend, "constant");
shader_setfloat(shader, str, light->constant);
prepstring(str, prepend, "linear");
shader_setfloat(shader, str, light->linear);
prepstring(str, prepend, "quadratic");
shader_setfloat(shader, str, light->quadratic);
prepstring(str, prepend, "strength");
shader_setfloat(shader, str, light->light.strength);
prepstring(str, prepend, "color");
shader_setvec3(shader, str, light->light.color);
}
static struct mSpotLight *spotLights[4];
static int numSpots = 0;
struct mSpotLight *MakeSpotlight()
{
if (numSpots < 4) {
struct mSpotLight *light =
(struct mSpotLight *) malloc(sizeof(struct mSpotLight));
spotLights[numSpots++] = light;
return light;
}
return NULL;
}
void spotlights_prepshader(struct shader *shader)
{
for (int i = 0; i < numSpots; i++)
spotlight_prepshader(spotLights[i], shader, i);
}
void spotlight_prepshader(struct mSpotLight *light, struct shader *shader,
int num)
{
mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform);
shader_use(shader);
shader_setvec3(shader, "spotLight.position",
light->light.obj.transform.position);
shader_setvec3(shader, "spotLight.direction", fwd);
shader_setvec3(shader, "spotLight.color", light->light.color);
shader_setfloat(shader, "spotLight.strength", light->light.strength);
shader_setfloat(shader, "spotLight.cutoff", light->cutoff);
shader_setfloat(shader, "spotLight.distance", light->distance);
shader_setfloat(shader, "spotLight.outerCutoff", light->outerCutoff);
shader_setfloat(shader, "spotLight.linear", light->linear);
shader_setfloat(shader, "spotLight.quadratic", light->quadratic);
shader_setfloat(shader, "spotLight.constant", light->constant);
}
*/
/*
void light_gui(struct mLight *light)
{
object_gui(&light->obj);
if (nk_tree_push(ctx, NK_TREE_NODE, "Light", NK_MINIMIZED)) {
nk_property_float(ctx, "Strength", 0.f, &light->strength, 1.f, 0.01f, 0.001f);
// ImGui::ColorEdit3("Color", &light->color[0]);
nk_checkbox_label(ctx, "Dynamic", (bool *) &light->dynamic);
nk_tree_pop(ctx);
}
}
void pointlight_gui(struct mPointLight *light)
{
light_gui(&light->light);
if (nk_tree_push(ctx, NK_TREE_NODE, "Point Light", NK_MINIMIZED)) {
nk_property_float(ctx, "Constant", 0.f, &light->constant, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Linear", 0.f, &light->linear, 0.3f, 0.01f, 0.001f);
nk_property_float(ctx, "Quadratic", 0.f, &light->quadratic, 0.3f, 0.01f, 0.001f);
nk_tree_pop(ctx);
}
}
void spotlight_gui(struct mSpotLight *spot)
{
light_gui(&spot->light);
if (nk_tree_push(ctx, NK_TREE_NODE, "Spotlight", NK_MINIMIZED)) {
nk_property_float(ctx, "Linear", 0.f, &spot->linear, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Quadratic", 0.f, &spot->quadratic, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Distance", 0.f, &spot->distance, 200.f, 1.f, 0.1f, 200.f);
nk_property_float(ctx, "Cutoff Degrees", 0.f, &spot->cutoff, 0.7f, 0.01f, 0.001f);
nk_property_float(ctx, "Outer Cutoff Degrees", 0.f, &spot->outerCutoff, 0.7f, 0.01f, 0.001f);
nk_tree_pop(ctx);
}
}
*/

63
source/engine/3d/light.h Normal file
View File

@@ -0,0 +1,63 @@
#ifndef LIGHT_H
#define LIGHT_H
#include <stdint.h>
struct mLight {
struct gameobject *go;
uint8_t color[3];
float strength;
int dynamic;
int on;
};
/*
struct mPointLight {
struct mLight light;
float constant;
float linear;
float quadratic;
};
struct mPointLight *MakePointlight();
void pointlight_prepshader(struct mPointLight *light,
struct shader *shader, int num);
void pointlights_prepshader(struct shader *shader);
struct mSpotLight {
struct mLight light;
float constant;
float linear;
float quadratic;
float distance;
float cutoff;
float outerCutoff;
};
struct mSpotLight *MakeSpotlight();
void spotlight_gui(struct mSpotLight *light);
void spotlight_prepshader(struct mSpotLight *light, struct shader *shader,
int num);
void spotlights_prepshader(struct shader *shader);
struct mDirectionalLight {
struct mLight light;
};
void dlight_prepshader(struct mDirectionalLight *light,
struct shader *shader);
struct mDirectionalLight *MakeDLight();
extern struct mDirectionalLight *dLight;
*/
void light_gui(struct mLight *light);
void pointlight_gui(struct mPointLight *light);
void spotlight_gui(struct mSpotLight *spot);
#endif

132
source/engine/3d/mesh.c Normal file
View File

@@ -0,0 +1,132 @@
#include "mesh.h"
#include "render.h"
#include "shader.h"
#include "texture.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void DrawMesh(struct mesh *mesh, struct shader *shader)
{
// bind appropriate textures
uint32_t diffuseNr = 1;
uint32_t specularNr = 1;
uint32_t normalNr = 1;
uint32_t heightNr = 1;
for (int i = 0; i < (mesh->te - mesh->textures); i++) {
glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN)
char number = 0;
// TODO: malloc every single frame ... nope! Change to stack
/*char *name =
(char *) malloc(sizeof(char) *
(strlen(mesh->textures[i].type) + 2));*/
if (mesh->textures[i].type == TEX_DIFF)
number = diffuseNr++;
else if (mesh->textures[i].type == TEX_SPEC)
number = specularNr++;
else if (mesh->textures[i].type == TEX_NORM)
number = normalNr++;
else if (mesh->textures[i].type == TEX_HEIGHT)
number = heightNr++;
/*
glUniform1i(glGetUniformLocation(shader->id, name), i);
glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id);
free(name);
*/
}
// draw mesh
glBindVertexArray(mesh->VAO);
DrawMeshAgain(mesh);
// DEBUG
// triCount += indices.size() / 3;
}
void DrawMeshAgain(struct mesh *mesh)
{
glDrawElements(GL_TRIANGLES, (mesh->ie - mesh->indices),
GL_UNSIGNED_INT, 0);
}
struct mesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve,
uint32_t * indices, uint32_t * ie,
struct Texture *textures, struct Texture *te)
{
struct mesh *newmesh = (struct mesh *) malloc(sizeof(struct mesh));
newmesh->vertices = vertices;
newmesh->ve = ve;
newmesh->indices = indices;
newmesh->ie = ie;
newmesh->textures = textures;
newmesh->te = te;
setupmesh(newmesh);
return newmesh;
}
void setupmesh(struct mesh *mesh)
{
// create buffers/arrays
glGenVertexArrays(1, &mesh->VAO);
glGenBuffers(1, &mesh->VBO);
glGenBuffers(1, &mesh->EBO);
glBindVertexArray(mesh->VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to vevc array which
// again translates to 3/2 floats which translates to a byte array.
glBufferData(GL_ARRAY_BUFFER,
(mesh->ve - mesh->vertices) * sizeof(struct Vertex),
&mesh->vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(mesh->ie - mesh->indices) * sizeof(uint32_t),
&mesh->indices[0], GL_STATIC_DRAW);
// set the vertex attribute pointers
// vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) 0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Normal[3]));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, TexCoords[2]));
// vertex tangent
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Tangent[3]));
// vertex bitangent
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Bitangent[3]));
// Bone ids
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex,
m_BoneIDs
[MAX_BONE_INFLUENCE]));
// Weights
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, m_Weights));
glBindVertexArray(0);
}

41
source/engine/3d/mesh.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef MESH_H
#define MESH_H
#include "mathc.h"
#include <stdint.h>
struct shader;
struct Texture;
#define MAX_BONE_INFLUENCE 4
struct Vertex {
mfloat_t Position[3];
mfloat_t Normal[3];
mfloat_t TexCoords[2];
mfloat_t Tangent[3];
mfloat_t Bitangent[3];
int m_BoneIDs[MAX_BONE_INFLUENCE];
float m_Weights[MAX_BONE_INFLUENCE];
};
struct mesh {
struct Vertex *vertices;
struct Vertex *ve;
uint32_t *indices;
uint32_t *ie;
struct Texture *textures;
struct Texture *te;
uint32_t VAO, VBO, EBO;
};
struct mesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve,
uint32_t * indices, uint32_t * ie,
struct Texture *textures, struct Texture *te);
void setupmesh(struct mesh *mesh); /* Loads mesh into the GPU */
void DrawMesh(struct mesh *mesh, struct shader *shader);
void DrawMeshAgain(struct mesh *mesh); /* Draws whatever mesh was drawn last */
#endif

282
source/engine/3d/model.c Normal file
View File

@@ -0,0 +1,282 @@
#include "model.h"
#include "mesh.h"
#include "resources.h"
#include "shader.h"
#include <cgltf.h>
#include <string.h>
#include <stdlib.h>
#include "log.h"
static struct model *lastRendered;
static struct model *loadedModels[100];
static struct model **lastModel = loadedModels;
static void processnode();
static void processmesh();
static void processtexture();
struct model *GetExistingModel(const char *path)
{
struct model **model = loadedModels;
while (model++ != lastModel) {
if (!strcmp(path, (*model)->path))
goto end;
return MakeModel(path);
}
end:
return NULL;
}
/* TODO: Make this a hash compare for speedup */
struct model *MakeModel(const char *path)
{
char *modelPath =
(char *) malloc(sizeof(char) *
(strlen(DATA_PATH) + strlen(path) + 1));
modelPath[0] = '\0';
strcat(modelPath, DATA_PATH);
strcat(modelPath, path);
printf
("Created new model with modelPath %s, from data_path %s and path %s\n",
modelPath, DATA_PATH, path);
struct model *newmodel =
(struct model *) malloc(sizeof(struct model));
newmodel->path = path;
loadmodel(newmodel);
*lastModel++ = newmodel;
return newmodel;
}
// TODO: Come back to this; simple optimization
void draw_model(struct model *model, struct shader *shader)
{
if (lastRendered != model) {
lastRendered = model;
for (int i = 0; i < (model->mp - model->meshes); i++)
DrawMesh(&model->meshes[i], shader);
} else {
for (uint32_t i = 0; i < (model->mp - model->meshes); i++)
DrawMeshAgain(&model->meshes[i]);
}
}
void loadmodel(struct model *model)
{
YughInfo("Loading model at path %s", model->path);
/*
// Load model with cgltf
cgltf_options options = {0};
cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, model->path, &data);
meshes = (struct mesh*)malloc(sizeof(Mesh)*cgltf_data->meshes_count);
directory = get_directory_from_path(model->path);
for (int i = 0; i < data->nodes_count; i++) {
if (data->nodes[i]->mesh) {
for (int j = 0; j < data->nodes[i]->mesh->primatives_count; j++) {
for (int k = 0; k < data->nodes[i]->mesh->primatives[j]->attributes_count; k++) {
switch(data->nodes[i]->mesh->primatives[j]->attributes[k]->type) {
case cgltf_attribute_type_position:
Vertex *vs = (Vertex*)malloc(sizeof(Vertex) * cgltf_accessor_unpack_floats(:::attributes[k]->accesor, NULL, attributes[k]->accessor.count);
cgltf_accessor_unpack_floats(:::attributes[k]->accessor, vs, attributes[k]->accessor.count);
break;
case cgltf_attribute_type_normal:
break;
case cgltf_attribute_type_tangent:
break;
case cgltf_attribute_type_texcoord:
break;
}
}
}
}
}
}
*/
/* TODO: DELETE
// read file via ASSIMP
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path,
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace);
// check for errors
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE
|| !scene->mRootNode) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"ASSIMP error: %s",
importer.GetErrorString());
return;
}
directory = get_directory_from_path(path);
meshes = (Mesh *) malloc(sizeof(Mesh) * 100);
mp = meshes;
// process ASSIMP's root node recursively
processNode(scene->mRootNode, scene); */
}
static void processnode()
{
/*
for (uint32_t i = 0; i < node->mNumMeshes; i++) {
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
*mp = processMesh(mesh, scene);
mp++;
}
for (uint32_t i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene);
}
*/
}
static void processmesh()
{
/*
Vertex *vertices =
(Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices);
Vertex *vp = vertices + mesh->mNumVertices;
Vertex *p = vertices;
for (int i = 0; i < mesh->mNumVertices; i++) {
// positions
(p + i)->Position.x = mesh->mVertices[i][0];
(p + i)->Position.y = mesh->mVertices[i][1];
(p + i)->Position.z = mesh->mVertices[i][2];
// normals
if (mesh->HasNormals()) {
(p + i)->Normal.x = mesh->mNormals[i][0];
(p + i)->Normal.y = mesh->mNormals[i].y;
(p + i)->Normal.z = mesh->mNormals[i].z;
}
// texture coordinates
if (mesh->mTextureCoords[0]) {
glm::vec2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
(p + i)->TexCoords.x = mesh->mTextureCoords[0][i].x;
(p + i)->TexCoords.y = mesh->mTextureCoords[0][i].y;
// tangent
(p + i)->Tangent.x = mesh->mTangents[i].x;
(p + i)->Tangent.y = mesh->mTangents[i].y;
(p + i)->Tangent.z = mesh->mTangents[i].z;
// bitangent
(p + i)->Bitangent.x = mesh->mBitangents[i].x;
(p + i)->Bitangent.y = mesh->mBitangents[i].y;
(p + i)->Bitangent.z = mesh->mBitangents[i].z;
} else
(p + i)->TexCoords = glm::vec2(0.0f, 0.0f);
}
// TODO: Done quickly, find better way. Go through for loop twice!
int numindices = 0;
// now walk through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
numindices += mesh->mFaces[i].mNumIndices;
}
uint32_t *indices = (uint32_t *) malloc(sizeof(uint32_t) * numindices);
uint32_t *ip = indices;
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
for (uint32_t j = 0; j < mesh->mFaces[i].mNumIndices; j++) {
*ip = mesh->mFaces[i].mIndices[j];
ip++;
}
}
// std::vector<Texture> textures;
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
// TODO: Allocating 100 to be safe, can probably be way less
textures_loaded = (Texture *) malloc(sizeof(Texture) * 100);
tp = textures_loaded;
// we assume a convention for sampler names in the shaders. Each diffuse texture should be named
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
// Same applies to other texture as the following list summarizes:
// diffuse: texture_diffuseN
// specular: texture_specularN
// normal: texture_normalN
// 1. diffuse maps
loadMaterialTextures(material, aiTextureType_DIFFUSE,
"texture_diffuse");
// 2. specular maps
loadMaterialTextures(material, aiTextureType_SPECULAR,
"texture_specular");
// 3. normal maps
loadMaterialTextures(material, aiTextureType_NORMALS,
"texture_normal");
// 4. height maps
loadMaterialTextures(material, aiTextureType_AMBIENT,
"texture_height");
// return a mesh object created from the extracted mesh data
return Mesh(vertices, vp, indices, ip, textures_loaded, tp);
*/
}
// TODO: This routine mallocs inside the function
static void processtexture()
{
/*
for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
for (Texture * tpp = textures_loaded; tpp != tp; tpp++) {
if (strcmp(tpp->path, str.data) == 0)
goto next; // Check if we already have this texture
}
tp->id = TextureFromFile(str.data, this->directory);
tp->type = (char *) malloc(sizeof(char) * strlen(typeName));
strcpy(tp->type, typeName);
tp->path = (char *) malloc(sizeof(char) * strlen(str.data));
strcpy(tp->path, str.data);
tp++;
next:;
}
*/
}

26
source/engine/3d/model.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef MODEL_H
#define MODEL_H
struct mesh;
struct shader;
struct model {
struct mesh *meshes;
struct mesh *mp;
char *directory;
const char *path;
char *name;
};
/* Get the model at a path, or create and return if it doesn't exist */
struct model *GetExistingModel(const char *path);
/* Make a Model struct */
struct model *MakeModel(const char *path);
/* Load a model from memory into the GPU */
void loadmodel(struct model *model);
void draw_model(struct model *model, struct shader *shader);
#endif

126
source/engine/3d/skybox.c Normal file
View File

@@ -0,0 +1,126 @@
#include "skybox.h"
#include "shader.h"
#include "camera.h"
#include <string.h>
#include <stdlib.h>
#include "openglrender.h"
static const float skyboxVertices[216] = {
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
struct mSkybox *MakeSkybox(const char *cubemap)
{
struct mSkybox *newskybox =
(struct mSkybox *) malloc(sizeof(struct mSkybox));
newskybox->shader = MakeShader("skyvert.glsl", "skyfrag.glsl");
shader_compile(newskybox->shader);
glGenVertexArrays(1, &newskybox->VAO);
glGenBuffers(1, &newskybox->VBO);
glBindVertexArray(newskybox->VAO);
glBindBuffer(GL_ARRAY_BUFFER, newskybox->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void *) 0);
shader_use(newskybox->shader);
shader_setint(newskybox->shader, "skybox", 0);
/*
const char *faces[6] =
{ "right.jpg", "left.jpg", "top.jpg", "bottom.jpg", "front.jpg",
"back.jpg"
};
*/
glGenTextures(1, &newskybox->id);
glBindTexture(GL_TEXTURE_CUBE_MAP, newskybox->id);
/*char buf[100] = { '\0' };*/
for (int i = 0; i < 6; i++) {
/*
buf[0] = '\0';
strcat(buf, cubemap);
strcat(buf, "/");
strcat(buf, faces[i]);
IMG_Load(buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 2048,
2048, 0, GL_RGB, GL_UNSIGNED_BYTE, data->pixels);
*/
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE);
return newskybox;
}
void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera)
{
shader_use(skybox->shader);
mfloat_t view[16] = { 0.f };
getviewmatrix(view, camera);
shader_setmat4(skybox->shader, "skyview", view);
// skybox cube
glBindVertexArray(skybox->VAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->id);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}

17
source/engine/3d/skybox.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef SKYBOX_H
#define SKYBOX_H
struct mCamera;
struct mSkybox {
unsigned int VAO;
unsigned int VBO;
unsigned int id;
struct shader *shader;
};
struct mSkybox *MakeSkybox(const char *cubemap);
void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera);
#endif

View File

@@ -0,0 +1,94 @@
#include "static_actor.h"
//ADDMAKE(StaticActor);
static struct mStaticActor *models[100];
static int numModels = 0;
static struct mStaticActor *shadow_casters[100];
static int numShadowCasters = 0;
struct mStaticActor *curActor = NULL;
void staticactor_draw_dbg_color_pick(struct shader *s)
{
for (int i = 0; i < numModels; i++) {
shader_setvec3(s, "PickingColor", models[i]->obj.editor.color);
setup_model_transform(&models[i]->obj.transform, s, 1.f);
//models[i]->obj.draw(s);
}
}
void staticactor_draw_models(struct shader *s)
{
for (int i = 0; i < numModels; i++) {
setup_model_transform(&models[i]->obj.transform, s, 1.f);
draw_model(models[i]->model, s);
}
}
void staticactor_draw_shadowcasters(struct shader *s)
{
for (int i = 0; i < numShadowCasters; i++) {
setup_model_transform(&shadow_casters[i]->obj.transform, s, 1.f);
//models[i]->obj.draw(s);
}
}
/*
void StaticActor::serialize(FILE * file)
{
GameObject::serialize(file);
SerializeBool(file, &castShadows);
Serializecstr(file, currentModelPath);
}
void StaticActor::deserialize(FILE * file)
{
GameObject::deserialize(file);
DeserializeBool(file, &castShadows);
Deserializecstr(file, currentModelPath, MAXPATH);
curActor = this;
set_new_model(currentModelPath);
}
*/
struct mStaticActor *MakeStaticActor(const char *modelPath)
{
struct mStaticActor *newsa =
(struct mStaticActor *) malloc(sizeof(struct mStaticActor));
newsa->model = GetExistingModel(modelPath);
models[numModels++] = newsa;
return newsa;
}
/*
Serialize *make_staticactor()
{
StaticActor *nactor = (StaticActor *) malloc(sizeof(StaticActor));
return nactor;
}
*/
#include "nuke.h"
void staticactor_gui(struct mStaticActor *sa)
{
object_gui(&sa->obj);
if (nk_tree_push(ctx, NK_TREE_NODE, "Model", NK_MINIMIZED)) {
nk_checkbox_label(ctx, "Cast Shadows", &sa->castShadows);
nk_labelf(ctx, NK_TEXT_LEFT, "Model path: %s", sa->currentModelPath);
//ImGui::SameLine();
if (nk_button_label(ctx, "Load model")) {
//asset_command = set_new_model;
curActor = sa;
}
}
}

View File

@@ -0,0 +1,24 @@
#ifndef STATIC_ACTOR_H
#define STATIC_ACTOR_H
#include "gameobject.h"
#include "model.h"
#include "shader.h"
struct mStaticActor {
struct gameobject obj;
struct model *model;
char *modelPath;
char currentModelPath[MAXPATH];
bool castShadows;
};
void staticactor_draw_dbg_color_pick(struct shader *s);
void staticactor_draw_models(struct shader *s);
void staticactor_draw_shadowcasters(struct shader *s);
struct mStaticActor *MakeStaticActor();
void staticactor_gui(struct mStaticActor *sa);
extern struct mStaticActor *curActor;
#endif