Upd
This commit is contained in:
@@ -1,16 +1,4 @@
|
||||
<Scene>
|
||||
<StaticMesh filename="graveyard_fence.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_001.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_002.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_003.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_004.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_005.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_006.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_007.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_008.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_009.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_010.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_011.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_012.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_fence_013.obj" shader="lightmapped"/>
|
||||
<StaticMesh filename="graveyard_terrain.obj" shader="lightmapped"/>
|
||||
</Scene>
|
||||
@@ -5,7 +5,8 @@
|
||||
</LevelDescription>
|
||||
|
||||
<Entities>
|
||||
<Entity classname="TempPlayer">
|
||||
<Entity classname="actor_player">
|
||||
<Position x="1.0" y="5.0" z="1.0" />
|
||||
<IsDisableled value="false" />
|
||||
</Entity>
|
||||
</Entities>
|
||||
|
||||
BIN
data/levels/cemetery/graveyard_fence.wmb
Normal file
BIN
data/levels/cemetery/graveyard_fence.wmb
Normal file
Binary file not shown.
13
data/levels/cemetery/graveyard_terrain.mtl
Normal file
13
data/levels/cemetery/graveyard_terrain.mtl
Normal file
@@ -0,0 +1,13 @@
|
||||
# Blender MTL File: 'None'
|
||||
# Material Count: 1
|
||||
|
||||
newmtl graveyard_terrain
|
||||
Ns 225.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd data\\textures\\scenes\\cemetery\\grass_01.png
|
||||
1237
data/levels/cemetery/graveyard_terrain.obj
Normal file
1237
data/levels/cemetery/graveyard_terrain.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
data/levels/cemetery/graveyard_terrain.wmb
Normal file
BIN
data/levels/cemetery/graveyard_terrain.wmb
Normal file
Binary file not shown.
@@ -5,10 +5,7 @@
|
||||
</LevelDescription>
|
||||
|
||||
<Entities>
|
||||
<Entity classname="TempPlayer">
|
||||
<IsDisableled value="false" />
|
||||
</Entity>
|
||||
<Entity classname="game_object">
|
||||
<Entity classname="actor_player">
|
||||
<IsDisableled value="false" />
|
||||
</Entity>
|
||||
</Entities>
|
||||
|
||||
40
data/scripts/actors/actor_player.lua
Normal file
40
data/scripts/actors/actor_player.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
-- базовый класс актора
|
||||
actor_base = inherit_table(game_object)
|
||||
|
||||
-- инициализация FSM
|
||||
|
||||
|
||||
function actor_base:on_init()
|
||||
game_object.on_init(self)
|
||||
end
|
||||
|
||||
function actor_base:on_shutdown()
|
||||
game_object.on_shutdown(self)
|
||||
end
|
||||
|
||||
function actor_base:on_update(dt)
|
||||
game_object.on_update(self, dt)
|
||||
end
|
||||
|
||||
-- игрок
|
||||
actor_player = inherit_table(actor_base)
|
||||
|
||||
function actor_player:on_init()
|
||||
actor_base.on_init(self)
|
||||
|
||||
self:create_body()
|
||||
|
||||
self:activate_camera()
|
||||
end
|
||||
|
||||
function actor_player:on_shutdown()
|
||||
actor_base.on_shutdown(self)
|
||||
end
|
||||
|
||||
function actor_player:on_update(dt)
|
||||
actor_base.on_update(self, dt)
|
||||
|
||||
self:update_camera_look()
|
||||
--self:update_camera_movement(dt)
|
||||
self:update_body_movement(dt)
|
||||
end
|
||||
@@ -1,13 +1,19 @@
|
||||
-- Game initialization script
|
||||
|
||||
-- загружаем скрипты
|
||||
load_script("game_utils.lua")
|
||||
load_script("game_object.lua")
|
||||
load_script("test_object.lua")
|
||||
load_script("actors/actor_player.lua")
|
||||
|
||||
-- глобальная таблица сущностей
|
||||
g_entity_table = {
|
||||
-- Lua class -- CPP class -- Description
|
||||
-- Lua class -- CPP class -- Description
|
||||
|
||||
{ "game_object", "Entity", "Test Lua Entity" }
|
||||
{ "actor_player", "ActorBase", "Player entity" },
|
||||
|
||||
-- Simple entity
|
||||
{ "test_object", "Entity", "Test entity" },
|
||||
|
||||
|
||||
}
|
||||
18
data/scripts/game_utils.lua
Normal file
18
data/scripts/game_utils.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
-- http://lua-users.org/wiki/InheritanceTutorial
|
||||
|
||||
function merge_table( baseClass, newClass )
|
||||
for k, v in pairs( baseClass ) do
|
||||
if type( v ) == "table" then
|
||||
newClass[ k ] = newClass[ k ] or {}
|
||||
merge_table( v, newClass[ k ] )
|
||||
else
|
||||
newClass[ k ] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function inherit_table( baseClass )
|
||||
local newClass = {}
|
||||
merge_table( baseClass, newClass )
|
||||
return newClass
|
||||
end
|
||||
16
data/scripts/test_object.lua
Normal file
16
data/scripts/test_object.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
-- тестовый класс
|
||||
test_object = inherit_table(game_object)
|
||||
|
||||
function test_object:on_init()
|
||||
game_object.on_init(self)
|
||||
|
||||
self:load_model("data/models/scene_walls.obj")
|
||||
|
||||
self.m_test = 0.0
|
||||
end
|
||||
|
||||
function test_object:on_update(dt)
|
||||
game_object.on_update(self, dt)
|
||||
self:set_position(self.m_test, 0.0, 0.0)
|
||||
self.m_test = self.m_test + ( 0.2 * dt )
|
||||
end
|
||||
@@ -5,14 +5,26 @@ varying vec3 v_normal;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec3 v_finalColor;
|
||||
|
||||
uniform sampler2D u_albedoTexture;
|
||||
uniform vec4 u_customColor;
|
||||
uniform vec4 u_sunAmbientColor;
|
||||
|
||||
uniform sampler2D u_albedoTexture;
|
||||
|
||||
void main() {
|
||||
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
//gl_FragColor = u_customColor * vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
|
||||
//gl_FragColor = vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
|
||||
gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
|
||||
//gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
|
||||
//gl_FragColor = vec4( v_normal, 1.0 );
|
||||
//gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
|
||||
|
||||
// !!! NO AREF
|
||||
|
||||
// vec3 color = texture2D(u_albedoTexture, v_texcoord).rgb * v_finalColor;
|
||||
|
||||
vec3 color = texture2D(u_albedoTexture, v_texcoord).rgb;
|
||||
color = color * ( u_sunAmbientColor.rgb + v_finalColor.x );
|
||||
color = color + v_finalColor.y;
|
||||
|
||||
gl_FragColor = vec4(color.x, color.y, color.z, 1.0);
|
||||
}
|
||||
@@ -13,34 +13,41 @@ uniform mat4 u_modelMatrix;
|
||||
uniform mat4 u_viewMatrix;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_modelViewProjection;
|
||||
uniform vec4 u_sunDirection;
|
||||
uniform vec4 u_sunColor;
|
||||
uniform vec4 u_sunAmbientColor;
|
||||
uniform vec4 u_cameraPos;
|
||||
|
||||
vec3 CalcOmniLight()
|
||||
{
|
||||
vec3 lightPos = vec3(0.1, 2.1, 0.1);
|
||||
float d = distance(lightPos, v_position);
|
||||
vec3 L = normalize(lightPos-v_position);
|
||||
vec3 N = normalize(v_normal);
|
||||
vec3 col = vec3( max(0, dot(N, L) / d) );
|
||||
col = col * 0.8 + 0.2;
|
||||
return col;
|
||||
}
|
||||
// #TODO: should use own uniforms
|
||||
#define u_ligthPosition u_sunDirection.xyz
|
||||
#define u_ligthRadius u_sunDirection.w
|
||||
|
||||
vec3 CalcDirLight()
|
||||
{
|
||||
vec3 lightPos = vec3(5.0, 10.0, 1.0);
|
||||
//lightPos = -lightPos;
|
||||
// Calculate blinn-phong per-vertex lighting
|
||||
float CalcPhongLighting( vec3 worldPos, vec3 normal, vec3 lightPos ) {
|
||||
vec3 lightDir = normalize( lightPos - worldPos );
|
||||
vec3 viewDir = normalize( u_cameraPos.xyz - worldPos );
|
||||
vec3 halfVec = normalize( lightDir + viewDir );
|
||||
|
||||
float diff = max( dot( normal, lightDir ), 0.0 );
|
||||
|
||||
vec3 L = normalize(lightPos);
|
||||
vec3 N = normalize(v_normal);
|
||||
vec3 col = vec3( max(0, dot(N, L)) );
|
||||
col = col * 0.8 + 0.2;
|
||||
return col;
|
||||
v_finalColor.x = diff;
|
||||
|
||||
float spec = pow( max( dot( normal, halfVec ), 0.0 ), 128.0 ) * 1.0;
|
||||
|
||||
v_finalColor.y = spec;
|
||||
|
||||
return diff + spec;
|
||||
}
|
||||
|
||||
void main() {
|
||||
v_position = vec3( u_modelMatrix * vec4(a_position, 1.0) );
|
||||
v_normal = vec3( mat3(u_modelMatrix) * a_normal );
|
||||
v_texcoord = a_texcoord;
|
||||
v_finalColor = CalcDirLight();
|
||||
|
||||
CalcPhongLighting( v_position, v_normal, u_ligthPosition );
|
||||
|
||||
//v_finalColor = u_sunAmbientColor.rgb + CalcPhongLighting( v_position, v_normal, u_ligthPosition );
|
||||
|
||||
|
||||
gl_Position = u_modelViewProjection * vec4(a_position, 1);
|
||||
}
|
||||
18
data/shaders/unlit_generic.ps
Normal file
18
data/shaders/unlit_generic.ps
Normal file
@@ -0,0 +1,18 @@
|
||||
#version 120
|
||||
|
||||
varying vec3 v_position;
|
||||
varying vec3 v_normal;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec3 v_finalColor;
|
||||
|
||||
uniform sampler2D u_albedoTexture;
|
||||
uniform vec4 u_customColor;
|
||||
|
||||
void main() {
|
||||
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
//gl_FragColor = u_customColor * vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
|
||||
//gl_FragColor = vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
|
||||
gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
|
||||
//gl_FragColor = vec4( v_normal, 1.0 );
|
||||
//gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
|
||||
}
|
||||
46
data/shaders/unlit_generic.vs
Normal file
46
data/shaders/unlit_generic.vs
Normal file
@@ -0,0 +1,46 @@
|
||||
#version 120
|
||||
|
||||
attribute vec3 a_position;
|
||||
attribute vec3 a_normal;
|
||||
attribute vec2 a_texcoord;
|
||||
|
||||
varying vec3 v_position;
|
||||
varying vec3 v_normal;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec3 v_finalColor;
|
||||
|
||||
uniform mat4 u_modelMatrix;
|
||||
uniform mat4 u_viewMatrix;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_modelViewProjection;
|
||||
|
||||
vec3 CalcOmniLight()
|
||||
{
|
||||
vec3 lightPos = vec3(0.1, 2.1, 0.1);
|
||||
float d = distance(lightPos, v_position);
|
||||
vec3 L = normalize(lightPos-v_position);
|
||||
vec3 N = normalize(v_normal);
|
||||
vec3 col = vec3( max(0, dot(N, L) / d) );
|
||||
col = col * 0.8 + 0.2;
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 CalcDirLight()
|
||||
{
|
||||
vec3 lightPos = vec3(5.0, 10.0, 1.0);
|
||||
//lightPos = -lightPos;
|
||||
|
||||
vec3 L = normalize(lightPos);
|
||||
vec3 N = normalize(v_normal);
|
||||
vec3 col = vec3( max(0, dot(N, L)) );
|
||||
col = col * 0.8 + 0.2;
|
||||
return col;
|
||||
}
|
||||
|
||||
void main() {
|
||||
v_position = vec3( u_modelMatrix * vec4(a_position, 1.0) );
|
||||
v_normal = vec3( mat3(u_modelMatrix) * a_normal );
|
||||
v_texcoord = a_texcoord;
|
||||
v_finalColor = CalcDirLight();
|
||||
gl_Position = u_modelViewProjection * vec4(a_position, 1);
|
||||
}
|
||||
BIN
data/textures/scenes/cemetery/grass_01.png
Normal file
BIN
data/textures/scenes/cemetery/grass_01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
@@ -8,6 +8,7 @@
|
||||
#include "world.h"
|
||||
#include "camera.h"
|
||||
#include "inputmanager.h"
|
||||
#include "physics/physicsworld.h"
|
||||
|
||||
// renderer
|
||||
#include "render.h"
|
||||
@@ -221,6 +222,10 @@ void Engine::Frame()
|
||||
// *** ImGui scope begin
|
||||
g_ImGuiManager.BeginFrame();
|
||||
|
||||
// update physics
|
||||
if (g_PhysicsWorld)
|
||||
g_PhysicsWorld->Step(dt);
|
||||
|
||||
// update entities
|
||||
if (g_world)
|
||||
g_world->Update(dt);
|
||||
@@ -300,6 +305,9 @@ void Engine::NewGame(const char* mapname)
|
||||
// create entity container
|
||||
Disconnect();
|
||||
|
||||
g_PhysicsWorld = new PhysicsWorld();
|
||||
//g_PhysicsWorld->ToggleDebugDraw();
|
||||
|
||||
g_world = new World();
|
||||
|
||||
g_render->LoadSceneXML(mapname);
|
||||
@@ -316,6 +324,11 @@ void Engine::Disconnect()
|
||||
delete g_world;
|
||||
g_world = nullptr;
|
||||
}
|
||||
|
||||
if (g_PhysicsWorld) {
|
||||
delete g_PhysicsWorld;
|
||||
g_PhysicsWorld = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Window* Engine::GetWindow()
|
||||
|
||||
@@ -23,6 +23,11 @@ void IEntityBase::Render()
|
||||
{
|
||||
}
|
||||
|
||||
void IEntityBase::SetPosition(const glm::vec3& pos)
|
||||
{
|
||||
m_position = pos;
|
||||
}
|
||||
|
||||
const glm::mat4& IEntityBase::GetWorldTransform()
|
||||
{
|
||||
return m_worldTM;
|
||||
|
||||
@@ -17,6 +17,8 @@ public:
|
||||
|
||||
const BoundingBox& GetBoundingBox() { return m_boundingBox; }
|
||||
|
||||
void SetPosition(const glm::vec3& pos);
|
||||
|
||||
const glm::mat4& GetWorldTransform();
|
||||
void UpdateTransform();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "engine/core.h"
|
||||
#include "engine/log.h"
|
||||
#include "engine/engine.h"
|
||||
#include "engine/camera.h"
|
||||
#include "engine/physics/physicsworld.h"
|
||||
@@ -10,6 +11,8 @@
|
||||
#include <BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h>
|
||||
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
|
||||
|
||||
PhysicsWorld* g_PhysicsWorld = nullptr;
|
||||
|
||||
static void InternalTickCallback(btDynamicsWorld* world, btScalar timeStep)
|
||||
{
|
||||
SDL_assert(world);
|
||||
@@ -88,9 +91,9 @@ const std::vector<RigidBody*>& PhysicsWorld::GetRigidBodies()
|
||||
|
||||
void PhysicsWorld::Step(float delta)
|
||||
{
|
||||
// m_world->stepSimulation(delta);
|
||||
m_world->stepSimulation(delta);
|
||||
// m_world->stepSimulation(delta, 12, m_stepTime);
|
||||
#if 1
|
||||
#if 0
|
||||
if (delta < 0.01f)
|
||||
{
|
||||
m_accumulatedTime += delta;
|
||||
@@ -178,3 +181,100 @@ void PhysicsWorld::InternalTick()
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsWorld::AddCollisionModel(StaticMeshVertex* vertices, size_t verticesCount, uint32_t* indices, size_t indicesCount)
|
||||
{
|
||||
int index = (int)m_collisionModels.size();
|
||||
m_collisionModels.resize((size_t)index + 1);
|
||||
|
||||
// Check for is indices are 32 bits
|
||||
bool is32Bits = true;// sizeof(index_t) == sizeof(uint32_t);
|
||||
|
||||
m_collisionModels[index].triangleMesh = new btTriangleMesh(is32Bits);
|
||||
m_collisionModels[index].triangleMesh->preallocateVertices((int)verticesCount);
|
||||
m_collisionModels[index].triangleMesh->preallocateIndices((int)indicesCount);
|
||||
|
||||
// Initialize triangle mesh
|
||||
uint32_t trianglesCount = 0;
|
||||
for (uint32_t n = 0; n < indicesCount; n += 3) {
|
||||
m_collisionModels[index].triangleMesh->addTriangle(
|
||||
glmVectorToBt(vertices[indices[n]].position),
|
||||
glmVectorToBt(vertices[indices[n + 1]].position),
|
||||
glmVectorToBt(vertices[indices[n + 2]].position),
|
||||
true);
|
||||
|
||||
trianglesCount++;
|
||||
}
|
||||
|
||||
// Create shape
|
||||
m_collisionModels[index].shape = new btBvhTriangleMeshShape(m_collisionModels[index].triangleMesh, true);
|
||||
|
||||
// Create collision body
|
||||
m_collisionModels[index].object = new btCollisionObject();
|
||||
m_collisionModels[index].object->setCollisionShape(m_collisionModels[index].shape);
|
||||
m_collisionModels[index].object->setUserPointer(&m_collisionModels[index]);
|
||||
|
||||
// Add to scene
|
||||
m_world->addCollisionObject(m_collisionModels[index].object);
|
||||
|
||||
// Report
|
||||
Msg("PhysicsSystem::AddCollisionModel: %i triangles %i bytes", trianglesCount, trianglesCount * sizeof(btVector3));
|
||||
}
|
||||
|
||||
void PhysicsWorld::Reset()
|
||||
{
|
||||
int numModels = (int)m_collisionModels.size();
|
||||
for (int i = 0; i < numModels; i++)
|
||||
{
|
||||
if (m_collisionModels[i].object)
|
||||
{
|
||||
// remove object from world
|
||||
m_world->removeCollisionObject(m_collisionModels[i].object);
|
||||
|
||||
// reset shape
|
||||
m_collisionModels[i].object->setCollisionShape(nullptr);
|
||||
|
||||
// delete
|
||||
delete m_collisionModels[i].object;
|
||||
m_collisionModels[i].object = nullptr;
|
||||
}
|
||||
|
||||
if (m_collisionModels[i].shape)
|
||||
{
|
||||
delete m_collisionModels[i].shape;
|
||||
m_collisionModels[i].shape = nullptr;
|
||||
}
|
||||
|
||||
if (m_collisionModels[i].triangleMesh)
|
||||
{
|
||||
delete m_collisionModels[i].triangleMesh;
|
||||
m_collisionModels[i].triangleMesh = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Msg("PhysicsSystem: Destroyed %d static collision models", numModels);
|
||||
|
||||
m_collisionModels.clear();
|
||||
}
|
||||
|
||||
//
|
||||
ClosestRayResultCallback::ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, IEntityBase* entity) :
|
||||
btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld),
|
||||
m_entity(entity)
|
||||
{
|
||||
}
|
||||
|
||||
ClosestRayResultCallback::~ClosestRayResultCallback()
|
||||
{
|
||||
m_entity = nullptr;
|
||||
}
|
||||
|
||||
bool ClosestRayResultCallback::needsCollision(btBroadphaseProxy* proxy0) const
|
||||
{
|
||||
bool needsCollision = inherited::needsCollision(proxy0);
|
||||
|
||||
btCollisionObject* collisionObject = (btCollisionObject*)proxy0->m_clientObject;
|
||||
if (m_entity && collisionObject->getUserPointer() == m_entity)
|
||||
return false;
|
||||
|
||||
return needsCollision;
|
||||
}
|
||||
@@ -6,7 +6,16 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct StaticMeshVertex;
|
||||
class RigidBody;
|
||||
class IEntityBase;
|
||||
|
||||
struct SceneCollisionModel
|
||||
{
|
||||
btCollisionObject* object;
|
||||
btCollisionShape* shape;
|
||||
btTriangleMesh* triangleMesh;
|
||||
};
|
||||
|
||||
class PhysicsWorld
|
||||
{
|
||||
@@ -29,8 +38,16 @@ public:
|
||||
|
||||
void InternalTick();
|
||||
|
||||
// Add static collision model.
|
||||
void AddCollisionModel(StaticMeshVertex* vertices, size_t verticesCount,
|
||||
uint32_t* indices, size_t indicesCount);
|
||||
|
||||
// Reset all collision models and dynamic bodies.
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
std::vector<SceneCollisionModel> m_collisionModels;
|
||||
|
||||
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||
btCollisionDispatcher* m_dispatcher;
|
||||
btBroadphaseInterface* m_overlappingPairCache;
|
||||
@@ -48,4 +65,20 @@ private:
|
||||
bool m_debugDraw;
|
||||
};
|
||||
|
||||
class ClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
typedef btCollisionWorld::ClosestRayResultCallback inherited;
|
||||
public:
|
||||
ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, IEntityBase* entity);
|
||||
~ClosestRayResultCallback();
|
||||
|
||||
bool needsCollision(btBroadphaseProxy* proxy0) const override;
|
||||
|
||||
private:
|
||||
IEntityBase* m_entity;
|
||||
};
|
||||
|
||||
|
||||
extern PhysicsWorld* g_PhysicsWorld;
|
||||
|
||||
#endif // !PHYSICSWORLD_H
|
||||
|
||||
@@ -21,6 +21,9 @@ World::~World()
|
||||
|
||||
void World::DestroyWorld()
|
||||
{
|
||||
// Run destroyer
|
||||
UpdateDestroyList();
|
||||
|
||||
for (int i = 0; i < m_entities.size(); ++i)
|
||||
{
|
||||
delete m_entities[i];
|
||||
|
||||
@@ -30,21 +30,19 @@ void engineWarning(const char* msg)
|
||||
|
||||
LuaPlus::LuaObject engineCreateEntity(const char* classname)
|
||||
{
|
||||
LuaPlus::LuaObject entityObject;
|
||||
entityObject.AssignNewTable(GetLuaState());
|
||||
Entity* entity = static_cast<Entity*>(g_game->Lua_CreateEntity(classname));
|
||||
SDL_assert_always(entity);
|
||||
|
||||
//GameObject* entity = (GameObject*)g_entityManager->createEntity(classname);
|
||||
//entity->init_from_lua(entityObject);
|
||||
//entity->init();
|
||||
|
||||
return entityObject;
|
||||
return entity->GetLuaObject();
|
||||
}
|
||||
|
||||
void engineAddEntityToWorld(LuaPlus::LuaObject& object)
|
||||
{
|
||||
LuaPlus::LuaObject cppclass = object["__cpp_entity"];
|
||||
LuaPlus::LuaObject cppclass = object["__object"];
|
||||
SDL_assert_always(cppclass.IsLightUserdata());
|
||||
|
||||
// todo
|
||||
Entity* entity = static_cast<Entity*>(cppclass.GetLightUserdata());
|
||||
g_world->AddEntity(entity);
|
||||
}
|
||||
|
||||
void registerEngine()
|
||||
@@ -108,6 +106,11 @@ void initializeEntityPrototypesFromLua()
|
||||
prototype.m_description = description.ToString();
|
||||
g_prototypes.push_back(prototype);
|
||||
|
||||
// get a prototype
|
||||
LuaObject prototypeTable = GetLuaState().GetGlobal(luaname.ToString());
|
||||
SDL_assert_always(!prototypeTable.IsNil());
|
||||
prototypeTable.SetObject("__index", prototypeTable);
|
||||
|
||||
|
||||
/*for (LuaTableIterator it2(entityTable); it2; it2.Next()) {
|
||||
Logger::Msg("%s", it2.GetValue().ToString());
|
||||
@@ -180,9 +183,9 @@ void Game::LoadLevelXML(const char* mapname)
|
||||
|
||||
// std::map<std::string, std::string> properties;
|
||||
|
||||
for (pugi::xml_node entity : doc.child("Level").child("Entities").children("Entity")) {
|
||||
pugi::xml_attribute entityname = entity.attribute("name");
|
||||
pugi::xml_attribute classname = entity.attribute("classname");
|
||||
for (pugi::xml_node entitynode : doc.child("Level").child("Entities").children("Entity")) {
|
||||
pugi::xml_attribute entityname = entitynode.attribute("name");
|
||||
pugi::xml_attribute classname = entitynode.attribute("classname");
|
||||
|
||||
if (classname.empty()) {
|
||||
if (!entityname.empty()) {
|
||||
@@ -199,6 +202,16 @@ void Game::LoadLevelXML(const char* mapname)
|
||||
if (!entity)
|
||||
entity = g_entityManager->CreateEntity(classname.as_string());
|
||||
|
||||
pugi::xml_node position = entitynode.child("Position");
|
||||
if (position)
|
||||
{
|
||||
float x = position.attribute("x").as_float();
|
||||
float y = position.attribute("y").as_float();
|
||||
float z = position.attribute("z").as_float();
|
||||
|
||||
entity->SetPosition(glm::vec3(x, y, z));
|
||||
}
|
||||
|
||||
//IEntityBase* entity = g_entityManager->CreateEntity(classname.as_string());
|
||||
g_world->AddEntity(entity);
|
||||
}
|
||||
@@ -235,7 +248,7 @@ IEntityBase* Game::Lua_CreateEntity(const char* classname)
|
||||
// get a prototype
|
||||
LuaObject prototype = GetLuaState().GetGlobal(pluaprototype->m_luaname.c_str());
|
||||
SDL_assert_always(!prototype.IsNil());
|
||||
prototype.SetObject("__index", prototype);
|
||||
//prototype.SetObject("__index", prototype);
|
||||
|
||||
// generate table
|
||||
LuaObject factory = GetLuaState().GetGlobal("g_factory");
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
#include "inputmanager.h"
|
||||
#include "debugrender.h"
|
||||
#include "game_object.h"
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#define PLAYER_PHYS_MASS 80.0
|
||||
#define PLAYER_PHYS_RADIUS 0.40
|
||||
#define PLAYER_PHYS_HEIGHT 1.79
|
||||
#define PLAYER_PHYS_JUMPDIST PLAYER_PHYS_RADIUS
|
||||
#define PLAYER_PHYS_JUMPHEIGHT 2.0
|
||||
#define PLAYER_PHYS_JUMPSPEEDY 5.0
|
||||
#define PLAYER_PHYS_WALK_SPEED ( 5.5 )
|
||||
#define PLAYER_PHYS_RUN_SPEED_MUL 1.4
|
||||
#define PLAYER_PHYS_MOVE_SPEED_EXP 1.0
|
||||
#define PLAYER_PHYS_FLY_SPEED_EXP 4.0
|
||||
|
||||
// Lua wrappers
|
||||
void Entity_LoadModel(LuaPlus::LuaState* state)
|
||||
{
|
||||
@@ -11,6 +23,46 @@ void Entity_LoadModel(LuaPlus::LuaState* state)
|
||||
entity->LoadModel(stack[2].GetString());
|
||||
}
|
||||
|
||||
void Entity_SetVisible(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
Entity* entity = (Entity*)stack[1].GetByName("__object").GetLightUserdata();
|
||||
entity->SetVisible(stack[2].GetBoolean());
|
||||
}
|
||||
|
||||
bool Entity_GetVisible(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
Entity* entity = (Entity*)stack[1].GetByName("__object").GetLightUserdata();
|
||||
return entity->GetVisible();
|
||||
}
|
||||
|
||||
void ActorBase_UpdateCameraMovement(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
ActorBase* entity = (ActorBase*)stack[1].GetByName("__object").GetLightUserdata();
|
||||
entity->UpdateCameraMovement(stack[2].GetFloat());
|
||||
}
|
||||
|
||||
void ActorBase_UpdateCameraLook(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
ActorBase* entity = (ActorBase*)stack[1].GetByName("__object").GetLightUserdata();
|
||||
entity->UpdateCameraLook();
|
||||
}
|
||||
|
||||
void ActorBase_ActivateCamera(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
ActorBase* entity = (ActorBase*)stack[1].GetByName("__object").GetLightUserdata();
|
||||
entity->ActivateCamera();
|
||||
}
|
||||
|
||||
REGISTER_ENTITY(Entity);
|
||||
|
||||
Entity::Entity() :
|
||||
@@ -44,14 +96,31 @@ void Entity::Update(float dt)
|
||||
if ( m_onUpdateFunction.IsFunction())
|
||||
{
|
||||
LuaPlus::LuaFunctionVoid function = m_onUpdateFunction;
|
||||
function(m_luaObject, dt);
|
||||
function(m_luaObject, static_cast<lua_Number>(dt));
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::Render()
|
||||
{
|
||||
if (m_model)
|
||||
{
|
||||
m_model->Draw(GetWorldTransform());
|
||||
|
||||
BoundingBox bbox = m_model->GetBoundingBox();
|
||||
bbox.TransformAABB(GetWorldTransform());
|
||||
|
||||
g_debugRender->DrawBoundingBox(bbox, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& Entity::GetName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Entity::SetName(const std::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void Entity::LoadModel(const char* filename)
|
||||
@@ -83,10 +152,11 @@ void Entity::InitFromTable(LuaPlus::LuaObject& _object)
|
||||
// check
|
||||
SDL_assert_always(m_onInitFunction.IsFunction() || m_onShutdownFunction.IsFunction() || m_onUpdateFunction.IsFunction());
|
||||
|
||||
// register base entity functions
|
||||
RegisterBaseFunctions();
|
||||
|
||||
// register entity functions
|
||||
m_luaObject.RegisterDirect("load_model", &Entity_LoadModel);
|
||||
//m_luaObject.RegisterDirect("set_visible", &Entity::SetVisible);
|
||||
//m_luaObject.RegisterDirect("get_visible", &Entity::GetVisible);
|
||||
RegisterFunctions();
|
||||
|
||||
// assign C++ object
|
||||
m_luaObject.SetLightUserdata("__object", this);
|
||||
@@ -96,29 +166,141 @@ void Entity::InitFromTable(LuaPlus::LuaObject& _object)
|
||||
onInitFunction(m_luaObject);
|
||||
}
|
||||
|
||||
REGISTER_ENTITY(TempPlayer);
|
||||
void Entity::RegisterBaseFunctions()
|
||||
{
|
||||
m_luaObject.Register("load_model", *this, &Entity::Lua_LoadModel);
|
||||
m_luaObject.Register("translate", *this, &Entity::Lua_Translate);
|
||||
m_luaObject.Register("set_position", *this, &Entity::Lua_SetPosition);
|
||||
|
||||
TempPlayer::TempPlayer()
|
||||
// m_luaObject.RegisterDirect("load_model", &Entity_LoadModel);
|
||||
//m_luaObject.RegisterDirect("set_visible", &Entity_SetVisible);
|
||||
//m_luaObject.RegisterDirect("get_visible", &Entity_GetVisible);
|
||||
}
|
||||
|
||||
void Entity::RegisterFunctions()
|
||||
{
|
||||
}
|
||||
|
||||
TempPlayer::~TempPlayer()
|
||||
void Entity::Help_Translate(float x, float y, float z)
|
||||
{
|
||||
m_position.x += x;
|
||||
m_position.y += y;
|
||||
m_position.z += z;
|
||||
}
|
||||
|
||||
void Entity::Help_SetPosition(float x, float y, float z)
|
||||
{
|
||||
m_position.x = x;
|
||||
m_position.y = y;
|
||||
m_position.z = z;
|
||||
}
|
||||
|
||||
int Entity::Lua_LoadModel(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
if (stack.Count() > 1)
|
||||
{
|
||||
LoadModel(stack[2].GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadModel(stack[1].GetString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Entity::Lua_Translate(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
float x = stack[2].GetNumber();
|
||||
float y = stack[3].GetNumber();
|
||||
float z = stack[4].GetNumber();
|
||||
|
||||
Help_Translate(x, y, z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Entity::Lua_SetPosition(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
float x = stack[2].GetNumber();
|
||||
float y = stack[3].GetNumber();
|
||||
float z = stack[4].GetNumber();
|
||||
|
||||
Help_SetPosition(x, y, z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const LuaPlus::LuaObject& Entity::GetLuaObject()
|
||||
{
|
||||
return m_luaObject;
|
||||
}
|
||||
|
||||
REGISTER_ENTITY(ActorBase);
|
||||
|
||||
ActorBase::ActorBase() :
|
||||
m_shape(nullptr),
|
||||
m_rigidBody(nullptr),
|
||||
m_bodyDirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
void TempPlayer::Update(float dt)
|
||||
ActorBase::~ActorBase()
|
||||
{
|
||||
g_cameraManager.SetActiveCamera(&m_camera);
|
||||
if (m_rigidBody) {
|
||||
g_PhysicsWorld->GetWorld()->removeRigidBody(m_rigidBody);
|
||||
|
||||
UpdateCameraLook();
|
||||
delete m_rigidBody;
|
||||
m_rigidBody = nullptr;
|
||||
|
||||
UpdateCameraMovement(dt);
|
||||
m_ph_motion_state.setBody(nullptr);
|
||||
}
|
||||
|
||||
if (m_shape) {
|
||||
delete m_shape;
|
||||
m_shape = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TempPlayer::UpdateCameraMovement(float dt)
|
||||
void ActorBase::Update(float dt)
|
||||
{
|
||||
static bool s_test = true;
|
||||
|
||||
if (s_test) {
|
||||
UpdateBody();
|
||||
Entity::Update(dt);
|
||||
AfterEngineStep();
|
||||
} else {
|
||||
ActivateCamera();
|
||||
|
||||
UpdateCameraLook();
|
||||
|
||||
UpdateCameraMovement(dt);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ActorBase::AfterEngineStep()
|
||||
{
|
||||
//btTransform xform = m_rigidBody->getWorldTransform();
|
||||
//m_position = btVectorToGlm(xform.getOrigin());
|
||||
|
||||
m_position = btVectorToGlm(m_ph_motion_state.m_transform.getOrigin());
|
||||
m_camera.SetPosition(m_position);
|
||||
}
|
||||
|
||||
void ActorBase::UpdateCameraMovement(float dt)
|
||||
{
|
||||
// calculate player movement
|
||||
float speed = 19.0f * dt;
|
||||
float speed = 12.0f * dt;
|
||||
|
||||
uint32_t movementDir = GenMovementDir();
|
||||
|
||||
@@ -135,10 +317,41 @@ void TempPlayer::UpdateCameraMovement(float dt)
|
||||
m_camera.SetPosition(m_position);
|
||||
}
|
||||
|
||||
void TempPlayer::UpdateCameraLook()
|
||||
void ActorBase::UpdateBodyMovement(float dt)
|
||||
{
|
||||
g_inputManager.SetRelativeMouseMode(true);
|
||||
|
||||
glm::vec3 dir = glm::vec3(0.0f);
|
||||
|
||||
glm::vec3 camFront = m_camera.GetFront();
|
||||
camFront.y = 0.0f;
|
||||
camFront = glm::normalize(camFront);
|
||||
|
||||
// calculate player movement
|
||||
float speed = 4.f;
|
||||
|
||||
uint32_t movementDir = GenMovementDir();
|
||||
|
||||
if (movementDir & EMovementDir_Forward)
|
||||
dir += camFront;
|
||||
if (movementDir & EMovementDir_Backward)
|
||||
dir -= camFront;
|
||||
if (movementDir & EMovementDir_Left)
|
||||
dir -= glm::normalize(glm::cross(camFront, m_camera.GetUp()));
|
||||
if (movementDir & EMovementDir_Right)
|
||||
dir += glm::normalize(glm::cross(camFront, m_camera.GetUp()));
|
||||
|
||||
glm::vec3 velocity = dir * speed;
|
||||
|
||||
if (glm::length(velocity) > 0.1f && OnGround() && !(movementDir & EMovementDir_Jump))
|
||||
m_rigidBody->setLinearVelocity(glmVectorToBt(velocity));
|
||||
|
||||
if ((movementDir & EMovementDir_Jump) && OnGround()) {
|
||||
m_rigidBody->applyCentralImpulse(btVector3(0.0f, PLAYER_PHYS_JUMPSPEEDY*25, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
void ActorBase::UpdateCameraLook()
|
||||
{
|
||||
glm::ivec2 mousePos = g_inputManager.GetMousePos();
|
||||
|
||||
// calculate yaw and pitch
|
||||
@@ -158,7 +371,132 @@ void TempPlayer::UpdateCameraLook()
|
||||
m_camera.SetYawPitch(yaw, pitch);
|
||||
}
|
||||
|
||||
uint32_t TempPlayer::GenMovementDir()
|
||||
void ActorBase::UpdateBody()
|
||||
{
|
||||
if (m_bodyDirty)
|
||||
{
|
||||
btTransform xform;
|
||||
xform.setIdentity();
|
||||
xform.setOrigin(glmVectorToBt(m_position));
|
||||
m_rigidBody->setWorldTransform(xform);
|
||||
|
||||
m_bodyDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ActorBase::ActivateCamera()
|
||||
{
|
||||
g_inputManager.SetRelativeMouseMode(true);
|
||||
|
||||
g_cameraManager.SetActiveCamera(&m_camera);
|
||||
}
|
||||
|
||||
void ActorBase::CreateBody()
|
||||
{
|
||||
|
||||
m_shape = new btCapsuleShape(PLAYER_PHYS_RADIUS, PLAYER_PHYS_HEIGHT - PLAYER_PHYS_RADIUS * 2.0);
|
||||
|
||||
m_mass = 80.0f;
|
||||
btVector3 local_inertia(0.0f, 0.0f, 0.0f);
|
||||
if (m_mass > 0.f) {
|
||||
m_shape->calculateLocalInertia(m_mass, local_inertia);
|
||||
}
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo rigid_body_ci(m_mass, nullptr, m_shape, local_inertia);
|
||||
|
||||
m_rigidBody = new btRigidBody(rigid_body_ci);
|
||||
m_rigidBody->setUserPointer(this);
|
||||
m_rigidBody->setMotionState(&m_ph_motion_state);
|
||||
m_ph_motion_state.setBody(m_rigidBody);
|
||||
|
||||
// I'm sure that position is valid
|
||||
btTransform xform;
|
||||
xform.setIdentity();
|
||||
xform.setOrigin(glmVectorToBt(m_position));
|
||||
m_rigidBody->setWorldTransform(xform);
|
||||
|
||||
// ACTOR STUFF
|
||||
m_rigidBody->setAngularFactor(btVector3(0.0f, 0.0f, 0.0f));
|
||||
m_rigidBody->setFriction(2.5f);
|
||||
m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
|
||||
|
||||
// #TODO: body filter and mask
|
||||
g_PhysicsWorld->GetWorld()->addRigidBody(m_rigidBody);
|
||||
|
||||
m_bodyDirty = true;
|
||||
}
|
||||
|
||||
bool ActorBase::OnGround()
|
||||
{
|
||||
float rayLength = (PLAYER_PHYS_HEIGHT / 2.0f) + 0.1f;
|
||||
|
||||
btTransform xform = m_rigidBody->getWorldTransform();
|
||||
|
||||
btVector3 rayStart = xform.getOrigin();
|
||||
btVector3 rayEnd = rayStart - btVector3(0.0f, rayLength, 0.0f);
|
||||
|
||||
ClosestRayResultCallback RayResultCallback(rayStart, rayEnd, this);
|
||||
g_PhysicsWorld->GetWorld()->rayTest(rayStart, rayEnd, RayResultCallback);
|
||||
if (RayResultCallback.hasHit()) {
|
||||
btVector3 hitNormal = RayResultCallback.m_hitNormalWorld;
|
||||
if (hitNormal.y() > 0.7f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActorBase::RegisterFunctions()
|
||||
{
|
||||
m_luaObject.Register("activate_camera", *this, &ActorBase::Lua_ActivateCamera);
|
||||
m_luaObject.Register("update_camera_look", *this, &ActorBase::Lua_UpdateCameraLook);
|
||||
m_luaObject.Register("update_camera_movement", *this, &ActorBase::Lua_UpdateCameraMovement);
|
||||
m_luaObject.Register("create_body", *this, &ActorBase::Lua_CreateBody);
|
||||
m_luaObject.Register("update_body_movement", *this, &ActorBase::Lua_UpdateBodyMovement);
|
||||
|
||||
//m_luaObject.RegisterDirect("activate_camera", &ActorBase_ActivateCamera);
|
||||
//m_luaObject.RegisterDirect("update_camera_look", &ActorBase_UpdateCameraLook);
|
||||
//m_luaObject.RegisterDirect("update_camera_movement", &ActorBase_UpdateCameraMovement);
|
||||
}
|
||||
|
||||
int ActorBase::Lua_UpdateCameraMovement(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
UpdateCameraMovement(stack[2].GetFloat());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActorBase::Lua_UpdateBodyMovement(LuaPlus::LuaState* state)
|
||||
{
|
||||
LuaPlus::LuaStack stack(state);
|
||||
|
||||
UpdateBodyMovement(stack[2].GetFloat());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActorBase::Lua_UpdateCameraLook(LuaPlus::LuaState* state)
|
||||
{
|
||||
UpdateCameraLook();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActorBase::Lua_ActivateCamera(LuaPlus::LuaState* state)
|
||||
{
|
||||
ActivateCamera();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActorBase::Lua_CreateBody(LuaPlus::LuaState* state)
|
||||
{
|
||||
CreateBody();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ActorBase::GenMovementDir()
|
||||
{
|
||||
uint32_t movementDir = EMovementDir_None;
|
||||
|
||||
@@ -178,6 +516,10 @@ uint32_t TempPlayer::GenMovementDir()
|
||||
movementDir |= EMovementDir_Right;
|
||||
}
|
||||
|
||||
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_SPACE)) {
|
||||
movementDir |= EMovementDir_Jump;
|
||||
}
|
||||
|
||||
return movementDir;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef GAME_OBJECT_H
|
||||
#define GAME_OBJECT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "engine/ientity.h"
|
||||
#include "engine/camera.h"
|
||||
#include "engine/physics/physicsworld.h"
|
||||
|
||||
#include "render/model.h"
|
||||
#include "render/modelsystem.h"
|
||||
@@ -15,9 +18,47 @@ enum EMovmentDir
|
||||
EMovementDir_Forward = 1 << 1,
|
||||
EMovementDir_Backward = 1 << 2,
|
||||
EMovementDir_Left = 1 << 3,
|
||||
EMovementDir_Right = 1 << 4
|
||||
EMovementDir_Right = 1 << 4,
|
||||
EMovementDir_Jump = 1 << 5,
|
||||
};
|
||||
|
||||
struct ph_motion_state : public btMotionState {
|
||||
btRigidBody* m_body;
|
||||
btTransform m_transform;
|
||||
|
||||
ph_motion_state() : m_body(nullptr) {}
|
||||
ph_motion_state(btRigidBody* body) : m_body(body) {}
|
||||
|
||||
void setBody(btRigidBody* body) { m_body = body; }
|
||||
|
||||
// getWorldTransform() relays transform from external logic to Bullet.
|
||||
// It is called by Bullet in two places:
|
||||
// (1) Once when the Body is created and added to the world.
|
||||
// (2) Once per substep iff the Body is Kinematic and active.
|
||||
//
|
||||
void getWorldTransform(btTransform& worldTrans) const {
|
||||
// Note: worldTrans is passed by reference
|
||||
// It is our duty here to copy into it the correct transform as known
|
||||
// to external logic and Bullet will harvest<73>
|
||||
// <20>
|
||||
// m_gameObject->getWorldTransform( worldTrans );
|
||||
}
|
||||
|
||||
// setWorldTransform() relays Body transform from the Bullet simulation to the GameObject
|
||||
// and is called once per substep iff the Body is Dynamic and active.
|
||||
//
|
||||
void setWorldTransform(const btTransform& worldTrans) {
|
||||
// It is our duty here to apply worldTrans to GameObject.
|
||||
// Note: worldTrans is NOT necessarily the Body's transform as known to Bullet.
|
||||
// It is an extrapolated transform based on the Body's state at the
|
||||
// end of the last substep... extrapolated forward into the future (e.g. the remainder
|
||||
// not yet stepped) according the current Body velocities.
|
||||
//
|
||||
m_transform = worldTrans;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Entity : public IEntityBase
|
||||
{
|
||||
public:
|
||||
@@ -28,14 +69,32 @@ public:
|
||||
virtual void Render();
|
||||
|
||||
// Game entity extensions
|
||||
const std::string& GetName();
|
||||
void SetName(const std::string& name);
|
||||
|
||||
virtual void LoadModel(const char* filename);
|
||||
void SetVisible(bool visible);
|
||||
bool GetVisible();
|
||||
|
||||
// Game entity lua bindings
|
||||
|
||||
void InitFromTable(LuaPlus::LuaObject& _object);
|
||||
void RegisterBaseFunctions();
|
||||
virtual void RegisterFunctions();
|
||||
|
||||
// Game entity lua wrappers
|
||||
void Help_Translate(float x, float y, float z);
|
||||
void Help_SetPosition(float x, float y, float z);
|
||||
|
||||
int Lua_LoadModel(LuaPlus::LuaState* state);
|
||||
int Lua_Translate(LuaPlus::LuaState* state);
|
||||
int Lua_SetPosition(LuaPlus::LuaState* state);
|
||||
|
||||
const LuaPlus::LuaObject& GetLuaObject();
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
|
||||
Model* m_model;
|
||||
|
||||
LuaPlus::LuaObject m_luaObject;
|
||||
@@ -44,23 +103,52 @@ protected:
|
||||
LuaPlus::LuaObject m_onUpdateFunction;
|
||||
};
|
||||
|
||||
class TempPlayer : public Entity
|
||||
class ActorBase : public Entity
|
||||
{
|
||||
public:
|
||||
TempPlayer();
|
||||
~TempPlayer();
|
||||
ActorBase();
|
||||
~ActorBase();
|
||||
|
||||
virtual void Update(float dt);
|
||||
|
||||
void AfterEngineStep();
|
||||
|
||||
void UpdateCameraMovement(float dt);
|
||||
|
||||
void UpdateBodyMovement(float dt);
|
||||
|
||||
void UpdateCameraLook();
|
||||
|
||||
void UpdateBody();
|
||||
|
||||
void ActivateCamera();
|
||||
|
||||
void CreateBody();
|
||||
|
||||
bool OnGround();
|
||||
|
||||
// Lua bindings
|
||||
|
||||
virtual void RegisterFunctions();
|
||||
|
||||
int Lua_UpdateCameraMovement(LuaPlus::LuaState* state);
|
||||
int Lua_UpdateBodyMovement(LuaPlus::LuaState* state);
|
||||
int Lua_UpdateCameraLook(LuaPlus::LuaState* state);
|
||||
int Lua_ActivateCamera(LuaPlus::LuaState* state);
|
||||
int Lua_CreateBody(LuaPlus::LuaState* state);
|
||||
|
||||
private:
|
||||
uint32_t GenMovementDir();
|
||||
|
||||
private:
|
||||
Camera m_camera;
|
||||
|
||||
private:
|
||||
btCollisionShape* m_shape;
|
||||
btRigidBody* m_rigidBody;
|
||||
ph_motion_state m_ph_motion_state;
|
||||
float m_mass;
|
||||
bool m_bodyDirty;
|
||||
};
|
||||
|
||||
class Weapon : public Entity
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "modelsystem.h"
|
||||
#include "texturesmanager.h"
|
||||
|
||||
extern Shader* g_litShader;
|
||||
extern Shader* g_unlitShader;
|
||||
|
||||
static std::string getFileNameWithoutExtension(const std::string& filename)
|
||||
{
|
||||
@@ -220,7 +220,7 @@ void Model::LoadMtl(const char* filename)
|
||||
|
||||
void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
|
||||
{
|
||||
SDL_assert(g_litShader);
|
||||
SDL_assert(g_unlitShader);
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
glDepthFunc(GL_LESS);
|
||||
@@ -236,20 +236,20 @@ void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
|
||||
g_renderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f);
|
||||
g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
|
||||
g_shaderSystem->SetUniformFloat4(g_unlitShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderDevice->SetBlending(false);
|
||||
|
||||
//glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f);
|
||||
//g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
|
||||
//g_shaderSystem->SetUniformFloat4(g_unlitShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
|
||||
}
|
||||
|
||||
g_renderDevice->SetVerticesBuffer(m_data.vb);
|
||||
|
||||
g_shaderSystem->SetShader(g_litShader);
|
||||
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &model[0]);
|
||||
g_shaderSystem->SetShader(g_unlitShader);
|
||||
g_shaderSystem->SetUniformMatrix(g_unlitShader, UNIFORM_MODEL_MATRIX, &model[0]);
|
||||
|
||||
//static float test = 0.0f;
|
||||
//test += g_systemTimer->GetDelta() * 6.0f;
|
||||
@@ -277,10 +277,10 @@ void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
|
||||
|
||||
glm::mat4 mvp = glm::identity<glm::mat4>();
|
||||
mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix() * model;
|
||||
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
|
||||
g_shaderSystem->SetUniformMatrix(g_unlitShader, UNIFORM_MVP_MATRIX, &mvp[0]);
|
||||
|
||||
g_texturesManager->SetTexture(0, m_AlbedoTexture);
|
||||
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
|
||||
g_shaderSystem->SetUniformSampler(g_unlitShader, SAMPLER_ALBEDO, 0);
|
||||
|
||||
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ static InputLayoutDesc_t g_skinnedVertexLayout[] = {
|
||||
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD }
|
||||
};
|
||||
|
||||
Shader* g_unlitShader = nullptr;
|
||||
Shader* g_litShader = nullptr;
|
||||
|
||||
static std::string getFileNameWithoutExtension(const std::string& filename)
|
||||
@@ -48,7 +49,11 @@ ModelSystem::~ModelSystem()
|
||||
|
||||
void ModelSystem::Init()
|
||||
{
|
||||
// Load model generic shader
|
||||
// Load unlighted model generic shader
|
||||
g_unlitShader = g_shaderSystem->CreateShader("unlit_generic", "data/shaders/unlit_generic.vs", "data/shaders/unlit_generic.ps",
|
||||
g_staticVertexLayout, sizeof(g_staticVertexLayout) / sizeof(g_staticVertexLayout[0]));
|
||||
|
||||
// Load lighted model generic shader
|
||||
g_litShader = g_shaderSystem->CreateShader("lit_generic", "data/shaders/lit_generic.vs", "data/shaders/lit_generic.ps",
|
||||
g_staticVertexLayout, sizeof(g_staticVertexLayout) / sizeof(g_staticVertexLayout[0]));
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ enum ShaderUniform_t
|
||||
UNIFORM_SUN_DIRECTION,
|
||||
UNIFORM_SUN_COLOR,
|
||||
UNIFORM_SUN_AMBIENT,
|
||||
UNIFORM_CAMERA_POS,
|
||||
|
||||
UNIFORM_MAX,
|
||||
};
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include "render/shadersystem.h"
|
||||
#include "render/render.h"
|
||||
#include "render/debugrender.h"
|
||||
#include "render/gpu_buffer.h"
|
||||
#include "engine/camera.h"
|
||||
#include "engine/physics/physicsworld.h"
|
||||
|
||||
#include <pugixml.hpp>
|
||||
|
||||
@@ -54,6 +57,37 @@ static std::string getFilenameWithoutPathAndExtension(const std::string& filenam
|
||||
return string;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TReadFile(FileHandle_t handle, T* value)
|
||||
{
|
||||
GetFileSystem()->ReadFile(handle, (void*)value, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TWriteFile(FileHandle_t handle, const T* value)
|
||||
{
|
||||
GetFileSystem()->WriteFile(handle, (void*)value, sizeof(T));
|
||||
}
|
||||
|
||||
static void WriteString(FileHandle_t handle, const std::string& string)
|
||||
{
|
||||
uint16_t size = string.length();
|
||||
TWriteFile(handle, &size);
|
||||
|
||||
GetFileSystem()->WriteFile(handle, (void*)string.c_str(), size);
|
||||
}
|
||||
|
||||
static void ReadString(FileHandle_t handle, std::string& string)
|
||||
{
|
||||
uint16_t size;
|
||||
TReadFile(handle, &size);
|
||||
|
||||
//string.resize(size + 1);
|
||||
string.resize(size);
|
||||
GetFileSystem()->ReadFile(handle, (void*)string.c_str(), size);
|
||||
//string[size] = '\0';
|
||||
}
|
||||
|
||||
//#ifdef NDEBUG
|
||||
//#pragma comment(lib, "assimp-vc141-mt.lib")
|
||||
//#else
|
||||
@@ -329,7 +363,13 @@ void SceneManager::loadStaticMesh(const char* filename)
|
||||
|
||||
if (GetFileSystem()->IsExist(filenamebuf)) {
|
||||
SceneStaticMesh* staticMesh = new SceneStaticMesh();
|
||||
staticMesh->LoadObj(filenamebuf);
|
||||
|
||||
const char* ext = strrchr(filenamebuf, '.');
|
||||
if (ext && strcmp(ext, ".obj") == 0)
|
||||
staticMesh->LoadObj(filenamebuf);
|
||||
else if (ext && strcmp(ext, ".wmb") == 0)
|
||||
staticMesh->LoadBin(filenamebuf);
|
||||
|
||||
m_sceneMeshes.push_back(staticMesh);
|
||||
}
|
||||
}
|
||||
@@ -593,6 +633,42 @@ void SceneStaticMesh::LoadObj(const char* filename)
|
||||
}
|
||||
}
|
||||
|
||||
// Fill face indices
|
||||
std::vector<uint32_t> indices;
|
||||
for (uint32_t i = 0; i < vertices.size(); i++) {
|
||||
indices.push_back(i);
|
||||
}
|
||||
|
||||
std::string binaryCache = getFileNameWithoutExtension(filename);
|
||||
binaryCache += ".wmb";
|
||||
|
||||
if (!GetFileSystem()->IsExist(binaryCache.c_str()))
|
||||
{
|
||||
FileHandle_t handle = GetFileSystem()->OpenFile(binaryCache.c_str(), "wb");
|
||||
|
||||
// write header
|
||||
WriteString(handle, "StaticSceneMeshFile");
|
||||
WriteString(handle, "0.1");
|
||||
|
||||
// write material file
|
||||
|
||||
std::string mtlfilename = getFileNameWithoutExtension(filename);
|
||||
mtlfilename += ".mtl";
|
||||
WriteString(handle, mtlfilename);
|
||||
|
||||
// write vertices
|
||||
uint32_t vbcount = vertices.size();
|
||||
TWriteFile(handle, &vbcount);
|
||||
GetFileSystem()->WriteFile(handle, vertices.data(), vertices.size() * sizeof(StaticMeshVertex));
|
||||
|
||||
// write indices
|
||||
uint32_t ibcount = indices.size();
|
||||
TWriteFile(handle, &ibcount);
|
||||
GetFileSystem()->WriteFile(handle, indices.data(), indices.size() * sizeof(uint32_t));
|
||||
|
||||
GetFileSystem()->CloseFile(handle);
|
||||
}
|
||||
|
||||
// m_Vertices = vertices;
|
||||
|
||||
m_vb = g_renderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
|
||||
@@ -601,6 +677,75 @@ void SceneStaticMesh::LoadObj(const char* filename)
|
||||
std::string mtlfilename = getFileNameWithoutExtension(filename);
|
||||
mtlfilename += ".mtl";
|
||||
LoadMtl(mtlfilename.c_str());
|
||||
|
||||
if (g_PhysicsWorld) {
|
||||
g_PhysicsWorld->AddCollisionModel(vertices.data(), vertices.size(), indices.data(), indices.size());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneStaticMesh::LoadBin(const char* filename)
|
||||
{
|
||||
FileHandle_t handle = GetFileSystem()->OpenFile(filename, "rb");
|
||||
|
||||
std::string header;
|
||||
ReadString(handle, header);
|
||||
if (header != "StaticSceneMeshFile")
|
||||
Core::Error(" SceneStaticMesh::LoadBin: Error during scene loading!\n%s is not a proper scene mesh.\n%s (should be %s)", filename, header.c_str(), "StaticSceneMeshFile");
|
||||
|
||||
std::string version;
|
||||
ReadString(handle, version);
|
||||
if (version != "0.1")
|
||||
Core::Error(" SceneStaticMesh::LoadBin: Error during scene loading!\n%s is outdated.\nversion %s (current is %s)", filename, version.c_str(), "0.1");
|
||||
|
||||
std::string mtlfilename;
|
||||
ReadString(handle, mtlfilename);
|
||||
|
||||
LoadMtl(mtlfilename.c_str());
|
||||
|
||||
// read vertices
|
||||
uint32_t vbcount;
|
||||
TReadFile(handle, &vbcount);
|
||||
|
||||
std::vector<StaticMeshVertex> vertices;
|
||||
vertices.resize(vbcount);
|
||||
GetFileSystem()->ReadFile(handle, vertices.data(), vertices.size() * sizeof(StaticMeshVertex));
|
||||
|
||||
// read indices
|
||||
uint32_t ibcount;
|
||||
TReadFile(handle, &ibcount);
|
||||
|
||||
std::vector<unsigned int> vertexIndices;
|
||||
vertexIndices.resize(ibcount);
|
||||
GetFileSystem()->ReadFile(handle, vertexIndices.data(), vertexIndices.size() * sizeof(unsigned int));
|
||||
|
||||
// bbox calculation
|
||||
for (unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
m_boundingBox.m_min = vertices[i].position;
|
||||
m_boundingBox.m_max = vertices[i].position;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_boundingBox.m_min = glm::min(m_boundingBox.m_min, vertices[i].position);
|
||||
m_boundingBox.m_max = glm::max(m_boundingBox.m_max, vertices[i].position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create vb
|
||||
m_vb = g_renderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
|
||||
m_vbcount = vertices.size();
|
||||
|
||||
// create ib ??
|
||||
|
||||
if (g_PhysicsWorld) {
|
||||
g_PhysicsWorld->AddCollisionModel(vertices.data(), vertices.size(), vertexIndices.data(), vertexIndices.size());
|
||||
}
|
||||
|
||||
GetFileSystem()->CloseFile(handle);
|
||||
}
|
||||
|
||||
void SceneStaticMesh::LoadMtl(const char* filename)
|
||||
@@ -643,12 +788,57 @@ void SceneStaticMesh::LoadMtl(const char* filename)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void SceneStaticMesh::RenderObjects()
|
||||
static glm::mat4 s_identity = glm::mat4(1.0f);
|
||||
|
||||
void R_SceneStaticMesh_BindShader(const glm::mat4& worldMatrix, Texture2D* albedoTexture)
|
||||
{
|
||||
extern Shader* g_unlitShader;
|
||||
extern Shader* g_litShader;
|
||||
|
||||
SDL_assert(g_unlitShader);
|
||||
SDL_assert(g_litShader);
|
||||
|
||||
Shader* shader = g_litShader;
|
||||
|
||||
g_shaderSystem->SetShader(shader);
|
||||
|
||||
g_shaderSystem->SetUniformMatrix(shader, UNIFORM_MODEL_MATRIX, &worldMatrix[0]);
|
||||
|
||||
glm::mat4 mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix() * worldMatrix;
|
||||
g_shaderSystem->SetUniformMatrix(shader, UNIFORM_MVP_MATRIX, &mvp[0]);
|
||||
|
||||
Camera* camera = g_cameraManager.GetActiveCamera();
|
||||
if (camera && shader->HasUniform(UNIFORM_CAMERA_POS))
|
||||
{
|
||||
glm::vec4 campos = glm::vec4(camera->GetPosition(), 1.0f);
|
||||
g_shaderSystem->SetUniformFloat4(shader, UNIFORM_CAMERA_POS, &campos);
|
||||
}
|
||||
|
||||
if (shader->HasUniform(UNIFORM_SUN_DIRECTION))
|
||||
{
|
||||
glm::vec4 lightPos = glm::vec4(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
|
||||
g_debugRender->DrawAxis(glm::vec3(lightPos));
|
||||
|
||||
Camera* camera = g_cameraManager.GetActiveCamera();
|
||||
if (camera)
|
||||
lightPos = glm::vec4(camera->GetPosition(), 1.0f);
|
||||
|
||||
g_shaderSystem->SetUniformFloat4(shader, UNIFORM_SUN_DIRECTION, &lightPos);
|
||||
}
|
||||
|
||||
if (shader->HasUniform(UNIFORM_SUN_AMBIENT))
|
||||
{
|
||||
glm::vec4 lightColor = glm::vec4(0.1f);
|
||||
g_shaderSystem->SetUniformFloat4(shader, UNIFORM_SUN_AMBIENT, &lightColor);
|
||||
}
|
||||
|
||||
g_texturesManager->SetTexture(0, albedoTexture);
|
||||
g_shaderSystem->SetUniformSampler(shader, SAMPLER_ALBEDO, 0);
|
||||
}
|
||||
|
||||
void SceneStaticMesh::RenderObjects()
|
||||
{
|
||||
glFrontFace(GL_CCW);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
@@ -660,17 +850,7 @@ void SceneStaticMesh::RenderObjects()
|
||||
|
||||
g_renderDevice->SetVerticesBuffer(m_vb);
|
||||
|
||||
g_shaderSystem->SetShader(g_litShader);
|
||||
|
||||
static glm::mat4 s_identity = glm::mat4(1.0f);
|
||||
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &s_identity[0]);
|
||||
|
||||
glm::mat4 mvp = glm::identity<glm::mat4>();
|
||||
mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix();
|
||||
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
|
||||
|
||||
g_texturesManager->SetTexture(0, m_albedoTexture);
|
||||
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
|
||||
R_SceneStaticMesh_BindShader(s_identity, m_albedoTexture);
|
||||
|
||||
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_vbcount);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
~SceneStaticMesh();
|
||||
|
||||
void LoadObj(const char* filename);
|
||||
void LoadBin(const char* filename);
|
||||
void LoadMtl(const char* filename);
|
||||
|
||||
const BoundingBox& GetBoundingBox() { return m_boundingBox; }
|
||||
|
||||
@@ -12,6 +12,7 @@ static const char* g_uniformNameTable[UNIFORM_MAX] =
|
||||
"u_sunDirection",
|
||||
"u_sunColor",
|
||||
"u_sunAmbientColor",
|
||||
"u_cameraPos",
|
||||
};
|
||||
|
||||
static const char* g_samplersNameTable[SAMPLER_MAX] =
|
||||
|
||||
Reference in New Issue
Block a user