readd instancing alongside static geometry

This commit is contained in:
floralrainfall 2023-07-19 07:23:26 -04:00
parent cd72268950
commit ad9376f7e0
20 changed files with 275 additions and 69 deletions

View File

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

View File

@ -59,9 +59,10 @@ namespace RNR
ogreCamera = ogreSceneManager->createCamera("myCam");
ogreCamera->setNearClipDistance(0.1); // specific to this sample
ogreCamera->setFarClipDistance(5000.f);
ogreCamera->setFarClipDistance(1000.f);
ogreCamera->setAutoAspectRatio(true);
ogreCamera->setFOVy(Ogre::Degree(70.f));
ogreCamera->setUseRenderingDistance(true);
camNode->attachObject(ogreCamera);
ogreViewport = ogreWindow->addViewport(ogreCamera);

View File

@ -1,7 +1,10 @@
#include <MainWindow.hpp>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <App/V8/Tree/ModelInstance.hpp>
#include <App/V8/DataModel/Light.hpp>
MainWindow::MainWindow()
{
@ -130,7 +133,22 @@ void MainWindow::pause()
void MainWindow::dbg_pointlight()
{
if(!ogreWidget->selectedInstance)
{
QMessageBox::about(this, "selectedInstance = NULL", "Please select an instance in the explorer");
return;
}
printf("MainWindow::dbg_pointlight: inserting Light\n");
RNR::Light* dbg_light = new RNR::Light();
dbg_light->setParent(ogreWidget->selectedInstance);
double r = QInputDialog::getDouble(this, "Red", "Set red component [0.0-1.0]", 1.0, 0.0, 1.0, 2);
double g = QInputDialog::getDouble(this, "Blue", "Set blue component [0.0-1.0]", 1.0, 0.0, 1.0, 2);
double b = QInputDialog::getDouble(this, "Green", "Set green component [0.0-1.0]", 1.0, 0.0, 1.0, 2);
dbg_light->setColor(Ogre::Vector3(r,g,b));
updateTree(ogreWidget->world->getDatamodel());
}
void MainWindow::closeEvent(QCloseEvent* event)

View File

@ -3,6 +3,8 @@
#include <QHeaderView>
#include <QFile>
#include <App/BrickColor.hpp>
PropertyViewer::PropertyViewer() : QWidget()
{
prop_table = new QTableWidget();
@ -88,6 +90,17 @@ void PropertyViewer::view(RNR::Instance* instance)
new_property_itemval->setData(Qt::DecorationRole, QPixmap::fromImage(image));
}
break;
case RNR::PROPERTY_BRICKCOLOR:
{
int brickcolor = *(int*)property.rawGetter();
Ogre::Vector3 color = RNR::BrickColor::color(brickcolor);
new_property_itemval->setBackground(QBrush(QColor(
(int)floorf(color.x * 255),
(int)floorf(color.y * 255),
(int)floorf(color.z * 255)
)));
}
break;
}
prop_table->setItem(property_count, 0, new_property_item);

View File

@ -18,6 +18,7 @@ namespace RNR
BrickColor(int color_id, std::string name, Ogre::Vector3 color);
static Ogre::Vector3 color(int brickcolor);
static bool valid(int brickcolor);
static std::string name(int brickcolor);
static Ogre::MaterialPtr material(int brickcolor);
};
}

View File

@ -1,12 +1,23 @@
#pragma once
#include <OGRE/Ogre.h>
#include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreOverlayContainer.h>
#include <OGRE/Overlay/OgreTextAreaOverlayElement.h>
#include <OGRE/Overlay/OgreFontManager.h>
#include <OGRE/Overlay/OgreOverlay.h>
namespace RNR
{
class World;
class TopMenuBar
{
Ogre::TextAreaOverlayElement* m_debugText;
World* m_world;
public:
TopMenuBar();
TopMenuBar(World* world);
void frame();
};
}

View File

@ -41,6 +41,7 @@ namespace RNR
PROPERTY_CFRAME,
PROPERTY_INSTANCE,
PROPERTY_FLOAT,
PROPERTY_BRICKCOLOR,
};
class ReflectionProperty

View File

@ -12,5 +12,16 @@ namespace RNR
bool m_shadows;
public:
Light();
virtual void setupLight(Ogre::Light* light);
virtual void onSetParent(RNR::Instance* newParent);
virtual std::string getClassName() { return std::string("Light"); }
void setColor(Ogre::Vector3 color) { m_color = color; setupLight((Ogre::Light*)getObject()); }
Ogre::Vector3 getColor() { return m_color; }
void setEnabled(bool enabled) { m_enabled = enabled; setupLight((Ogre::Light*)getObject()); }
bool getEnabled() { return m_enabled; }
void setShadows(bool shadows) { m_shadows = shadows; setupLight((Ogre::Light*)getObject()); }
bool getShadows() { return m_shadows; }
};
}

View File

@ -28,6 +28,8 @@ namespace RNR
Ogre::Vector3 getSize() { return m_size; }
Ogre::Vector4 getColor() { return m_color; }
Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); }
void setBrickColor(int brickcolor) { m_brickColor = brickcolor; }
int getBrickColor() { return m_brickColor; }
};

View File

@ -11,26 +11,38 @@ namespace RNR
{
class Camera;
enum WorkspaceBatchingMode
{
BATCH_INSTANCED,
BATCH_STATIC_GEOMETRY,
};
class Workspace : public ModelInstance
{
friend class TopMenuBar;
public:
Workspace();
virtual std::string getClassName() { return "Workspace"; }
virtual void onChildAdded(RNR::Instance* childAdded);
virtual void onChildRemoved(RNR::Instance* childRemoved);
virtual void onDescendantAdded(RNR::Instance* childAdded);
virtual void onDescendantRemoved(RNR::Instance* childRemoved);
void buildGeom();
Camera* getCurrentCamera() const;
void setCurrentCamera(Camera *value);
void setDirty() { m_geomDirty = true; }
private:
enum WorkspaceBatchingMode m_batchMode;
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
void buildGeomInstance(Instance* instance);
bool m_geomDirty;
Ogre::StaticGeometry* m_geom;
Ogre::InstanceManager* m_instanceManager;
Ogre::SceneNode* m_worldspawn;
Ogre::Entity* m_partEntity;

View File

@ -30,6 +30,9 @@ namespace RNR
RNR::Instance* m_parent;
std::vector<RNR::Instance*> m_children;
bool m_archivable;
void descendantAddedChildren(Instance* p, Instance* c);
void descendantRemovedChildren(Instance* p, Instance* c);
public:
Instance();
@ -69,6 +72,9 @@ namespace RNR
int numChildren() { return this->m_children.size(); };
virtual void onChildAdded(RNR::Instance* childAdded);
virtual void onDescendantAdded(RNR::Instance* descendantAdded); // make sure this is called in any derived versions of this
virtual void onChildRemoved(RNR::Instance* childRemoved);
virtual void onDescendantRemoved(RNR::Instance* descendantRemoved); // make sure this is called in any derived versions of this
virtual void onSetParent(RNR::Instance* newParent);
};
}

View File

@ -18,6 +18,7 @@ namespace RNR
struct WorldUndeserialized
{
Instance* instance;
Instance* parent;
pugi::xml_node node;
};

View File

@ -151,4 +151,16 @@ namespace RNR
}
return false;
}
std::string BrickColor::name(int brickcolor)
{
for(int i = 0; i < sizeof(brickcolors) / sizeof(BrickColor); i++)
{
if(brickcolors[i].color_id == brickcolor)
{
return brickcolors[i].color_name;
}
}
return brickcolors[0].color_name;
}
}

View File

@ -1,14 +1,12 @@
#include <App/GUI/TopMenuBar.hpp>
#include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreOverlayContainer.h>
#include <OGRE/Overlay/OgreTextAreaOverlayElement.h>
#include <OGRE/Overlay/OgreFontManager.h>
#include <OGRE/Overlay/OgreOverlay.h>
#include <App/V8/World/World.hpp>
namespace RNR
{
TopMenuBar::TopMenuBar()
TopMenuBar::TopMenuBar(World* world)
{
m_world = world;
Ogre::OverlayManager* overlayManager = Ogre::OverlayManager::getSingletonPtr();
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Background", "General");
material->getTechnique(0)->getPass(0)->createTextureUnitState("placeholder.png");
@ -33,12 +31,43 @@ namespace RNR
textArea->setFontName("ComicSans");
textArea->setColour(Ogre::ColourValue(0.f,0.f,0.f));
m_debugText = static_cast<Ogre::TextAreaOverlayElement*>(overlayManager->createOverlayElement("TextArea", "DebugTextArea"));
m_debugText->setMetricsMode(Ogre::GMM_PIXELS);
m_debugText->setPosition(0, 300);
m_debugText->setDimensions(420, 500);
m_debugText->setCaption("Debug text!");
m_debugText->setCharHeight(24);
m_debugText->setFontName("ComicSans");
m_debugText->setColour(Ogre::ColourValue(0.5f,0.f,0.5f));
Ogre::Overlay* overlay = overlayManager->create("OverlayName");
overlay->add2D(panel);
overlay->setZOrder(500);
panel->addChild(textArea);
panel->addChild(m_debugText);
overlay->show();
}
void TopMenuBar::frame()
{
Workspace* workspace = m_world->getWorkspace();
char debugtext[512];
char render_debugtext[255];
switch(workspace->m_batchMode)
{
case BATCH_INSTANCED:
snprintf(render_debugtext, 255, "using BATCH_INSTANCED");
break;
case BATCH_STATIC_GEOMETRY:
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());
m_debugText->setCaption(debugtext);
}
}

View File

@ -1,6 +1,7 @@
#include <App/Script/ReflectionProperty.hpp>
#include <App/V8/Tree/Instance.hpp>
#include <App/CoordinateFrame.hpp>
#include <App/BrickColor.hpp>
#include <Helpers/Strings.hpp>
#include <format>
@ -64,6 +65,8 @@ namespace RNR
cframe_rotation.z,
cframe_rotation.w);
}
case PROPERTY_BRICKCOLOR:
return std::string(BrickColor::name(*(int*)m_getter(m_object)));
default:
return std::string("???");
}

View File

@ -1,4 +1,6 @@
#include <App/V8/DataModel/Light.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/World/World.hpp>
namespace RNR
{
@ -7,6 +9,43 @@ namespace RNR
m_brightness = 1.f;
m_enabled = true;
m_shadows = true;
m_color = Ogre::Vector3(1.f,1.f,1.f);
m_color = Ogre::Vector3(75.f/255.f,151.f/255.f,75.f/255.f);
setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode());
setObject(world->getOgreSceneManager()->createLight(Ogre::Light::LT_POINT));
getNode()->attachObject(getObject());
Ogre::Light* light_object = (Ogre::Light*)getObject();
}
void Light::onSetParent(Instance* newParent)
{
Ogre::Light* light_object = (Ogre::Light*)getObject();
if(!newParent)
{
light_object->setVisible(false);
return;
}
PartInstance* part = dynamic_cast<PartInstance*>(newParent);
if(!part)
{
light_object->setVisible(false);
return;
}
getNode()->setPosition(part->getPosition());
setupLight(light_object);
}
void Light::setupLight(Ogre::Light* light)
{
light->setVisible(m_enabled);
light->setCastShadows(m_shadows);
light->setDiffuseColour(Ogre::ColourValue(m_color.x, m_color.y, m_color.z));
//light->setAttenuation(100, 1.0, 0.045, 0.0075);
light->setRenderingDistance(500.f);
light->setShadowFarDistance(100);
}
}

View File

@ -10,6 +10,10 @@ namespace RNR
m_color = Ogre::Vector4(0.63, 0.64, 0.63, 1.0);
setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode());
setObject(world->getOgreSceneManager()->createEntity("fonts/Cube.mesh"));
getNode()->attachObject(getObject());
updateMatrix();
}
@ -17,6 +21,16 @@ namespace RNR
{
m_matrix = m_cframe.getMatrix();
m_position = m_cframe.getPosition();
getNode()->setOrientation(Ogre::Quaternion(m_cframe.getRotation()));
getNode()->setPosition(m_position);
getNode()->setScale(m_size);
Ogre::Entity* entity = (Ogre::Entity*)getObject();
for(auto& subentity : entity->getSubEntities())
{
subentity->getMaterial()->setManualCullingMode(Ogre::ManualCullingMode::MANUAL_CULL_BACK);
}
}
void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node)
@ -35,6 +49,7 @@ namespace RNR
}
else
PVInstance::deserializeProperty(prop_name, node);
updateMatrix();
}
void PartInstance::addProperties(std::vector<ReflectionProperty>& properties)
@ -44,6 +59,10 @@ namespace RNR
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_size; ),
REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setSize(*(Ogre::Vector3*)value); ) },
{ this, std::string("BrickColor"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_BRICKCOLOR,
REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_brickColor; ),
REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setBrickColor(*(int*)value); ) },
};
PVInstance::addProperties(properties);

View File

@ -8,81 +8,67 @@ namespace RNR
Workspace::Workspace() : ModelInstance()
{
setName("Workspace");
m_batchMode = BATCH_STATIC_GEOMETRY;
m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode();
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
m_geom->setCastShadows(true);
m_partEntity = world->getOgreSceneManager()->createEntity("fonts/Cube.mesh");
m_partEntity->setCastShadows(true);
for(int i = 0; i < m_partEntity->getNumSubEntities(); i++)
switch(m_batchMode)
{
Ogre::SubEntity* surface = m_partEntity->getSubEntity(i);
Ogre::TextureUnitState* texture = surface->getMaterial()->getTechnique(0)->getPass(0)->createTextureUnitState("textures/stud_top.png");
surface->getMaterial()->setShininess(1.0);
case BATCH_INSTANCED:
m_instanceManager = world->getOgreSceneManager()->createInstanceManager("workspaceInstanceManager", "fonts/Cube.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::InstancingTechnique::HWInstancingBasic, 255);
break;
case BATCH_STATIC_GEOMETRY:
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
m_geom->setRegionDimensions(Ogre::Vector3(255,255,255));
m_geom->setCastShadows(true);
break;
}
}
void Workspace::onChildAdded(Instance* childAdded)
void Workspace::onDescendantAdded(Instance* childAdded)
{
m_geomDirty = true;
PartInstance* part = dynamic_cast<PartInstance*>(childAdded);
if(part)
{
Ogre::SceneNode* child_node = childAdded->getNode();
switch(m_batchMode)
{
case BATCH_INSTANCED:
{
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity("materials/partinstanced");
replica->setPosition(part->getPosition());
replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize());
}
break;
case BATCH_STATIC_GEOMETRY:
m_geom->addEntity((Ogre::Entity*)childAdded->getObject(),
part->getPosition(),
part->getCFrame().getRotation(),
part->getSize());
break;
}
child_node->setVisible(false);
m_geomDirty = true;
}
}
void Workspace::buildGeomInstance(Instance* instance)
{
PartInstance* child_part = dynamic_cast<PartInstance*>(instance);
if(child_part)
{
Ogre::Vector3 part_size = child_part->getSize();
for(int i = 0; i < m_partEntity->getNumSubEntities(); i++)
{
m_partEntity->setMaterial(BrickColor::material(child_part->getBrickColor()));
/*
Ogre::SubMesh* surface = m_partEntity->getMesh()->getSubMesh(i);
surface->setMaterial();
Ogre::TextureUnitState* texture = surface->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0);
Ogre::Vector2 uvs;
std::string surf_name = std::string(surface->getMaterialName().c_str());
if(surf_name == "TopMaterial")
uvs = Ogre::Vector2(part_size.x, part_size.z);
else if(surf_name == "BottomMaterial")
uvs = Ogre::Vector2(-part_size.x, part_size.z);
else if(surf_name == "LeftMaterial")
uvs = Ogre::Vector2(part_size.y, part_size.z);
else if(surf_name == "RightMaterial")
uvs = Ogre::Vector2(-part_size.y, part_size.z);
else if(surf_name == "BackMaterial")
uvs = Ogre::Vector2(part_size.x, part_size.z);
else if(surf_name == "FrontMaterial")
uvs = Ogre::Vector2(-part_size.x, part_size.z);*/
}
m_geom->addEntity(m_partEntity,
child_part->getCFrame().getPosition(),
Ogre::Quaternion(child_part->getCFrame().getRotation()),
child_part->getSize());
}
for(auto& child : *instance->getChildren())
buildGeomInstance(child);
}
void Workspace::buildGeom()
{
if(!m_geomDirty)
if(!m_geomDirty || m_batchMode != BATCH_STATIC_GEOMETRY)
return;
m_geom->reset();
for(auto& child : *getChildren())
buildGeomInstance(child);
m_geom->build();
m_geomDirty = false;
}
void Workspace::onChildRemoved(Instance* childRemoved)
void Workspace::onDescendantRemoved(Instance* childRemoved)
{
m_geomDirty = true;
m_geomDirty = true;
}
Camera* Workspace::getCurrentCamera() const

View File

@ -132,6 +132,9 @@ namespace RNR
{
children->erase(child_it);
m_parent->onChildRemoved(this);
m_parent->onDescendantRemoved(this);
for(auto& child : m_children)
descendantRemovedChildren(m_parent, child);
if (m_parent->numChildren() == 0)
{
@ -140,24 +143,59 @@ namespace RNR
}
}
onSetParent(newParent);
m_parent = newParent;
if(m_parent)
{
m_parent->m_children.push_back(this);
newParent->onChildAdded(this);
newParent->onDescendantAdded(this);
for(auto& child : m_children)
descendantAddedChildren(m_parent, child);
}
}
}
void Instance::descendantAddedChildren(Instance* p, Instance* c)
{
for(auto& child : *c->getChildren())
descendantAddedChildren(p, child);
p->onDescendantAdded(c);
}
void Instance::descendantRemovedChildren(Instance* p, Instance* c)
{
for(auto& child : *c->getChildren())
descendantRemovedChildren(p, child);
p->onDescendantRemoved(c);
}
void Instance::onChildAdded(Instance* childAdded)
{
//
}
void Instance::onDescendantAdded(Instance* descendantAdded)
{
if(m_parent)
m_parent->onDescendantAdded(descendantAdded);
}
void Instance::onChildRemoved(RNR::Instance* childRemoved)
{
}
void Instance::onDescendantRemoved(Instance* descendantRemoved)
{
if(m_parent)
m_parent->onDescendantRemoved(descendantRemoved);
}
void Instance::onSetParent(Instance* newParent)
{
}
bool Instance::isA(std::string type)

View File

@ -32,7 +32,7 @@ namespace RNR
m_workspace = (Workspace*)m_datamodel->getService("Workspace");
m_runService = (RunService*)m_datamodel->getService("RunService");
m_tmb = new TopMenuBar();
m_tmb = new TopMenuBar(this);
Camera* start_cam = new Camera();
start_cam->setParent(m_workspace);
@ -70,9 +70,9 @@ namespace RNR
m_refs[referent.as_string()] = instance;
WorldUndeserialized s;
s.instance = instance;
s.parent = parent;
s.node = node;
m_undeserialized.push(s);
instance->setParent(parent);
for(pugi::xml_node item = node.child("Item"); item; item = item.next_sibling("Item"))
xmlAddItem(item, instance);
@ -111,6 +111,7 @@ namespace RNR
s.instance->deserializeXmlProperty(prop);
}
s.instance->setParent(s.parent);
if(s.instance->getClassName() == "Model")
{
ModelInstance* m = (ModelInstance*)s.instance;
@ -129,6 +130,7 @@ namespace RNR
{
if(m_inputManager)
m_inputManager->frame();
m_tmb->frame();
}
double World::step(float timestep)