Moved source file locations for easier compiling; cleaned up Makefile; cleaned up opengl code
This commit is contained in:
47
source/engine/3d/3dphysics.c
Normal file
47
source/engine/3d/3dphysics.c
Normal 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);
|
||||
}
|
||||
*/
|
||||
5
source/engine/3d/3dphysics.h
Normal file
5
source/engine/3d/3dphysics.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#ifndef THREEDPHYSICS_H
|
||||
#define THREEDPHYSICS_H
|
||||
|
||||
|
||||
#endif
|
||||
220
source/engine/3d/3pfollow.c
Normal file
220
source/engine/3d/3pfollow.c
Normal 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
189
source/engine/3d/3pfollow.h
Normal 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
202
source/engine/3d/light.c
Normal 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
63
source/engine/3d/light.h
Normal 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
132
source/engine/3d/mesh.c
Normal 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
41
source/engine/3d/mesh.h
Normal 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
282
source/engine/3d/model.c
Normal 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
26
source/engine/3d/model.h
Normal 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
126
source/engine/3d/skybox.c
Normal 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
17
source/engine/3d/skybox.h
Normal 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
|
||||
94
source/engine/3d/static_actor.c
Normal file
94
source/engine/3d/static_actor.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
source/engine/3d/static_actor.h
Normal file
24
source/engine/3d/static_actor.h
Normal 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
|
||||
Reference in New Issue
Block a user