bullet3d support, Humanoid controlling
This commit is contained in:
parent
ed414707c1
commit
461866a1a4
|
|
@ -34,6 +34,7 @@ jobs:
|
|||
mingw-w64-${{ matrix.env }}-pugixml
|
||||
mingw-w64-${{ matrix.env }}-ogre3d
|
||||
mingw-w64-${{ matrix.env }}-qt6
|
||||
mingw-w64-${{ matrix.env }}-bullet
|
||||
|
||||
- name: Generate Ninja build files
|
||||
run: cmake -G Ninja -B build -DCI=ON -DCMAKE_BUILD_TYPE=${{ matrix.configuration == 'Release' && 'MinSizeRel' || matrix.configuration }} .
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ add_compile_options(-Wno-attributes -Wno-return-type) # Ignore warnings generate
|
|||
find_package(Boost REQUIRED)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites CONFIG)
|
||||
find_package(pugixml REQUIRED)
|
||||
find_package(Bullet CONFIG REQUIRED)
|
||||
set(RNR_BULLET_LIBRARIES LinearMath Bullet3Common BulletDynamics BulletSoftBody BulletCollision BulletInverseDynamics)
|
||||
|
||||
add_subdirectory(Projects)
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 218159140c7d79ae745e646da721d12331f536f5
|
||||
Subproject commit e25de95445f2d635a125ab463426bb7fda017093
|
||||
|
|
@ -76,7 +76,7 @@ namespace RNR
|
|||
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
|
||||
std::filesystem::create_directory("ShaderCache");
|
||||
}
|
||||
|
||||
|
||||
ogreShaderGen->setShaderCachePath("ShaderCache/");
|
||||
ogreShaderGen->addSceneManager(ogreSceneManager);
|
||||
|
||||
|
|
@ -220,7 +220,11 @@ namespace RNR
|
|||
|
||||
void OgreWidget::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
delete world;
|
||||
|
||||
ogreWindow->destroy();
|
||||
ogreRoot->destroySceneManager(ogreSceneManager);
|
||||
ogreRoot->shutdown();
|
||||
}
|
||||
|
||||
QPaintEngine* OgreWidget::paintEngine() const
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ void MainWindow::playSolo()
|
|||
|
||||
RNR::Players* players = (RNR::Players*)this->ogreWidget->world->getDatamodel()->getService("Players");
|
||||
RNR::Player* player = players->createLocalPlayer(0);
|
||||
if(!player)
|
||||
return;
|
||||
player->setName(QInputDialog::getText(this, "Player Name", "Enter your player name").toLocal8Bit().data());
|
||||
player->loadCharacter();
|
||||
|
||||
|
|
|
|||
|
|
@ -67,5 +67,7 @@ add_library(Engine STATIC
|
|||
Source/Rendering/Adorn.cpp
|
||||
)
|
||||
|
||||
target_include_directories(Engine PUBLIC ${Boost_INCLUDE_DIRS} Header/)
|
||||
target_link_libraries(Engine PUBLIC ${Boost_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM)
|
||||
target_include_directories(Engine PUBLIC ${Boost_INCLUDE_DIRS} ${BULLET_ROOT_DIR}/${BULLET_INCLUDE_DIR} Header/)
|
||||
target_compile_definitions(Engine PUBLIC ${BULLET_DEFINITIONS})
|
||||
target_link_directories(Engine PUBLIC ${Bullet_DIR}/${BULLET_ROOT_DIR}/${BULLET_LIBRARY_DIRS})
|
||||
target_link_libraries(Engine PUBLIC ${Boost_LIBRARIES} ${RNR_BULLET_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM)
|
||||
|
|
@ -20,6 +20,7 @@ namespace RNR
|
|||
PartInstance* getTorso();
|
||||
PartInstance* getHead();
|
||||
|
||||
void inputFrame(float dx, float dy);
|
||||
void createHealthBar();
|
||||
|
||||
float getHealth() { return m_health; };
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace RNR
|
|||
{
|
||||
World* m_world;
|
||||
std::vector<int> scancodes_down;
|
||||
float m_mouseDX;
|
||||
float m_mouseDY;
|
||||
protected:
|
||||
MouseState state;
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace RNR
|
|||
private:
|
||||
CoordinateFrame m_cframe;
|
||||
CoordinateFrame m_focus;
|
||||
Ogre::Radian m_yaw;
|
||||
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
|
||||
virtual void addProperties(std::vector<ReflectionProperty>& properties);
|
||||
public:
|
||||
|
|
@ -24,6 +25,7 @@ namespace RNR
|
|||
virtual std::string getClassName() { return "Camera"; }
|
||||
CoordinateFrame& getCFrame() { return m_cframe; };
|
||||
CoordinateFrame& getFocus() { return m_focus; }
|
||||
Ogre::Radian getYaw() { return m_yaw; }
|
||||
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
|
||||
void setFocus(CoordinateFrame focus) { m_focus = focus; }
|
||||
bool zoom(float distance);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace RNR
|
|||
|
||||
public:
|
||||
Instance();
|
||||
~Instance();
|
||||
virtual ~Instance();
|
||||
|
||||
virtual std::vector<ReflectionProperty> getProperties();
|
||||
void deserializeXmlProperty(pugi::xml_node prop); // TODO: eventually replace this with a method that uses getProperties
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace RNR
|
|||
|
||||
CoordinateFrame& getCFrame() { return m_cframe; };
|
||||
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
|
||||
Ogre::Vector3 relativePositionTo(PVInstance* point);
|
||||
virtual std::string getClassName() { return "PVInstance"; }
|
||||
|
||||
Ogre::Vector3 getPosition() { return m_cframe.getPosition(); }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#include <OGRE/Ogre.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <stack>
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
|
|
@ -28,6 +31,7 @@ namespace RNR
|
|||
private:
|
||||
std::map<std::string, Instance*> m_refs;
|
||||
std::stack<WorldUndeserialized> m_undeserialized;
|
||||
btDiscreteDynamicsWorld* m_dynamicsWorld;
|
||||
DataModel* m_datamodel;
|
||||
Workspace* m_workspace;
|
||||
RunService* m_runService;
|
||||
|
|
@ -52,6 +56,7 @@ namespace RNR
|
|||
double step(float timestep);
|
||||
void update();
|
||||
|
||||
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
|
||||
float getLastDelta() { return m_lastDelta; }
|
||||
DataModel* getDatamodel() { return m_datamodel; }
|
||||
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ namespace RNR
|
|||
void TopMenuBar::frame()
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
btDiscreteDynamicsWorld* dynamicsWorld = m_world->getDynamicsWorld();
|
||||
|
||||
char debugtext[512];
|
||||
char render_debugtext[255];
|
||||
|
|
@ -127,7 +128,11 @@ namespace RNR
|
|||
snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size());
|
||||
break;
|
||||
}
|
||||
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n",m_world->getLastDelta(),render_debugtext,m_world->getOgreSceneManager());
|
||||
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n\nPhysics\n%i objects, %i constraints",
|
||||
m_world->getLastDelta(),
|
||||
render_debugtext,
|
||||
m_world->getOgreSceneManager(),
|
||||
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints());
|
||||
m_debugText->setCaption(debugtext);
|
||||
|
||||
Players* players = (Players*)m_world->getDatamodel()->getService("Players");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <App/V8/World/World.hpp>
|
||||
#include <App/InputManager.hpp>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
|
|
@ -45,13 +46,38 @@ namespace RNR
|
|||
}
|
||||
if(getNode())
|
||||
world->getOgreSceneManager()->destroySceneNode(getNode());
|
||||
|
||||
setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode());
|
||||
Ogre::BillboardSet* healthBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidHealth" + getParent()->getName());
|
||||
Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(100, 0, 200));
|
||||
getNode()->attachObject(healthBarSet);
|
||||
getNode()->setPosition(getHead()->getPosition());
|
||||
healthBarSet->setBillboardType(Ogre::BillboardType::BBT_PERPENDICULAR_COMMON);
|
||||
healthBarSet->setDebugDisplayEnabled(true);
|
||||
//Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(1, 0, 0, 1));
|
||||
Ogre::Billboard* healthBarBillboardFilled = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(0, 1, 0, 1));
|
||||
float healthBarScale = 0.5f;
|
||||
//healthBarBillboard->setDimensions(5 * healthBarScale, 1 * healthBarScale);
|
||||
healthBarBillboardFilled->setDimensions((m_health / m_maxHealth) * 5.f * healthBarScale, 1 * healthBarScale);
|
||||
healthBarSet->setCastShadows(true);
|
||||
|
||||
printf("Humanoid::createHealthBar: WIP");
|
||||
Ogre::BillboardSet* nameBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidName" + getParent()->getName());
|
||||
nameBarSet->setDebugDisplayEnabled(true);
|
||||
Ogre::FontPtr comic = Ogre::FontManager::getSingletonPtr()->getByName("ComicSans");
|
||||
if(!comic)
|
||||
printf("Humanoid::createHealthBar: comic == NULL\n");
|
||||
comic->putText(nameBarSet, getParent()->getName(), 1);
|
||||
int num_billboards = nameBarSet->getNumBillboards();
|
||||
for(int i = 0; i < num_billboards; i++)
|
||||
{
|
||||
Ogre::Billboard* chara = nameBarSet->getBillboard(i);
|
||||
Ogre::Vector3 chara_pos = chara->getPosition();
|
||||
chara_pos.y += 2 + healthBarScale;
|
||||
chara->setPosition(chara_pos);
|
||||
}
|
||||
getNode()->attachObject(healthBarSet);
|
||||
getNode()->attachObject(nameBarSet);
|
||||
getNode()->setPosition(getHead()->getPosition());
|
||||
getNode()->setOrientation(getHead()->getRotation());
|
||||
|
||||
printf("Humanoid::createHealthBar: WIP\n");
|
||||
}
|
||||
|
||||
void Humanoid::deserializeProperty(char* prop_name, pugi::xml_node prop)
|
||||
|
|
@ -66,6 +92,58 @@ namespace RNR
|
|||
}
|
||||
}
|
||||
|
||||
void Humanoid::inputFrame(float dx, float dy)
|
||||
{
|
||||
IInputManager* inputManager = world->getInputManager();
|
||||
PartInstance* torso = getTorso();
|
||||
Camera* camera = world->getWorkspace()->getCurrentCamera();
|
||||
if(!torso)
|
||||
{
|
||||
printf("Humanoid::inputFrame: no torso\n");
|
||||
return;
|
||||
}
|
||||
if(inputManager)
|
||||
{
|
||||
Ogre::Matrix3 camera_rotation;
|
||||
camera_rotation.FromEulerAnglesYXZ(camera->getYaw(), Ogre::Radian(0), Ogre::Radian(0)); // we only want yaw because otherwise the movement target will go through the ground/in the air
|
||||
Ogre::Quaternion direction = torso->getRotation();
|
||||
Ogre::Quaternion new_direction = Ogre::Quaternion::nlerp(0.5f, direction, camera_rotation);
|
||||
float forward = 0;
|
||||
|
||||
if(inputManager->isKeyDown('W'))
|
||||
forward = 16;
|
||||
|
||||
Ogre::Vector3 move = Ogre::Vector3(0, 0, -forward);
|
||||
move = direction * move;
|
||||
move *= world->getLastDelta();
|
||||
|
||||
bool move_valid = true;
|
||||
|
||||
// TODO: collision checking
|
||||
|
||||
if(!move_valid)
|
||||
return;
|
||||
|
||||
for(auto& child : *getParent()->getChildren())
|
||||
{
|
||||
PartInstance* bp = dynamic_cast<PartInstance*>(child);
|
||||
if(bp)
|
||||
{
|
||||
Ogre::Vector3 bp_p = bp->getPosition();
|
||||
bp_p += move;
|
||||
bp->getCFrame().setPosition(bp_p);
|
||||
Ogre::Matrix3 new_rotation_matrix;
|
||||
new_direction.ToRotationMatrix(new_rotation_matrix);
|
||||
bp->getCFrame().setRotation(new_rotation_matrix);
|
||||
bp->updateMatrix();
|
||||
world->getWorkspace()->setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
camera->getCFrame().setPosition(camera->getCFrame().getPosition() + move);
|
||||
}
|
||||
}
|
||||
|
||||
void Humanoid::addProperties(std::vector<ReflectionProperty>& properties)
|
||||
{
|
||||
ReflectionProperty _properties[] = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <App/InputManager.hpp>
|
||||
#include <App/V8/DataModel/Camera.hpp>
|
||||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace RNR
|
||||
|
|
@ -9,8 +10,7 @@ namespace RNR
|
|||
state.mouse_primary = false;
|
||||
state.mouse_secondary = false;
|
||||
state.mouse_middle = false;
|
||||
state.mouse_scroll = 0;
|
||||
}
|
||||
state.mouse_scroll = 0; }
|
||||
|
||||
void IInputManager::keyDown(int scancode)
|
||||
{
|
||||
|
|
@ -43,14 +43,14 @@ namespace RNR
|
|||
{
|
||||
if(m_world)
|
||||
{
|
||||
float xd = x * m_world->getLastDelta();
|
||||
float yd = y * m_world->getLastDelta();
|
||||
m_mouseDX = x * m_world->getLastDelta();
|
||||
m_mouseDY = y * m_world->getLastDelta();
|
||||
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera && state.mouse_secondary)
|
||||
{
|
||||
camera->cameraFrame(xd, yd);
|
||||
camera->cameraFrame(m_mouseDX, m_mouseDY);
|
||||
|
||||
resetMouse();
|
||||
}
|
||||
|
|
@ -59,10 +59,29 @@ namespace RNR
|
|||
|
||||
void IInputManager::frame()
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera)
|
||||
camera->cameraFrame(0, 0, false); // update camera position
|
||||
Players* players = (Players*)m_world->getDatamodel()->getService("Players");
|
||||
Player* localPlayer = players->getLocalPlayer();
|
||||
if(localPlayer)
|
||||
{
|
||||
ModelInstance* character = localPlayer->getCharacter();
|
||||
if(character)
|
||||
{
|
||||
Humanoid* humanoid = (Humanoid*)character->findFirstChildOfType("Humanoid");
|
||||
if(humanoid)
|
||||
{
|
||||
humanoid->inputFrame(m_mouseDX, m_mouseDY);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera)
|
||||
camera->cameraFrame(0, 0, false); // update camera position
|
||||
}
|
||||
m_mouseDX = 0;
|
||||
m_mouseDY = 0;
|
||||
}
|
||||
|
||||
void IInputManager::mousePrimaryState(bool down)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace RNR
|
|||
|
||||
pitch = old_pitch + pitch;
|
||||
yaw = old_yaw - yaw;
|
||||
m_yaw = yaw;
|
||||
|
||||
Ogre::Matrix3 rotation;
|
||||
rotation.FromEulerAnglesYXZ(yaw, pitch, Ogre::Radian(0));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace RNR
|
|||
Workspace::Workspace() : ModelInstance()
|
||||
{
|
||||
setName("Workspace");
|
||||
m_batchMode = BATCH_STATIC_GEOMETRY;
|
||||
m_batchMode = BATCH_DONT;
|
||||
|
||||
m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode();
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,17 @@ namespace RNR
|
|||
Instance::~Instance()
|
||||
{
|
||||
setParent(NULL);
|
||||
if(getNode())
|
||||
{
|
||||
getNode()->removeAndDestroyAllChildren();
|
||||
delete getNode();
|
||||
}
|
||||
if(getObject())
|
||||
{
|
||||
if(getObject()->getParentNode() != 0)
|
||||
getObject()->detachFromParent();
|
||||
delete getObject();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ReflectionProperty> Instance::getProperties()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace RNR
|
|||
{
|
||||
PVInstance::PVInstance() : m_cframe(), Instance()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PVInstance::deserializeProperty(char* prop_name, pugi::xml_node node)
|
||||
|
|
@ -28,4 +28,9 @@ namespace RNR
|
|||
|
||||
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
|
||||
}
|
||||
|
||||
Ogre::Vector3 PVInstance::relativePositionTo(PVInstance* point)
|
||||
{
|
||||
return point->getPosition() - getPosition();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,13 @@ namespace RNR
|
|||
{
|
||||
Instance::setWorld(this);
|
||||
|
||||
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
|
||||
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
|
||||
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
|
||||
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
|
||||
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
|
||||
|
||||
m_inputManager = 0;
|
||||
|
||||
m_instanceFactory = new InstanceFactory();
|
||||
|
|
@ -112,7 +119,7 @@ namespace RNR
|
|||
m_undeserialized.pop();
|
||||
|
||||
s.instance->setParent(s.parent);
|
||||
|
||||
|
||||
pugi::xml_node props = s.node.child("Properties");
|
||||
for(pugi::xml_node prop : props.children())
|
||||
{
|
||||
|
|
@ -143,7 +150,10 @@ namespace RNR
|
|||
double World::step(float timestep)
|
||||
{
|
||||
if(m_runService && m_runService->getRunning())
|
||||
{
|
||||
m_runService->step(timestep);
|
||||
m_dynamicsWorld->stepSimulation(timestep);
|
||||
}
|
||||
m_lastDelta = timestep;
|
||||
return 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,19 @@ namespace RNR
|
|||
PartInstance* head = new PartInstance();
|
||||
head->setName("Head");
|
||||
head->setSize(Ogre::Vector3(2, 1, 1));
|
||||
head->setBrickColor(24);
|
||||
head->getCFrame().setPosition(Ogre::Vector3(0, 1.5, 0));
|
||||
head->updateMatrix();
|
||||
head->setParent(m_character);
|
||||
|
||||
PartInstance* torso = new PartInstance();
|
||||
torso->setName("Torso");
|
||||
torso->setSize(Ogre::Vector3(2, 2, 1));
|
||||
torso->setBrickColor(23);
|
||||
torso->getCFrame().setPosition(Ogre::Vector3(0, 0, 0));
|
||||
torso->updateMatrix();
|
||||
torso->setParent(m_character);
|
||||
|
||||
Humanoid* character_humanoid = new Humanoid();
|
||||
character_humanoid->setParent(m_character);
|
||||
m_character->setParent(world->getWorkspace());
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ namespace RNR
|
|||
{
|
||||
if(m_localPlayer)
|
||||
{
|
||||
printf("Players::createLocalPlayer: attempt to create another local player\n", userId);
|
||||
return m_localPlayer;
|
||||
printf("Players::createLocalPlayer: attempt to create another local player %i\n", userId);
|
||||
return 0;
|
||||
}
|
||||
printf("Players::createLocalPlayer: created player %i\n", userId);
|
||||
m_localPlayer = new Player();
|
||||
|
|
|
|||
Loading…
Reference in New Issue