Merge branch 'trunk' of https://github.com/lrre-foss/rnr into trunk

This commit is contained in:
sorket 2023-07-20 01:24:29 -04:00
commit 2df518efe1
41 changed files with 396 additions and 56 deletions

View File

@ -17,13 +17,13 @@ jobs:
shell: msys2 {0}
steps:
- uses: actions/checkout@v3
name: Clone repository
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive
- uses: msys2/setup-msys2@v2
name: Set up MSYS2 and install required packages
- name: Set up MSYS2 and install required packages
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
install: >-
@ -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 }} .
@ -58,7 +59,7 @@ jobs:
run: mkdir build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/Main/* build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/RTShaderLib/* build/dist/shaders
- name: Add additional runtime dependencies
run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "clang64" | xargs -I '{}' cp -v '{}' build/dist
run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "${{ matrix.sys }}" | xargs -I '{}' cp -v '{}' build/dist
- name: Set output variables
id: vars

View File

@ -16,11 +16,13 @@ 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)
if(CI AND UNIX)
file(COPY ${OGRE_MEDIA_DIR}/Main/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
file(COPY ${OGRE_MEDIA_DIR}/ShadowVolume/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
file(COPY ${OGRE_MEDIA_DIR}/RTShaderLib/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins)
endif()

View File

@ -16,7 +16,6 @@ material materials/partinstanced
rtshader_system
{
transform_stage instanced
lighting_stage per_pixel
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -34,6 +34,7 @@ namespace RNR
Ogre::SceneManager* ogreSceneManager;
Ogre::Camera* ogreCamera;
Ogre::Viewport* ogreViewport;
Ogre::Light* ogreSceneLight;
Ogre::RTShader::ShaderGenerator* ogreShaderGen;
QCursor cursor;

View File

@ -1,11 +1,13 @@
#include <OgreWidget.hpp>
#include <QApplication>
#include <filesystem>
#include <OGRE/Bites/OgreSGTechniqueResolverListener.h>
#include <OGRE/OgreDefaultDebugDrawer.h>
#include <OGRE/Overlay/OgreOverlaySystem.h>
#include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreFontManager.h>
#include <App/V8/DataModel/Lighting.hpp>
#ifdef __unix__
#include <qpa/qplatformnativeinterface.h>
@ -70,6 +72,11 @@ namespace RNR
if(Ogre::RTShader::ShaderGenerator::initialize())
{
ogreShaderGen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
ogreShaderGen->setShaderCachePath("ShaderCache/");
ogreShaderGen->addSceneManager(ogreSceneManager);
@ -90,19 +97,19 @@ namespace RNR
pFont->setTrueTypeSize(16);
pFont->load();
ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE);
ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_MODULATIVE);
ogreSceneManager->setShadowFarDistance(500.f);
Ogre::Light* light = ogreSceneManager->createLight("SunLight");
ogreSceneLight = ogreSceneManager->createLight("SunLight");
Ogre::SceneNode* lightNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode();
lightNode->setPosition(0, 10, 15);
lightNode->setDirection(-0.25, -0.5, -0.5);
lightNode->attachObject(light);
lightNode->attachObject(ogreSceneLight);
light->setCastShadows(true);
light->setDiffuseColour(0.9, 0.9, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
light->setType(Ogre::Light::LT_DIRECTIONAL);
ogreSceneLight->setCastShadows(true);
ogreSceneLight->setDiffuseColour(0.9, 0.9, 1.0);
ogreSceneLight->setSpecularColour(1.0, 1.0, 1.0);
ogreSceneLight->setType(Ogre::Light::LT_DIRECTIONAL);
Ogre::MaterialManager::getSingletonPtr()->reloadAll();
Ogre::MaterialManager::getSingletonPtr()->load("sky/null_plainsky512", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
@ -126,6 +133,21 @@ namespace RNR
ogreCamera->getParentSceneNode()->setPosition(cam->getCFrame().getPosition());
ogreCamera->getParentSceneNode()->setOrientation(Ogre::Quaternion(cam->getCFrame().getRotation()));
}
RNR::Lighting* lighting = (RNR::Lighting*)world->getDatamodel()->getService("Lighting");
if(lighting)
{
Ogre::Vector3 clearColor = lighting->getClearColor();
ogreViewport->setBackgroundColour(Ogre::ColourValue(clearColor.x, clearColor.y, clearColor.z));
Ogre::Vector3 shadowColor = lighting->getShadowColor();
ogreSceneManager->setShadowColour(Ogre::ColourValue(shadowColor.x, shadowColor.y, shadowColor.z));
Ogre::Vector3 topAmbient = lighting->getTopAmbient();
ogreSceneLight->setDiffuseColour(Ogre::ColourValue(topAmbient.x, topAmbient.y, topAmbient.z));
Ogre::Vector3 bottomAmbient = lighting->getBottomAmbient();
ogreSceneManager->setAmbientLight(Ogre::ColourValue(bottomAmbient.x, bottomAmbient.y, bottomAmbient.z));
Ogre::Vector3 spotLight = lighting->getSpotLight();
ogreSceneLight->setSpecularColour(Ogre::ColourValue(spotLight.x, spotLight.y, spotLight.z));
}
if(isVisible())
ogreRoot->renderOneFrame(this->delta);
@ -198,7 +220,11 @@ namespace RNR
void OgreWidget::closeEvent(QCloseEvent* event)
{
delete world;
ogreWindow->destroy();
ogreRoot->destroySceneManager(ogreSceneManager);
ogreRoot->shutdown();
}
QPaintEngine* OgreWidget::paintEngine() const

View File

@ -7,10 +7,6 @@
int main(int argc, char** argv)
{
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
QApplication app(argc, argv);
MainWindow window = MainWindow();

View File

@ -51,7 +51,7 @@ void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instanc
{
QString icon_path;
icon_path = "content/textures/studio/icons/";
icon_path += instance->getClassName();
icon_path += instance->getExplorerIcon();
icon_path += ".png";
QIcon icon;
if(QFile::exists(icon_path))
@ -138,7 +138,10 @@ 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();
updateTree(ogreWidget->world->getDatamodel());
}

View File

@ -81,7 +81,7 @@ void PropertyViewer::view(RNR::Instance* instance)
QImage image;
QString icon_path;
icon_path = "content/textures/studio/icons/";
icon_path += instance_ref->getClassName();
icon_path += instance_ref->getExplorerIcon();
icon_path += ".png";
if(QFile::exists(icon_path))
image = QImage(icon_path);

View File

@ -10,10 +10,6 @@
int main(int argc, char** argv)
{
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
QSurfaceFormat format;
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);

View File

@ -16,6 +16,7 @@ add_library(Engine STATIC
Header/App/V8/DataModel/ForceField.hpp
Header/App/V8/DataModel/PartInstance.hpp
Header/App/V8/DataModel/Light.hpp
Header/App/V8/DataModel/Lighting.hpp
Header/App/V8/DataModel/FaceInstance.hpp
Header/App/V8/DataModel/RunService.hpp
Header/App/V8/DataModel/Workspace.hpp
@ -48,6 +49,7 @@ add_library(Engine STATIC
Source/App/V8/DataModel/ForceField.cpp
Source/App/V8/DataModel/PartInstance.cpp
Source/App/V8/DataModel/Light.cpp
Source/App/V8/DataModel/Lighting.cpp
Source/App/V8/DataModel/FaceInstance.cpp
Source/App/V8/DataModel/RunService.cpp
Source/App/V8/DataModel/Workspace.cpp
@ -65,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)

View File

@ -20,6 +20,7 @@ namespace RNR
PartInstance* getTorso();
PartInstance* getHead();
void inputFrame(float dx, float dy);
void createHealthBar();
float getHealth() { return m_health; };

View File

@ -15,6 +15,8 @@ namespace RNR
{
World* m_world;
std::vector<int> scancodes_down;
float m_mouseDX;
float m_mouseDY;
protected:
MouseState state;
public:

View File

@ -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);

View File

@ -0,0 +1,36 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
namespace RNR
{
class Lighting : public Instance
{
float m_brightness;
float m_geographicLatitude;
Ogre::Vector3 m_bottomAmbient;
Ogre::Vector3 m_topAmbient;
Ogre::Vector3 m_spotLight;
Ogre::Vector3 m_shadowColor;
Ogre::Vector3 m_clearColor;
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
public:
Lighting();
void setBottomAmbient(Ogre::Vector3 color) { m_bottomAmbient = color; }
Ogre::Vector3 getBottomAmbient() { return m_bottomAmbient; }
void setTopAmbient(Ogre::Vector3 color) { m_topAmbient = color; }
Ogre::Vector3 getTopAmbient() { return m_topAmbient; }
void setSpotLight(Ogre::Vector3 color) { m_spotLight = color; }
Ogre::Vector3 getSpotLight() { return m_spotLight; }
void setShadowColor(Ogre::Vector3 color) { m_shadowColor = color; }
Ogre::Vector3 getShadowColor() { return m_shadowColor; }
void setClearColor(Ogre::Vector3 color) { m_clearColor = color; }
Ogre::Vector3 getClearColor() { return m_clearColor; }
virtual std::string getClassName() { return "Lighting"; }
virtual std::string getExplorerIcon() { return "PointLight"; }
};
}

View File

@ -13,8 +13,10 @@ namespace RNR
enum WorkspaceBatchingMode
{
BATCH_DONT,
BATCH_INSTANCED,
BATCH_STATIC_GEOMETRY,
BATCH_DYNAMIC_RENDERABLE,
};
class Workspace : public ModelInstance

View File

@ -2,6 +2,7 @@
#include <stdexcept>
#include <string>
#include <cstddef>
#include <OGRE/Ogre.h>
#include <boost/shared_ptr.hpp>
@ -36,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
@ -61,6 +62,7 @@ namespace RNR
RNR::Instance* getParent() { return this->m_parent; };
std::string getName() { return this->m_name; };
virtual std::string getClassName() { return "Instance"; }
virtual std::string getExplorerIcon() { return getClassName(); }
void setParent(RNR::Instance* newParent);
void setName(std::string name);

View File

@ -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(); }

View File

@ -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; }

View File

@ -1,6 +1,7 @@
#pragma once
#include <map>
#include <cstddef>
namespace RNR
{

View File

@ -10,6 +10,7 @@ namespace RNR
{
public:
static Ogre::Vector3 getVector3(pugi::xml_node node);
static Ogre::Vector3 getColor(pugi::xml_node node);
static CoordinateFrame getCFrame(pugi::xml_node node);
};
}

View File

@ -10,10 +10,13 @@ namespace RNR
int m_userId;
public:
Player();
void initLocalPlayer();
void loadCharacter();
ModelInstance* getCharacter() { return m_character; }
void setCharacter(ModelInstance* model) { m_character = model; }
virtual std::string getClassName() { return "Player"; }
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void addProperties(std::vector<ReflectionProperty>& properties);
};
}

View File

@ -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");

View File

@ -1,11 +1,15 @@
#include <App/Humanoid/Humanoid.hpp>
#include <App/V8/World/World.hpp>
#include <App/InputManager.hpp>
namespace RNR
{
Humanoid::Humanoid()
{
//
setName("Humanoid");
m_maxHealth = 100.f;
m_health = 100.f;
}
Humanoid::~Humanoid()
@ -42,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)
@ -63,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[] = {

View File

@ -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)

View File

@ -3,7 +3,6 @@
#include <App/CoordinateFrame.hpp>
#include <App/BrickColor.hpp>
#include <Helpers/Strings.hpp>
#include <format>
namespace RNR
{

View File

@ -1,6 +1,7 @@
#include <App/V8/DataModel/Camera.hpp>
#include <App/V8/World/World.hpp>
#include <App/InputManager.hpp>
#include <Network/Players.hpp>
#include <Helpers/XML.hpp>
namespace RNR
@ -40,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));

View File

@ -0,0 +1,67 @@
#include <App/V8/DataModel/Lighting.hpp>
#include <Helpers/XML.hpp>
namespace RNR
{
Lighting::Lighting()
{
setName("Lighting");
setClearColor(Ogre::Vector3(255.f/255.f,255.f/255.f,255.f/255.f));
setShadowColor(Ogre::Vector3(127.f/255.f,127.f/255.f,127.f/255.f));
setBottomAmbient(Ogre::Vector3(122.f/255.f,134.f/255.f,120.f/255.f));
setTopAmbient(Ogre::Vector3(209.f/255.f,208.f/255.f,217.f/255.f));
setSpotLight(Ogre::Vector3(191.f/255.f,191.f/255.f,191.f/255.f));
}
void Lighting::deserializeProperty(char* prop_name, pugi::xml_node node)
{
if(prop_name == std::string("ClearColor"))
{
setClearColor(XML::getColor(node));
}
else if(prop_name == std::string("ShadowColor"))
{
setShadowColor(XML::getColor(node));
}
else if(prop_name == std::string("SpotLightV9"))
{
setSpotLight(XML::getColor(node));
}
else if(prop_name == std::string("BottomAmbientV9"))
{
setBottomAmbient(XML::getColor(node));
}
else if(prop_name == std::string("TopAmbientV9"))
{
setTopAmbient(XML::getColor(node));
}
}
void Lighting::addProperties(std::vector<ReflectionProperty>& properties)
{
ReflectionProperty _properties[] = {
{ this, std::string("BottomAmbientV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_bottomAmbient; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setBottomAmbient(*(Ogre::Vector3*)value); ) },
{ this, std::string("TopAmbientV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_topAmbient; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setTopAmbient(*(Ogre::Vector3*)value); ) },
{ this, std::string("ClearColor"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_clearColor; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setClearColor(*(Ogre::Vector3*)value); ) },
{ this, std::string("ShadowColor"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_shadowColor; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setShadowColor(*(Ogre::Vector3*)value); ) },
{ this, std::string("SpotLightV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_spotLight; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setSpotLight(*(Ogre::Vector3*)value); ) },
};
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
}
}

View File

@ -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();
@ -19,9 +19,11 @@ namespace RNR
break;
case BATCH_STATIC_GEOMETRY:
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
m_geom->setRegionDimensions(Ogre::Vector3(512,512,512));
m_geom->setRegionDimensions(Ogre::Vector3(2048,2048,2048));
m_geom->setCastShadows(true);
break;
case BATCH_DONT:
break;
}
}
@ -36,11 +38,12 @@ namespace RNR
case BATCH_INSTANCED:
{
Ogre::Entity* childEntity = (Ogre::Entity*)childAdded->getObject();
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity(childEntity->getSubEntity(0)->getMaterialName());
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity("materials/partinstanced");
replica->setPosition(part->getPosition());
replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize());
childAdded->setObject(replica);
child_node->setVisible(false);
}
break;
case BATCH_STATIC_GEOMETRY:
@ -48,10 +51,12 @@ namespace RNR
part->getPosition(),
part->getCFrame().getRotation(),
part->getSize());
child_node->setVisible(false);
m_geomDirty = true;
break;
case BATCH_DONT:
break;
}
child_node->setVisible(false);
m_geomDirty = true;
}
}

View File

@ -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()
@ -47,6 +58,8 @@ namespace RNR
pugi::xml_attribute prop_name = prop.attribute("name");
if(prop_name.as_string() == std::string("Name"))
setName(prop.text().as_string());
else if(prop_name.as_string() == std::string("archivable"))
m_archivable = prop.text().as_bool();
else
deserializeProperty((char*)prop_name.as_string(), prop);
}

View File

@ -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();
}
}

View File

@ -1,6 +1,7 @@
#include <App/V8/World/World.hpp>
#include <App/V8/Tree/InstanceFactory.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/DataModel/Lighting.hpp>
#include <App/GUI/SelectionBox.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <App/InputManager.hpp>
@ -14,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();
@ -27,6 +35,7 @@ namespace RNR
m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder<RunService>);
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>);
m_ogreRoot = ogre;
m_ogreSceneManager = ogreSceneManager;
@ -109,13 +118,14 @@ namespace RNR
WorldUndeserialized s = m_undeserialized.top();
m_undeserialized.pop();
s.instance->setParent(s.parent);
pugi::xml_node props = s.node.child("Properties");
for(pugi::xml_node prop : props.children())
{
s.instance->deserializeXmlProperty(prop);
}
s.instance->setParent(s.parent);
if(s.instance->getClassName() == "Model")
{
ModelInstance* m = (ModelInstance*)s.instance;
@ -140,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;
}

View File

@ -11,6 +11,16 @@ namespace RNR
);
}
Ogre::Vector3 XML::getColor(pugi::xml_node node)
{
Ogre::Vector3 rgb;
unsigned int hex = node.text().as_uint();
rgb.x = ((hex >> 16) & 0xff) / 255.0;
rgb.y = ((hex >> 8) & 0xff) / 255.0;
rgb.z = ((hex) & 0xff) / 255.0;
return rgb;
}
CoordinateFrame XML::getCFrame(pugi::xml_node node)
{
CoordinateFrame cframe;

View File

@ -1,4 +1,5 @@
#include <Network/Player.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <App/V8/World/World.hpp>
namespace RNR
@ -22,4 +23,38 @@ namespace RNR
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
}
void Player::initLocalPlayer()
{
}
void Player::loadCharacter()
{
m_character = new ModelInstance();
m_character->setName(getName());
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());
Camera* player_camera = world->getWorkspace()->getCurrentCamera();
player_camera->setCFrame(CoordinateFrame());
}
}

View File

@ -12,11 +12,12 @@ 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();
m_localPlayer->initLocalPlayer();
return m_localPlayer;
}

View File

@ -1,9 +1,9 @@
# RNR
[![GitHub CI Status](https://img.shields.io/github/actions/workflow/status/lrre-foss/rnr/build.yml?branch=trunk&label=builds)](https://github.com/lrre-foss/rnr/actions)
[![Discord](https://img.shields.io/discord/1130992923329175552?style=social&logo=discord)](https://discord.gg/2tj4TREby3)
[![Star](https://img.shields.io/github/stars/lrre-foss/RNR?style=social)](https://github.com/lrre-foss/RNR/stargazers)
[Discord](https://discord.gg/89WagAUr)
RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining partially compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries.
RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining fully compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries.
Interested in contributing? [Feel free to make a pull request!](https://github.com/lrre-foss/RNR/pulls)
@ -13,6 +13,7 @@ There are several goals that RNR seeks to accomplish, them being;
- Easy-to-use (simple CLI options to launch and host games, as well as a level editor with a modern UI)
- Fully compatible with Roblox versions up to 0.3.744.0 (dated April 2008) in areas such as hosting, joining, levels, etc.
- Incorporates all the various facets of the Roblox engine, plus a little bit extra (e.g. a network replication whitelist, fancy shader support, etc.)
- Made using clean-room reverse engineering
- Uses Roblox's [Luau](https://luau-lang.org/) as its scripting language while remaining fully compatible with classic Roblox scripts written using Lua 5.1
- As free and open-source as possible (with client code licensed under the GPL and the engine itself being released into the public domain, void of any copyright)
- Patching all the security vulnerabilities and fixing bugs/inefficiencies that legacy Roblox clients had