From 8ae6d52ae5caeda040c521647dbe402fc9a8cd62 Mon Sep 17 00:00:00 2001 From: owner Date: Sun, 15 Mar 2026 21:14:51 -0400 Subject: [PATCH] Upload files to "src" --- src/OrbitManipulator.cpp | 35 ++++++++++++ src/SceneBuilder.cpp | 119 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/OrbitManipulator.cpp create mode 100644 src/SceneBuilder.cpp diff --git a/src/OrbitManipulator.cpp b/src/OrbitManipulator.cpp new file mode 100644 index 0000000..91f31aa --- /dev/null +++ b/src/OrbitManipulator.cpp @@ -0,0 +1,35 @@ +#include "OrbitManipulator.h" +#include + +OrbitManipulator::OrbitManipulator() { + setAllowThrow(false); + setMinimumDistance(0.05); +} + +void OrbitManipulator::setDefaultHumanoidView() { + // PMX models are Y-up and face -Z (into the screen in their local space). + // Place the camera along -Z looking toward +Z, so we see the model's face. + // + // eye = (0, 1.5, -3) -- 3 units in front of the model (-Z side) + // centre = (0, 1.0, 0) -- orbit target at chest height + // up = (0, 1.0, 0) -- Y-up, no roll + setHomePosition( + osg::Vec3d(0.0, 1.5, -3.0), + osg::Vec3d(0.0, 1.0, 0.0), + osg::Vec3d(0.0, 1.0, 0.0) + ); + home(0.0); +} + +bool OrbitManipulator::handleKeyDown(const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter& aa) { + switch (ea.getKey()) { + case 'r': + case 'R': + setDefaultHumanoidView(); + return true; + default: + break; + } + return osgGA::OrbitManipulator::handleKeyDown(ea, aa); +} \ No newline at end of file diff --git a/src/SceneBuilder.cpp b/src/SceneBuilder.cpp new file mode 100644 index 0000000..44d74e7 --- /dev/null +++ b/src/SceneBuilder.cpp @@ -0,0 +1,119 @@ +#include "SceneBuilder.h" + +#include +#include +#include +#include +#include + +// ───────────────────────────────────────────────────────────────────────────── + +osg::ref_ptr SceneBuilder::createGrid(float halfSize, int divisions) { + auto geode = new osg::Geode; + auto geom = new osg::Geometry; + + auto verts = new osg::Vec3Array; + auto cols = new osg::Vec4Array; + + const float step = (halfSize * 2.f) / static_cast(divisions); + + // Grid lines parallel to X axis + for (int i = 0; i <= divisions; ++i) { + float z = -halfSize + i * step; + verts->push_back({ -halfSize, 0.f, z }); + verts->push_back({ halfSize, 0.f, z }); + } + // Grid lines parallel to Z axis + for (int i = 0; i <= divisions; ++i) { + float x = -halfSize + i * step; + verts->push_back({ x, 0.f, -halfSize }); + verts->push_back({ x, 0.f, halfSize }); + } + + // Uniform grey colour + cols->push_back({ 0.45f, 0.45f, 0.45f, 1.f }); + + geom->setVertexArray(verts); + geom->setColorArray(cols, osg::Array::BIND_OVERALL); + geom->addPrimitiveSet( + new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, + static_cast(verts->size()))); + + // Thin lines, no lighting + osg::StateSet* ss = geom->getOrCreateStateSet(); + ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + ss->setAttribute(new osg::LineWidth(1.f)); + + geode->addDrawable(geom); + geode->setName("Grid"); + return geode; +} + +// ───────────────────────────────────────────────────────────────────────────── + +osg::ref_ptr SceneBuilder::createAxes(float length) { + auto geode = new osg::Geode; + auto geom = new osg::Geometry; + + auto verts = new osg::Vec3Array; + auto cols = new osg::Vec4Array; + + // X – red + verts->push_back({ 0.f, 0.f, 0.f }); cols->push_back({1,0,0,1}); + verts->push_back({ length, 0.f, 0.f }); cols->push_back({1,0,0,1}); + // Y – green + verts->push_back({ 0.f, 0.f, 0.f }); cols->push_back({0,1,0,1}); + verts->push_back({ 0.f, length, 0.f }); cols->push_back({0,1,0,1}); + // Z – blue + verts->push_back({ 0.f, 0.f, 0.f }); cols->push_back({0,0,1,1}); + verts->push_back({ 0.f, 0.f, length }); cols->push_back({0,0,1,1}); + + geom->setVertexArray(verts); + geom->setColorArray(cols, osg::Array::BIND_PER_VERTEX); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 6)); + + osg::StateSet* ss = geom->getOrCreateStateSet(); + ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + ss->setAttribute(new osg::LineWidth(2.f)); + + geode->addDrawable(geom); + geode->setName("Axes"); + return geode; +} + +// ───────────────────────────────────────────────────────────────────────────── + +osg::ref_ptr SceneBuilder::createSunLight(int lightNum) { + auto light = new osg::Light; + light->setLightNum(lightNum); + + // Warm directional light from upper-right front + light->setPosition({ 5.f, 10.f, 5.f, 0.f }); // w=0 → directional + light->setDiffuse({ 1.0f, 0.95f, 0.85f, 1.f }); + light->setSpecular({ 1.0f, 1.0f, 0.9f, 1.f }); + light->setAmbient({ 0.0f, 0.0f, 0.0f, 1.f }); + + auto src = new osg::LightSource; + src->setLight(light); + src->setLocalStateSetModes(osg::StateAttribute::ON); + src->setName("SunLight"); + return src; +} + +// ───────────────────────────────────────────────────────────────────────────── + +osg::ref_ptr SceneBuilder::createAmbientLight(int lightNum) { + auto light = new osg::Light; + light->setLightNum(lightNum); + + light->setPosition({ 0.f, 0.f, 0.f, 1.f }); // positional (ignored for ambient) + light->setDiffuse({ 0.0f, 0.0f, 0.0f, 1.f }); + light->setSpecular({ 0.0f, 0.0f, 0.0f, 1.f }); + light->setAmbient({ 0.25f, 0.25f, 0.3f, 1.f }); // cool blue ambient fill + + auto src = new osg::LightSource; + src->setLight(light); + src->setLocalStateSetModes(osg::StateAttribute::ON); + src->setName("AmbientLight"); + return src; +}