This commit is contained in:
2026-03-05 01:42:40 +03:00
parent 2815369bb8
commit 4290e99c61
31 changed files with 2285 additions and 99 deletions

View File

@@ -1,16 +1,4 @@
<Scene> <Scene>
<StaticMesh filename="graveyard_fence.obj" shader="lightmapped"/> <StaticMesh filename="graveyard_fence.obj" shader="lightmapped"/>
<StaticMesh filename="graveyard_fence_001.obj" shader="lightmapped"/> <StaticMesh filename="graveyard_terrain.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"/>
</Scene> </Scene>

View File

@@ -5,7 +5,8 @@
</LevelDescription> </LevelDescription>
<Entities> <Entities>
<Entity classname="TempPlayer"> <Entity classname="actor_player">
<Position x="1.0" y="5.0" z="1.0" />
<IsDisableled value="false" /> <IsDisableled value="false" />
</Entity> </Entity>
</Entities> </Entities>

Binary file not shown.

View 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

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -5,10 +5,7 @@
</LevelDescription> </LevelDescription>
<Entities> <Entities>
<Entity classname="TempPlayer"> <Entity classname="actor_player">
<IsDisableled value="false" />
</Entity>
<Entity classname="game_object">
<IsDisableled value="false" /> <IsDisableled value="false" />
</Entity> </Entity>
</Entities> </Entities>

View 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

View File

@@ -1,13 +1,19 @@
-- Game initialization script -- Game initialization script
-- загружаем скрипты -- загружаем скрипты
load_script("game_utils.lua")
load_script("game_object.lua") load_script("game_object.lua")
load_script("test_object.lua")
load_script("actors/actor_player.lua")
-- глобальная таблица сущностей -- глобальная таблица сущностей
g_entity_table = { 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" },
} }

View 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

View 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

View File

@@ -5,14 +5,26 @@ varying vec3 v_normal;
varying vec2 v_texcoord; varying vec2 v_texcoord;
varying vec3 v_finalColor; varying vec3 v_finalColor;
uniform sampler2D u_albedoTexture;
uniform vec4 u_customColor; uniform vec4 u_customColor;
uniform vec4 u_sunAmbientColor;
uniform sampler2D u_albedoTexture;
void main() { void main() {
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //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 = 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 = 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 = vec4( v_normal, 1.0 );
//gl_FragColor = texture2D(u_albedoTexture, v_texcoord); //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);
} }

View File

@@ -13,34 +13,41 @@ uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix; uniform mat4 u_viewMatrix;
uniform mat4 u_projectionMatrix; uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewProjection; uniform mat4 u_modelViewProjection;
uniform vec4 u_sunDirection;
uniform vec4 u_sunColor;
uniform vec4 u_sunAmbientColor;
uniform vec4 u_cameraPos;
vec3 CalcOmniLight() // #TODO: should use own uniforms
{ #define u_ligthPosition u_sunDirection.xyz
vec3 lightPos = vec3(0.1, 2.1, 0.1); #define u_ligthRadius u_sunDirection.w
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() // Calculate blinn-phong per-vertex lighting
{ float CalcPhongLighting( vec3 worldPos, vec3 normal, vec3 lightPos ) {
vec3 lightPos = vec3(5.0, 10.0, 1.0); vec3 lightDir = normalize( lightPos - worldPos );
//lightPos = -lightPos; vec3 viewDir = normalize( u_cameraPos.xyz - worldPos );
vec3 halfVec = normalize( lightDir + viewDir );
float diff = max( dot( normal, lightDir ), 0.0 );
vec3 L = normalize(lightPos); v_finalColor.x = diff;
vec3 N = normalize(v_normal);
vec3 col = vec3( max(0, dot(N, L)) ); float spec = pow( max( dot( normal, halfVec ), 0.0 ), 128.0 ) * 1.0;
col = col * 0.8 + 0.2;
return col; v_finalColor.y = spec;
return diff + spec;
} }
void main() { void main() {
v_position = vec3( u_modelMatrix * vec4(a_position, 1.0) ); v_position = vec3( u_modelMatrix * vec4(a_position, 1.0) );
v_normal = vec3( mat3(u_modelMatrix) * a_normal ); v_normal = vec3( mat3(u_modelMatrix) * a_normal );
v_texcoord = a_texcoord; 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); gl_Position = u_modelViewProjection * vec4(a_position, 1);
} }

View 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);
}

View 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);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -8,6 +8,7 @@
#include "world.h" #include "world.h"
#include "camera.h" #include "camera.h"
#include "inputmanager.h" #include "inputmanager.h"
#include "physics/physicsworld.h"
// renderer // renderer
#include "render.h" #include "render.h"
@@ -221,6 +222,10 @@ void Engine::Frame()
// *** ImGui scope begin // *** ImGui scope begin
g_ImGuiManager.BeginFrame(); g_ImGuiManager.BeginFrame();
// update physics
if (g_PhysicsWorld)
g_PhysicsWorld->Step(dt);
// update entities // update entities
if (g_world) if (g_world)
g_world->Update(dt); g_world->Update(dt);
@@ -300,6 +305,9 @@ void Engine::NewGame(const char* mapname)
// create entity container // create entity container
Disconnect(); Disconnect();
g_PhysicsWorld = new PhysicsWorld();
//g_PhysicsWorld->ToggleDebugDraw();
g_world = new World(); g_world = new World();
g_render->LoadSceneXML(mapname); g_render->LoadSceneXML(mapname);
@@ -316,6 +324,11 @@ void Engine::Disconnect()
delete g_world; delete g_world;
g_world = nullptr; g_world = nullptr;
} }
if (g_PhysicsWorld) {
delete g_PhysicsWorld;
g_PhysicsWorld = nullptr;
}
} }
SDL_Window* Engine::GetWindow() SDL_Window* Engine::GetWindow()

View File

@@ -23,6 +23,11 @@ void IEntityBase::Render()
{ {
} }
void IEntityBase::SetPosition(const glm::vec3& pos)
{
m_position = pos;
}
const glm::mat4& IEntityBase::GetWorldTransform() const glm::mat4& IEntityBase::GetWorldTransform()
{ {
return m_worldTM; return m_worldTM;

View File

@@ -17,6 +17,8 @@ public:
const BoundingBox& GetBoundingBox() { return m_boundingBox; } const BoundingBox& GetBoundingBox() { return m_boundingBox; }
void SetPosition(const glm::vec3& pos);
const glm::mat4& GetWorldTransform(); const glm::mat4& GetWorldTransform();
void UpdateTransform(); void UpdateTransform();

View File

@@ -1,4 +1,5 @@
#include "engine/core.h" #include "engine/core.h"
#include "engine/log.h"
#include "engine/engine.h" #include "engine/engine.h"
#include "engine/camera.h" #include "engine/camera.h"
#include "engine/physics/physicsworld.h" #include "engine/physics/physicsworld.h"
@@ -10,6 +11,8 @@
#include <BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h> #include <BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h>
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h> #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
PhysicsWorld* g_PhysicsWorld = nullptr;
static void InternalTickCallback(btDynamicsWorld* world, btScalar timeStep) static void InternalTickCallback(btDynamicsWorld* world, btScalar timeStep)
{ {
SDL_assert(world); SDL_assert(world);
@@ -88,9 +91,9 @@ const std::vector<RigidBody*>& PhysicsWorld::GetRigidBodies()
void PhysicsWorld::Step(float delta) void PhysicsWorld::Step(float delta)
{ {
// m_world->stepSimulation(delta); m_world->stepSimulation(delta);
// m_world->stepSimulation(delta, 12, m_stepTime); // m_world->stepSimulation(delta, 12, m_stepTime);
#if 1 #if 0
if (delta < 0.01f) if (delta < 0.01f)
{ {
m_accumulatedTime += delta; 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;
}

View File

@@ -6,7 +6,16 @@
#include <vector> #include <vector>
struct StaticMeshVertex;
class RigidBody; class RigidBody;
class IEntityBase;
struct SceneCollisionModel
{
btCollisionObject* object;
btCollisionShape* shape;
btTriangleMesh* triangleMesh;
};
class PhysicsWorld class PhysicsWorld
{ {
@@ -29,8 +38,16 @@ public:
void InternalTick(); 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: private:
std::vector<SceneCollisionModel> m_collisionModels;
btDefaultCollisionConfiguration* m_collisionConfiguration; btDefaultCollisionConfiguration* m_collisionConfiguration;
btCollisionDispatcher* m_dispatcher; btCollisionDispatcher* m_dispatcher;
btBroadphaseInterface* m_overlappingPairCache; btBroadphaseInterface* m_overlappingPairCache;
@@ -48,4 +65,20 @@ private:
bool m_debugDraw; 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 #endif // !PHYSICSWORLD_H

View File

@@ -21,6 +21,9 @@ World::~World()
void World::DestroyWorld() void World::DestroyWorld()
{ {
// Run destroyer
UpdateDestroyList();
for (int i = 0; i < m_entities.size(); ++i) for (int i = 0; i < m_entities.size(); ++i)
{ {
delete m_entities[i]; delete m_entities[i];

View File

@@ -30,21 +30,19 @@ void engineWarning(const char* msg)
LuaPlus::LuaObject engineCreateEntity(const char* classname) LuaPlus::LuaObject engineCreateEntity(const char* classname)
{ {
LuaPlus::LuaObject entityObject; Entity* entity = static_cast<Entity*>(g_game->Lua_CreateEntity(classname));
entityObject.AssignNewTable(GetLuaState()); SDL_assert_always(entity);
//GameObject* entity = (GameObject*)g_entityManager->createEntity(classname); return entity->GetLuaObject();
//entity->init_from_lua(entityObject);
//entity->init();
return entityObject;
} }
void engineAddEntityToWorld(LuaPlus::LuaObject& object) 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() void registerEngine()
@@ -108,6 +106,11 @@ void initializeEntityPrototypesFromLua()
prototype.m_description = description.ToString(); prototype.m_description = description.ToString();
g_prototypes.push_back(prototype); 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()) { /*for (LuaTableIterator it2(entityTable); it2; it2.Next()) {
Logger::Msg("%s", it2.GetValue().ToString()); Logger::Msg("%s", it2.GetValue().ToString());
@@ -180,9 +183,9 @@ void Game::LoadLevelXML(const char* mapname)
// std::map<std::string, std::string> properties; // std::map<std::string, std::string> properties;
for (pugi::xml_node entity : doc.child("Level").child("Entities").children("Entity")) { for (pugi::xml_node entitynode : doc.child("Level").child("Entities").children("Entity")) {
pugi::xml_attribute entityname = entity.attribute("name"); pugi::xml_attribute entityname = entitynode.attribute("name");
pugi::xml_attribute classname = entity.attribute("classname"); pugi::xml_attribute classname = entitynode.attribute("classname");
if (classname.empty()) { if (classname.empty()) {
if (!entityname.empty()) { if (!entityname.empty()) {
@@ -199,6 +202,16 @@ void Game::LoadLevelXML(const char* mapname)
if (!entity) if (!entity)
entity = g_entityManager->CreateEntity(classname.as_string()); 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()); //IEntityBase* entity = g_entityManager->CreateEntity(classname.as_string());
g_world->AddEntity(entity); g_world->AddEntity(entity);
} }
@@ -235,7 +248,7 @@ IEntityBase* Game::Lua_CreateEntity(const char* classname)
// get a prototype // get a prototype
LuaObject prototype = GetLuaState().GetGlobal(pluaprototype->m_luaname.c_str()); LuaObject prototype = GetLuaState().GetGlobal(pluaprototype->m_luaname.c_str());
SDL_assert_always(!prototype.IsNil()); SDL_assert_always(!prototype.IsNil());
prototype.SetObject("__index", prototype); //prototype.SetObject("__index", prototype);
// generate table // generate table
LuaObject factory = GetLuaState().GetGlobal("g_factory"); LuaObject factory = GetLuaState().GetGlobal("g_factory");

View File

@@ -1,7 +1,19 @@
#include "inputmanager.h" #include "inputmanager.h"
#include "debugrender.h"
#include "game_object.h" #include "game_object.h"
#include <SDL3/SDL.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 // Lua wrappers
void Entity_LoadModel(LuaPlus::LuaState* state) void Entity_LoadModel(LuaPlus::LuaState* state)
{ {
@@ -11,6 +23,46 @@ void Entity_LoadModel(LuaPlus::LuaState* state)
entity->LoadModel(stack[2].GetString()); 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); REGISTER_ENTITY(Entity);
Entity::Entity() : Entity::Entity() :
@@ -44,14 +96,31 @@ void Entity::Update(float dt)
if ( m_onUpdateFunction.IsFunction()) if ( m_onUpdateFunction.IsFunction())
{ {
LuaPlus::LuaFunctionVoid function = m_onUpdateFunction; LuaPlus::LuaFunctionVoid function = m_onUpdateFunction;
function(m_luaObject, dt); function(m_luaObject, static_cast<lua_Number>(dt));
} }
} }
void Entity::Render() void Entity::Render()
{ {
if (m_model) if (m_model)
{
m_model->Draw(GetWorldTransform()); 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) void Entity::LoadModel(const char* filename)
@@ -83,10 +152,11 @@ void Entity::InitFromTable(LuaPlus::LuaObject& _object)
// check // check
SDL_assert_always(m_onInitFunction.IsFunction() || m_onShutdownFunction.IsFunction() || m_onUpdateFunction.IsFunction()); SDL_assert_always(m_onInitFunction.IsFunction() || m_onShutdownFunction.IsFunction() || m_onUpdateFunction.IsFunction());
// register base entity functions
RegisterBaseFunctions();
// register entity functions // register entity functions
m_luaObject.RegisterDirect("load_model", &Entity_LoadModel); RegisterFunctions();
//m_luaObject.RegisterDirect("set_visible", &Entity::SetVisible);
//m_luaObject.RegisterDirect("get_visible", &Entity::GetVisible);
// assign C++ object // assign C++ object
m_luaObject.SetLightUserdata("__object", this); m_luaObject.SetLightUserdata("__object", this);
@@ -96,29 +166,141 @@ void Entity::InitFromTable(LuaPlus::LuaObject& _object)
onInitFunction(m_luaObject); 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 // calculate player movement
float speed = 19.0f * dt; float speed = 12.0f * dt;
uint32_t movementDir = GenMovementDir(); uint32_t movementDir = GenMovementDir();
@@ -135,10 +317,41 @@ void TempPlayer::UpdateCameraMovement(float dt)
m_camera.SetPosition(m_position); 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(); glm::ivec2 mousePos = g_inputManager.GetMousePos();
// calculate yaw and pitch // calculate yaw and pitch
@@ -158,7 +371,132 @@ void TempPlayer::UpdateCameraLook()
m_camera.SetYawPitch(yaw, pitch); 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; uint32_t movementDir = EMovementDir_None;
@@ -178,6 +516,10 @@ uint32_t TempPlayer::GenMovementDir()
movementDir |= EMovementDir_Right; movementDir |= EMovementDir_Right;
} }
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_SPACE)) {
movementDir |= EMovementDir_Jump;
}
return movementDir; return movementDir;
} }

View File

@@ -1,8 +1,11 @@
#ifndef GAME_OBJECT_H #ifndef GAME_OBJECT_H
#define GAME_OBJECT_H #define GAME_OBJECT_H
#include <string>
#include "engine/ientity.h" #include "engine/ientity.h"
#include "engine/camera.h" #include "engine/camera.h"
#include "engine/physics/physicsworld.h"
#include "render/model.h" #include "render/model.h"
#include "render/modelsystem.h" #include "render/modelsystem.h"
@@ -15,9 +18,47 @@ enum EMovmentDir
EMovementDir_Forward = 1 << 1, EMovementDir_Forward = 1 << 1,
EMovementDir_Backward = 1 << 2, EMovementDir_Backward = 1 << 2,
EMovementDir_Left = 1 << 3, 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 class Entity : public IEntityBase
{ {
public: public:
@@ -28,14 +69,32 @@ public:
virtual void Render(); virtual void Render();
// Game entity extensions // Game entity extensions
const std::string& GetName();
void SetName(const std::string& name);
virtual void LoadModel(const char* filename); virtual void LoadModel(const char* filename);
void SetVisible(bool visible); void SetVisible(bool visible);
bool GetVisible(); bool GetVisible();
// Game entity lua bindings
void InitFromTable(LuaPlus::LuaObject& _object); 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: protected:
std::string m_name;
Model* m_model; Model* m_model;
LuaPlus::LuaObject m_luaObject; LuaPlus::LuaObject m_luaObject;
@@ -44,23 +103,52 @@ protected:
LuaPlus::LuaObject m_onUpdateFunction; LuaPlus::LuaObject m_onUpdateFunction;
}; };
class TempPlayer : public Entity class ActorBase : public Entity
{ {
public: public:
TempPlayer(); ActorBase();
~TempPlayer(); ~ActorBase();
virtual void Update(float dt); virtual void Update(float dt);
void AfterEngineStep();
void UpdateCameraMovement(float dt); void UpdateCameraMovement(float dt);
void UpdateBodyMovement(float dt);
void UpdateCameraLook(); 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: private:
uint32_t GenMovementDir(); uint32_t GenMovementDir();
private: private:
Camera m_camera; 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 class Weapon : public Entity

View File

@@ -12,7 +12,7 @@
#include "modelsystem.h" #include "modelsystem.h"
#include "texturesmanager.h" #include "texturesmanager.h"
extern Shader* g_litShader; extern Shader* g_unlitShader;
static std::string getFileNameWithoutExtension(const std::string& filename) 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*/) void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
{ {
SDL_assert(g_litShader); SDL_assert(g_unlitShader);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glDepthFunc(GL_LESS); 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); g_renderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f); 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 else
{ {
g_renderDevice->SetBlending(false); g_renderDevice->SetBlending(false);
//glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f); //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_renderDevice->SetVerticesBuffer(m_data.vb);
g_shaderSystem->SetShader(g_litShader); g_shaderSystem->SetShader(g_unlitShader);
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &model[0]); g_shaderSystem->SetUniformMatrix(g_unlitShader, UNIFORM_MODEL_MATRIX, &model[0]);
//static float test = 0.0f; //static float test = 0.0f;
//test += g_systemTimer->GetDelta() * 6.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>(); glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix() * model; 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_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); g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);

View File

@@ -26,6 +26,7 @@ static InputLayoutDesc_t g_skinnedVertexLayout[] = {
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD } { VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD }
}; };
Shader* g_unlitShader = nullptr;
Shader* g_litShader = nullptr; Shader* g_litShader = nullptr;
static std::string getFileNameWithoutExtension(const std::string& filename) static std::string getFileNameWithoutExtension(const std::string& filename)
@@ -48,7 +49,11 @@ ModelSystem::~ModelSystem()
void ModelSystem::Init() 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_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])); g_staticVertexLayout, sizeof(g_staticVertexLayout) / sizeof(g_staticVertexLayout[0]));
} }

View File

@@ -206,6 +206,7 @@ enum ShaderUniform_t
UNIFORM_SUN_DIRECTION, UNIFORM_SUN_DIRECTION,
UNIFORM_SUN_COLOR, UNIFORM_SUN_COLOR,
UNIFORM_SUN_AMBIENT, UNIFORM_SUN_AMBIENT,
UNIFORM_CAMERA_POS,
UNIFORM_MAX, UNIFORM_MAX,
}; };

View File

@@ -12,6 +12,9 @@
#include "render/shadersystem.h" #include "render/shadersystem.h"
#include "render/render.h" #include "render/render.h"
#include "render/debugrender.h" #include "render/debugrender.h"
#include "render/gpu_buffer.h"
#include "engine/camera.h"
#include "engine/physics/physicsworld.h"
#include <pugixml.hpp> #include <pugixml.hpp>
@@ -54,6 +57,37 @@ static std::string getFilenameWithoutPathAndExtension(const std::string& filenam
return string; 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 //#ifdef NDEBUG
//#pragma comment(lib, "assimp-vc141-mt.lib") //#pragma comment(lib, "assimp-vc141-mt.lib")
//#else //#else
@@ -329,7 +363,13 @@ void SceneManager::loadStaticMesh(const char* filename)
if (GetFileSystem()->IsExist(filenamebuf)) { if (GetFileSystem()->IsExist(filenamebuf)) {
SceneStaticMesh* staticMesh = new SceneStaticMesh(); 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); 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_Vertices = vertices;
m_vb = g_renderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size()); 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); std::string mtlfilename = getFileNameWithoutExtension(filename);
mtlfilename += ".mtl"; mtlfilename += ".mtl";
LoadMtl(mtlfilename.c_str()); 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) void SceneStaticMesh::LoadMtl(const char* filename)
@@ -643,12 +788,57 @@ void SceneStaticMesh::LoadMtl(const char* filename)
fclose(file); 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; extern Shader* g_litShader;
SDL_assert(g_unlitShader);
SDL_assert(g_litShader); 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); glFrontFace(GL_CCW);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
@@ -660,17 +850,7 @@ void SceneStaticMesh::RenderObjects()
g_renderDevice->SetVerticesBuffer(m_vb); g_renderDevice->SetVerticesBuffer(m_vb);
g_shaderSystem->SetShader(g_litShader); R_SceneStaticMesh_BindShader(s_identity, m_albedoTexture);
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);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_vbcount); g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_vbcount);
} }

View File

@@ -15,6 +15,7 @@ public:
~SceneStaticMesh(); ~SceneStaticMesh();
void LoadObj(const char* filename); void LoadObj(const char* filename);
void LoadBin(const char* filename);
void LoadMtl(const char* filename); void LoadMtl(const char* filename);
const BoundingBox& GetBoundingBox() { return m_boundingBox; } const BoundingBox& GetBoundingBox() { return m_boundingBox; }

View File

@@ -12,6 +12,7 @@ static const char* g_uniformNameTable[UNIFORM_MAX] =
"u_sunDirection", "u_sunDirection",
"u_sunColor", "u_sunColor",
"u_sunAmbientColor", "u_sunAmbientColor",
"u_cameraPos",
}; };
static const char* g_samplersNameTable[SAMPLER_MAX] = static const char* g_samplersNameTable[SAMPLER_MAX] =