diff --git a/examples/geometries/box_geometry.cpp b/examples/geometries/box_geometry.cpp index 1e801579..af8b7c1d 100644 --- a/examples/geometries/box_geometry.cpp +++ b/examples/geometries/box_geometry.cpp @@ -16,8 +16,8 @@ namespace { auto geometry = BoxGeometry::create(params); auto material = MeshBasicMaterial::create(); - Mesh mesh(geometry, material); - mesh.add(createWireframe(*geometry)); + auto mesh = Mesh::create(geometry, material); + mesh->add(createWireframe(*geometry)); return mesh; } @@ -79,8 +79,8 @@ int main() { canvas.animate([&]() { float dt = clock.getDelta(); - mesh.rotation.y += 0.8f * dt; - mesh.rotation.x += 0.5f * dt; + mesh->rotation.y += 0.8f * dt; + mesh->rotation.x += 0.5f * dt; renderer.render(scene, camera); @@ -88,7 +88,7 @@ int main() { if (paramsChanged) { paramsChanged = false; - updateGroupGeometry(mesh, params); + updateGroupGeometry(*mesh, params); } }); } diff --git a/examples/geometries/heightmap.cpp b/examples/geometries/heightmap.cpp index 65e58b48..dcdae979 100644 --- a/examples/geometries/heightmap.cpp +++ b/examples/geometries/heightmap.cpp @@ -104,47 +104,36 @@ int main() { hudText.material()->as()->color.setHex(Color::black); hud.add(hudText); - std::promise> promise; - auto future = promise.get_future(); + auto material = MeshPhongMaterial::create(); + auto mesh = Mesh::create(BufferGeometry::create(), material); + scene->add(mesh); - auto f1 = std::async([&] { - TextureLoader tl; - auto texture = tl.load("data/textures/terrain/aalesund_terrain.png"); - auto material = MeshPhongMaterial::create({{"map", texture}}); - promise.set_value(material); - - canvas.invokeLater([&] { - hudText.setText("Material loaded..", opts); - }); - }); - - auto f2 = std::async([&] { - auto data = loadHeights(); + auto future = std::async(std::launch::async, [&] { + const auto data = loadHeights(); auto geometry = PlaneGeometry::create(5041, 5041, 1023, 1023); geometry->applyMatrix4(Matrix4().makeRotationX(-math::PI / 2)); - auto pos = geometry->getAttribute("position"); for (unsigned i = 0, j = 0, l = data.size(); i < l; ++i, j += 3) { pos->setY(i, data[i]); } - canvas.invokeLater([&] { - hudText.setText("Geometry loaded..", opts); - }); + TextureLoader tl; + auto texture = tl.load("data/textures/terrain/aalesund_terrain.png"); - auto material = future.get(); - auto mesh = Mesh::create(geometry, material); + canvas.invokeLater([&, texture, geometry] { - canvas.invokeLater([&, mesh] { - hudText.setText("Terrain loaded..", opts); + material->map = texture; + material->needsUpdate(); + mesh->setGeometry(geometry); - scene->add(mesh); + hudText.setText("Terrain loaded..", opts); }); canvas.invokeLater([&] { hud.remove(hudText); - }, 2); + }, + 2); }); canvas.onWindowResize([&](WindowSize size) { @@ -165,6 +154,4 @@ int main() { hud.apply(renderer); }); - f1.get(); - f2.get(); } diff --git a/examples/libs/CMakeLists.txt b/examples/libs/CMakeLists.txt index ee3db6b6..8b473686 100644 --- a/examples/libs/CMakeLists.txt +++ b/examples/libs/CMakeLists.txt @@ -27,4 +27,4 @@ add_library(pathfinding INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/pathfinding/heuristics/ClosestSquaredHeuristic.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/pathfinding/heuristics/ManhattanHeuristic.hpp" ) -target_include_directories(pathfinding INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") \ No newline at end of file +target_include_directories(pathfinding INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/examples/lights/point_light.cpp b/examples/lights/point_light.cpp index 62001ab7..f499a219 100644 --- a/examples/lights/point_light.cpp +++ b/examples/lights/point_light.cpp @@ -35,6 +35,42 @@ namespace { return plane; } + auto addLights(Scene& scene) { + auto light1 = PointLight::create(Color::yellow); + light1->castShadow = true; + light1->shadow->bias = -0.005f; + light1->distance = 8; + light1->position.y = 4; + + auto light2 = PointLight::create(Color::white); + light2->castShadow = true; + light2->shadow->bias = -0.005f; + light2->distance = 8; + light2->position.y = 4; + + auto light3 = PointLight::create(Color::purple); + light3->castShadow = true; + light3->shadow->bias = -0.005f; + light3->distance = 10; + light3->position.y = 7; + + auto lightHelper1 = PointLightHelper::create(*light1, 0.25f); + auto lightHelper2 = PointLightHelper::create(*light2, 0.25f); + auto lightHelper3 = PointLightHelper::create(*light3, 0.25f); + + light1->name = "light1"; + light2->name = "light2"; + light3->name = "light3"; + + scene.add(light1); + scene.add(light2); + scene.add(light3); + + scene.add(lightHelper1); + scene.add(lightHelper2); + scene.add(lightHelper3); + } + }// namespace int main() { @@ -49,25 +85,7 @@ int main() { OrbitControls controls{*camera, canvas}; - auto light1 = PointLight::create(Color::yellow); - light1->castShadow = true; - light1->shadow->bias = -0.005f; - light1->distance = 8; - light1->position.y = 4; - scene->add(light1); - - auto lightHelper1 = PointLightHelper::create(*light1, 0.25f); - scene->add(lightHelper1); - - auto light2 = PointLight::create(Color::white); - light2->castShadow = true; - light2->shadow->bias = -0.005f; - light2->distance = 8; - light2->position.y = 4; - scene->add(light2); - - auto lightHelper2 = PointLightHelper::create(*light2, 0.25f); - scene->add(lightHelper2); + addLights(*scene); auto knot = createTorusKnot(); scene->add(knot); @@ -82,10 +100,13 @@ int main() { renderer.setSize(size); }); + auto light1 = scene->getObjectByName("light1"); + auto light2 = scene->getObjectByName("light2"); + Clock clock; canvas.animate([&]() { - float dt = clock.getDelta(); - float t = clock.elapsedTime; + const float dt = clock.getDelta(); + const float t = clock.elapsedTime; knot->rotation.y += 0.5f * dt; diff --git a/examples/lights/spot_light.cpp b/examples/lights/spot_light.cpp index ddef6f31..f7b63c8b 100644 --- a/examples/lights/spot_light.cpp +++ b/examples/lights/spot_light.cpp @@ -62,7 +62,7 @@ int main() { scene->add(helper); auto target = Object3D::create(); - light->target = target; + light->setTarget(*target); scene->add(target); auto knot = createTorusKnot(); diff --git a/examples/misc/morphtargets_sphere.cpp b/examples/misc/morphtargets_sphere.cpp index 13fa15c5..242d984c 100644 --- a/examples/misc/morphtargets_sphere.cpp +++ b/examples/misc/morphtargets_sphere.cpp @@ -43,7 +43,7 @@ int main() { mesh->material()->as()->morphTargets = true; - auto points = Points::create(mesh->shared_geometry(), pointsMaterial); + auto points = Points::create(mesh->geometry()->shared_from_this(), pointsMaterial); points->copyMorphTargetInfluences(&mesh->morphTargetInfluences()); mesh->add(points); }); diff --git a/examples/objects/bones.cpp b/examples/objects/bones.cpp index 760abe65..499055dc 100644 --- a/examples/objects/bones.cpp +++ b/examples/objects/bones.cpp @@ -60,7 +60,6 @@ namespace { auto prevBone = Bone::create(); bones.emplace_back(prevBone); - prevBone->position.y = -sizing.halfHeight; for (unsigned i = 0; i < sizing.segmentCount; i++) { @@ -82,6 +81,7 @@ namespace { {"flatShading", true}}); auto mesh = SkinnedMesh::create(geometry, material); + mesh->castShadow = true; auto skeleton = Skeleton::create(bones); mesh->add(bones[0]); @@ -104,6 +104,7 @@ namespace { Sizing sizing{segmentHeight, segmentCount, height, halfHeight}; auto geometry = createGeometry(sizing); + geometry->applyMatrix4(Matrix4().makeTranslation(0,halfHeight,0)); auto bones = createBones(sizing); auto mesh = createMesh(geometry, bones); @@ -112,33 +113,56 @@ namespace { return mesh; } + auto initPlane() { + int gridSize = 100; + auto grid = GridHelper::create(gridSize, 10, Color::yellow); + + auto geometry = PlaneGeometry::create(gridSize, gridSize); + auto material = ShadowMaterial::create(); + material->color = 0x000000; + material->opacity = 0.2f; + + auto plane = Mesh::create(geometry, material); + plane->rotation.x = -math::PI / 2; + plane->receiveShadow = true; + grid->add(plane); + + return grid; + } + }// namespace int main() { Canvas canvas("Bones"); GLRenderer renderer(canvas.size()); - renderer.checkShaderErrors = true; + renderer.shadowMap().enabled = true; Scene scene; scene.background = Color(0x444444); PerspectiveCamera camera(75, canvas.size().aspect(), 0.1, 200); - camera.position.set(0, 30, 30); + camera.position.set(0, 50, 50); auto light1 = PointLight::create(0xffffff); light1->position.set(0, 200, 0); + light1->castShadow = true; auto light2 = PointLight::create(0xffffff); light2->position.set(100, 200, 100); + light2->castShadow = true; auto light3 = PointLight::create(0xffffff); light3->position.set(-100, -200, -100); + light3->castShadow = true; scene.add(light1); scene.add(light2); scene.add(light3); - auto mesh = initBones(); - scene.add(mesh); + auto plane = initPlane(); + scene.add(plane); + + auto bones = initBones(); + scene.add(bones); OrbitControls controls{camera, canvas}; controls.enableZoom = false; @@ -172,9 +196,9 @@ int main() { ui.render(); if (animate) { - for (unsigned i = 0; i < mesh->skeleton->bones.size(); i++) { + for (unsigned i = 0; i < bones->skeleton->bones.size(); i++) { - mesh->skeleton->bones[i]->rotation.z = std::sin(time) * 2 / float(mesh->skeleton->bones.size()); + bones->skeleton->bones[i]->rotation.z = std::sin(time) * 2 / float(bones->skeleton->bones.size()); } } }); diff --git a/examples/objects/decal.cpp b/examples/objects/decal.cpp index 13768dcd..0e5ac524 100644 --- a/examples/objects/decal.cpp +++ b/examples/objects/decal.cpp @@ -192,7 +192,7 @@ int main() { Vector3 scale = Vector3::ONES() * math::randFloat(0.6f, 1.2f); - auto mat = decalMat->clone()->as(); + auto mat = decalMat->clone()->as_shared(); mat->color.randomize(); orientation.z = math::PI * math::randFloat(); auto m = Mesh::create(DecalGeometry::create(*mesh, position, orientation, scale), mat); diff --git a/examples/objects/sprite.cpp b/examples/objects/sprite.cpp index 3146983d..27ccceb8 100644 --- a/examples/objects/sprite.cpp +++ b/examples/objects/sprite.cpp @@ -78,7 +78,7 @@ int main() { material->map = loader.load("data/textures/three.png"); material->map->offset.set(0.5, 0.5); - auto pickMaterial = material->clone()->as(); + auto pickMaterial = material->clone()->as_shared(); auto sprites = createSprites(material); scene->add(sprites); @@ -110,7 +110,7 @@ int main() { Sprite* lastPicked = nullptr; canvas.animate([&]() { if (lastPicked) { - lastPicked->material = material; + lastPicked->setMaterial(material); lastPicked->scale.set(1, 1, 1); } @@ -120,12 +120,12 @@ int main() { raycaster.setFromCamera(mouse, *camera); auto intersects = raycaster.intersectObjects(sprites->children, true); if (!intersects.empty()) { - auto& intersection = intersects.front(); + const auto& intersection = intersects.front(); helper->position.copy(intersection.point); helper->visible = true; lastPicked = intersection.object->as(); - lastPicked->material = pickMaterial; + lastPicked->setMaterial(pickMaterial); lastPicked->scale.set(1.2, 1.2, 1.2); } diff --git a/examples/textures/data_texture.cpp b/examples/textures/data_texture.cpp index def8ad67..93356ae2 100644 --- a/examples/textures/data_texture.cpp +++ b/examples/textures/data_texture.cpp @@ -67,6 +67,20 @@ int main() { box.position.x = -1; scene.add(box); + auto grid1 = GridHelper::create(5); + grid1->rotateX(math::PI / 2); + grid1->position.z = -2.5; + scene.add(grid1); + + auto grid2 = GridHelper::create(5); + grid2->rotateX(math::PI / 2).rotateZ(math::PI / 2); + grid2->position.x = -2.5; + scene.add(grid2); + + auto grid3 = GridHelper::create(5); + grid3->position.y = -2.5; + scene.add(grid3); + canvas.onWindowResize([&](WindowSize size) { camera.aspect = size.aspect(); camera.updateProjectionMatrix(); diff --git a/include/threepp/core/BufferGeometry.hpp b/include/threepp/core/BufferGeometry.hpp index 8a4239b6..3de76903 100644 --- a/include/threepp/core/BufferGeometry.hpp +++ b/include/threepp/core/BufferGeometry.hpp @@ -15,7 +15,7 @@ namespace threepp { - class BufferGeometry: public EventDispatcher { + class BufferGeometry: public EventDispatcher, public std::enable_shared_from_this { public: const unsigned int id{++_id}; @@ -35,6 +35,11 @@ namespace threepp { BufferGeometry(); + BufferGeometry(const BufferGeometry&) = delete; + BufferGeometry& operator=(const BufferGeometry&) = delete; + BufferGeometry(BufferGeometry&&) = delete; + BufferGeometry& operator=(BufferGeometry&&) = delete; + [[nodiscard]] virtual std::string type() const { return "BufferGeometry"; diff --git a/include/threepp/core/Object3D.hpp b/include/threepp/core/Object3D.hpp index 7f82d5f5..6ccfde66 100644 --- a/include/threepp/core/Object3D.hpp +++ b/include/threepp/core/Object3D.hpp @@ -105,7 +105,7 @@ namespace threepp { Object3D(); Object3D(Object3D&& source) noexcept; - Object3D& operator=(Object3D&& other) = delete; + Object3D& operator=(Object3D&&) = delete; Object3D(const Object3D&) = delete; Object3D& operator=(const Object3D&) = delete; @@ -228,19 +228,12 @@ namespace threepp { return nullptr; } - virtual std::vector materials() { - - return {}; - } - - [[nodiscard]] virtual const Material* material() const { - - return nullptr; - } - template T* as() { + static_assert(std::is_base_of::type>::type>::value, + "T must be a base class of Object3D"); + return dynamic_cast(this); } diff --git a/include/threepp/helpers/AxesHelper.hpp b/include/threepp/helpers/AxesHelper.hpp index 40305ffc..5d20d4f2 100644 --- a/include/threepp/helpers/AxesHelper.hpp +++ b/include/threepp/helpers/AxesHelper.hpp @@ -11,8 +11,6 @@ namespace threepp { class AxesHelper: public LineSegments { public: - ~AxesHelper() override; - static std::shared_ptr create(float size); protected: diff --git a/include/threepp/helpers/BoxHelper.hpp b/include/threepp/helpers/BoxHelper.hpp index e2949e2c..34bf808f 100644 --- a/include/threepp/helpers/BoxHelper.hpp +++ b/include/threepp/helpers/BoxHelper.hpp @@ -10,7 +10,7 @@ namespace threepp { class BoxHelper: public LineSegments { public: - std::string type() const override; + [[nodiscard]] std::string type() const override; void update(); diff --git a/include/threepp/helpers/GridHelper.hpp b/include/threepp/helpers/GridHelper.hpp index 51b6d3f6..ccfe7776 100644 --- a/include/threepp/helpers/GridHelper.hpp +++ b/include/threepp/helpers/GridHelper.hpp @@ -12,8 +12,6 @@ namespace threepp { class GridHelper: public LineSegments { public: - ~GridHelper() override; - static std::shared_ptr create( unsigned int size = 10, unsigned int divisions = 10, diff --git a/include/threepp/helpers/PointLightHelper.hpp b/include/threepp/helpers/PointLightHelper.hpp index 95b0337f..ac47e73b 100644 --- a/include/threepp/helpers/PointLightHelper.hpp +++ b/include/threepp/helpers/PointLightHelper.hpp @@ -3,7 +3,6 @@ #ifndef THREEPP_POINTLIGHTHELPER_HPP #define THREEPP_POINTLIGHTHELPER_HPP -#include "threepp/geometries/SphereGeometry.hpp" #include "threepp/objects/Mesh.hpp" #include @@ -22,7 +21,7 @@ namespace threepp { private: std::optional color; - PointLight& light; + PointLight* light; PointLightHelper(PointLight& light, float sphereSize, std::optional color); }; diff --git a/include/threepp/helpers/SpotLightHelper.hpp b/include/threepp/helpers/SpotLightHelper.hpp index 80ef68f8..04df1531 100644 --- a/include/threepp/helpers/SpotLightHelper.hpp +++ b/include/threepp/helpers/SpotLightHelper.hpp @@ -19,15 +19,13 @@ namespace threepp { public: void update(); - ~SpotLightHelper() override; - static std::shared_ptr create(SpotLight& light, std::optional color = std::nullopt); private: - SpotLight& light; + SpotLight* light; std::optional color; - std::shared_ptr cone; + LineSegments* cone; SpotLightHelper(SpotLight& light, std::optional color); }; diff --git a/include/threepp/lights/DirectionalLightShadow.hpp b/include/threepp/lights/DirectionalLightShadow.hpp index efd18bdc..3265ef07 100644 --- a/include/threepp/lights/DirectionalLightShadow.hpp +++ b/include/threepp/lights/DirectionalLightShadow.hpp @@ -19,7 +19,7 @@ namespace threepp { protected: DirectionalLightShadow() - : LightShadow(OrthographicCamera::create(-5, 5, 5, -5, 0.5f, 500)) {} + : LightShadow(std::make_unique(-5.f, 5.f, 5.f, -5.f, 0.5f, 500.f)) {} }; }// namespace threepp diff --git a/include/threepp/lights/LightShadow.hpp b/include/threepp/lights/LightShadow.hpp index 3d2da458..7cfc666a 100644 --- a/include/threepp/lights/LightShadow.hpp +++ b/include/threepp/lights/LightShadow.hpp @@ -17,7 +17,7 @@ namespace threepp { class LightShadow { public: - std::shared_ptr camera; + std::unique_ptr camera; float bias = 0; float normalBias = 0; @@ -35,13 +35,14 @@ namespace threepp { LightShadow(LightShadow&&) = delete; LightShadow(const LightShadow&) = delete; + LightShadow& operator=(LightShadow&&) = delete; LightShadow& operator=(const LightShadow&) = delete; [[nodiscard]] size_t getViewportCount() const; [[nodiscard]] const Frustum& getFrustum() const; - virtual void updateMatrices(Light* light); + virtual void updateMatrices(Light& light); Vector4& getViewport(size_t viewportIndex); @@ -61,7 +62,7 @@ namespace threepp { std::vector _viewports{Vector4(0, 0, 1, 1)}; - explicit LightShadow(std::shared_ptr camera); + explicit LightShadow(std::unique_ptr camera); }; }// namespace threepp diff --git a/include/threepp/lights/SpotLightShadow.hpp b/include/threepp/lights/SpotLightShadow.hpp index b799f415..6fc800f8 100644 --- a/include/threepp/lights/SpotLightShadow.hpp +++ b/include/threepp/lights/SpotLightShadow.hpp @@ -13,7 +13,7 @@ namespace threepp { public: float focus = 1; - void updateMatrices(Light* light) override; + void updateMatrices(Light& light) override; static std::shared_ptr create(); diff --git a/include/threepp/lights/light_interfaces.hpp b/include/threepp/lights/light_interfaces.hpp index d40d7d7f..a69dd771 100644 --- a/include/threepp/lights/light_interfaces.hpp +++ b/include/threepp/lights/light_interfaces.hpp @@ -20,9 +20,21 @@ namespace threepp { class LightWithTarget { public: - std::shared_ptr target{Object3D::create()}; + [[nodiscard]] const Object3D& target() const { + + return target_ ? *target_ : defaultTarget; + } + + void setTarget(Object3D& target) { + + this->target_ = ⌖ + } virtual ~LightWithTarget() = default; + + private: + Object3D* target_ = nullptr; + Object3D defaultTarget; }; }// namespace threepp diff --git a/include/threepp/materials/Material.hpp b/include/threepp/materials/Material.hpp index 7e8250fd..89aabcbf 100644 --- a/include/threepp/materials/Material.hpp +++ b/include/threepp/materials/Material.hpp @@ -76,12 +76,15 @@ namespace threepp { std::unordered_map defaultAttributeValues; - unsigned int version = 0; - + Material(Material&&) = delete; + Material& operator=(Material&&) = delete; Material(const Material&) = delete; + Material& operator=(const Material&) = delete; std::string uuid() const; + [[nodiscard]] unsigned int version() const; + void setValues(const std::unordered_map& values); void dispose(); @@ -91,7 +94,19 @@ namespace threepp { [[nodiscard]] virtual std::string type() const = 0; template - std::shared_ptr as() { + T* as() { + + static_assert(std::is_base_of::type>::type>::value, + "T must be a base class of the current class"); + + return dynamic_cast(this); + } + + template + std::shared_ptr as_shared() { + + static_assert(std::is_base_of::type>::type>::value, + "T must be a base class of Material"); auto m = shared_from_this(); return std::dynamic_pointer_cast(m); @@ -112,7 +127,7 @@ namespace threepp { void copyInto(Material* m) const; - Color extractColor(const MaterialValue& value) { + static Color extractColor(const MaterialValue& value) { if (std::holds_alternative(value)) { return std::get(value); } else { @@ -120,7 +135,7 @@ namespace threepp { } } - float extractFloat(const MaterialValue& value) { + static float extractFloat(const MaterialValue& value) { if (std::holds_alternative(value)) { return std::get(value); } else { @@ -133,6 +148,7 @@ namespace threepp { private: bool disposed_ = false; std::string uuid_; + unsigned int version_ = 0; inline static unsigned int materialId = 0; }; diff --git a/include/threepp/objects/Line.hpp b/include/threepp/objects/Line.hpp index f4fe22a4..1f7af295 100644 --- a/include/threepp/objects/Line.hpp +++ b/include/threepp/objects/Line.hpp @@ -6,6 +6,7 @@ #include "threepp/core/BufferGeometry.hpp" #include "threepp/core/Object3D.hpp" #include "threepp/materials/Material.hpp" +#include "threepp/objects/ObjectWithMaterials.hpp" #include #include @@ -13,21 +14,19 @@ namespace threepp { - class Line: public Object3D { + class Line: public virtual Object3D, public ObjectWithMaterials { public: Line(std::shared_ptr geometry, std::shared_ptr material); + Line(Line&&) = delete; + [[nodiscard]] std::string type() const override; BufferGeometry* geometry() override; void setGeometry(const std::shared_ptr& geometry); - Material* material() override; - - std::vector materials() override; - virtual void computeLineDistances(); void raycast(const Raycaster& raycaster, std::vector& intersects) override; @@ -38,7 +37,6 @@ namespace threepp { protected: std::shared_ptr geometry_; - std::shared_ptr material_; }; }// namespace threepp diff --git a/include/threepp/objects/Mesh.hpp b/include/threepp/objects/Mesh.hpp index 25320295..bd8b3088 100644 --- a/include/threepp/objects/Mesh.hpp +++ b/include/threepp/objects/Mesh.hpp @@ -6,44 +6,29 @@ #include "threepp/core/BufferGeometry.hpp" #include "threepp/core/Object3D.hpp" #include "threepp/materials/Material.hpp" +#include "threepp/objects/ObjectWithMaterials.hpp" #include "threepp/objects/ObjectWithMorphTargetInfluences.hpp" namespace threepp { // Class representing triangular polygon mesh based objects. - class Mesh: public Object3D, public ObjectWithMorphTargetInfluences { + class Mesh: public virtual Object3D, public ObjectWithMorphTargetInfluences, public ObjectWithMaterials { public: - explicit Mesh(std::shared_ptr geometry = nullptr, std::shared_ptr material = nullptr); Mesh(std::shared_ptr geometry, std::vector> materials); - Mesh(Mesh&& other) noexcept; + Mesh(Mesh&& other) = delete; [[nodiscard]] std::string type() const override; BufferGeometry* geometry() override; - std::shared_ptr shared_geometry() { - - return geometry_; - } - [[nodiscard]] const BufferGeometry* geometry() const; void setGeometry(const std::shared_ptr& geometry); - Material* material() override; - - [[nodiscard]] std::vector materials() override; - - void setMaterial(const std::shared_ptr& material); - - void setMaterials(const std::vector>& materials); - - [[nodiscard]] size_t numMaterials() const; - void raycast(const Raycaster& raycaster, std::vector& intersects) override; std::shared_ptr clone(bool recursive = true) override; @@ -60,7 +45,6 @@ namespace threepp { protected: std::shared_ptr geometry_; - std::vector> materials_; }; }// namespace threepp diff --git a/include/threepp/objects/ObjectWithMaterials.hpp b/include/threepp/objects/ObjectWithMaterials.hpp new file mode 100644 index 00000000..7fc803f4 --- /dev/null +++ b/include/threepp/objects/ObjectWithMaterials.hpp @@ -0,0 +1,34 @@ + +#ifndef THREEPP_OBJECTWITHMATERIALS_HPP +#define THREEPP_OBJECTWITHMATERIALS_HPP + +#include "threepp/core/Object3D.hpp" +#include "threepp/materials/Material.hpp" + + +#include + +namespace threepp { + + class ObjectWithMaterials: public virtual Object3D { + + public: + Material* material() override; + + void setMaterial(const std::shared_ptr& material); + + std::vector materials(); + + void setMaterials(const std::vector>& materials); + + [[nodiscard]] size_t numMaterials() const; + + protected: + std::vector> materials_; + + explicit ObjectWithMaterials(std::vector> materials); + }; + +}// namespace threepp + +#endif//THREEPP_OBJECTWITHMATERIALS_HPP diff --git a/include/threepp/objects/ObjectWithMorphTargetInfluences.hpp b/include/threepp/objects/ObjectWithMorphTargetInfluences.hpp index 50ec359d..dc2f73a0 100644 --- a/include/threepp/objects/ObjectWithMorphTargetInfluences.hpp +++ b/include/threepp/objects/ObjectWithMorphTargetInfluences.hpp @@ -2,12 +2,15 @@ #ifndef THREEPP_OBJECTWITHMORPHTARGETINFLUENCES_HPP #define THREEPP_OBJECTWITHMORPHTARGETINFLUENCES_HPP +#include "threepp/core/Object3D.hpp" + #include namespace threepp { - struct ObjectWithMorphTargetInfluences { + class ObjectWithMorphTargetInfluences: public virtual Object3D { + public: std::vector& morphTargetInfluences() { if (copyMorphTargetInfluences_) { diff --git a/include/threepp/objects/Points.hpp b/include/threepp/objects/Points.hpp index ec444466..07421c88 100644 --- a/include/threepp/objects/Points.hpp +++ b/include/threepp/objects/Points.hpp @@ -6,25 +6,24 @@ #include "threepp/core/BufferGeometry.hpp" #include "threepp/core/Object3D.hpp" #include "threepp/materials/PointsMaterial.hpp" +#include "threepp/objects/ObjectWithMaterials.hpp" #include "threepp/objects/ObjectWithMorphTargetInfluences.hpp" namespace threepp { - class Points: public Object3D, public ObjectWithMorphTargetInfluences { + class Points: public virtual Object3D, public ObjectWithMorphTargetInfluences, public ObjectWithMaterials { public: Points(std::shared_ptr geometry, std::shared_ptr material); + Points(Points&&) = delete; + [[nodiscard]] std::string type() const override; BufferGeometry* geometry() override; void setGeometry(const std::shared_ptr& geometry); - Material* material() override; - - std::vector materials() override; - std::shared_ptr clone(bool recursive = true) override; void raycast(const Raycaster& raycaster, std::vector& intersects) override; @@ -35,7 +34,6 @@ namespace threepp { protected: std::shared_ptr geometry_; - std::shared_ptr material_; }; }// namespace threepp diff --git a/include/threepp/objects/Sprite.hpp b/include/threepp/objects/Sprite.hpp index 35e5aa51..35b78c9a 100644 --- a/include/threepp/objects/Sprite.hpp +++ b/include/threepp/objects/Sprite.hpp @@ -13,20 +13,26 @@ namespace threepp { public: Vector2 center{0.5f, 0.5f}; - std::shared_ptr material; explicit Sprite(const std::shared_ptr& material); + Sprite(Sprite&&) = delete; + [[nodiscard]] std::string type() const override; void raycast(const Raycaster& raycaster, std::vector& intersects) override; BufferGeometry* geometry() override; - static std::shared_ptr create(const std::shared_ptr& material = SpriteMaterial::create()); + Material* material() override; + + void setMaterial(const std::shared_ptr& material); + + static std::shared_ptr create(const std::shared_ptr& material = nullptr); private: std::shared_ptr _geometry; + std::shared_ptr _material; }; }// namespace threepp diff --git a/include/threepp/textures/Texture.hpp b/include/threepp/textures/Texture.hpp index aa8c1fa3..c3736942 100644 --- a/include/threepp/textures/Texture.hpp +++ b/include/threepp/textures/Texture.hpp @@ -64,7 +64,9 @@ namespace threepp { Encoding encoding{Encoding::Linear}; Texture(const Texture&) = delete; - Texture operator=(const Texture&) = delete; + Texture& operator=(const Texture&) = delete; + Texture(Texture&&) = delete; + Texture& operator=(Texture&&) = delete; std::optional> onUpdate; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 406622e6..05665a6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -150,6 +150,7 @@ set(publicHeaders "threepp/objects/LineSegments.hpp" "threepp/objects/LOD.hpp" "threepp/objects/Mesh.hpp" + "threepp/objects/ObjectWithMaterials.hpp" "threepp/objects/ObjectWithMorphTargetInfluences.hpp" "threepp/objects/ParticleSystem.hpp" "threepp/objects/Sky.hpp" @@ -371,6 +372,7 @@ set(sources "threepp/objects/LOD.cpp" "threepp/objects/InstancedMesh.cpp" "threepp/objects/Mesh.cpp" + "threepp/objects/ObjectWithMaterials.cpp" "threepp/objects/ParticleSystem.cpp" "threepp/objects/Points.cpp" "threepp/objects/Skeleton.cpp" diff --git a/src/threepp/geometries/PlaneGeometry.cpp b/src/threepp/geometries/PlaneGeometry.cpp index a6f79869..592d3e21 100644 --- a/src/threepp/geometries/PlaneGeometry.cpp +++ b/src/threepp/geometries/PlaneGeometry.cpp @@ -23,10 +23,15 @@ PlaneGeometry::PlaneGeometry(const Params& params) // - std::list indices; - std::list vertices; - std::list normals; - std::list uvs; + std::vector indices; + std::vector vertices; + std::vector normals; + std::vector uvs; + + vertices.reserve(gridX1 * gridY1 * 3); + normals.reserve(gridX1 * gridY1 * 3); + uvs.reserve(gridX1 * gridY1 * 2); + indices.reserve(gridX * gridY * 6); for (unsigned iy = 0; iy < gridY1; iy++) { @@ -36,9 +41,13 @@ PlaneGeometry::PlaneGeometry(const Params& params) const auto x = static_cast(ix) * segment_width - width_half; - vertices.insert(vertices.end(), {x, -y, 0}); + vertices.push_back(x); + vertices.push_back(-y); + vertices.push_back(0); - normals.insert(normals.end(), {0, 0, 1}); + normals.push_back(0); + normals.push_back(0); + normals.push_back(1); uvs.emplace_back(static_cast(ix) / static_cast(gridX)); uvs.emplace_back(1 - (static_cast(iy) / static_cast(gridY))); @@ -54,8 +63,12 @@ PlaneGeometry::PlaneGeometry(const Params& params) const auto c = ((ix + 1) + gridX1 * (iy + 1)); const auto d = ((ix + 1) + gridX1 * iy); - indices.insert(indices.end(), {a, b, d}); - indices.insert(indices.end(), {b, c, d}); + indices.push_back(a); + indices.push_back(b); + indices.push_back(d); + indices.push_back(b); + indices.push_back(c); + indices.push_back(d); } } diff --git a/src/threepp/helpers/AxesHelper.cpp b/src/threepp/helpers/AxesHelper.cpp index 0b8a8eab..a10050c6 100644 --- a/src/threepp/helpers/AxesHelper.cpp +++ b/src/threepp/helpers/AxesHelper.cpp @@ -20,16 +20,10 @@ AxesHelper::AxesHelper(float size): LineSegments(BufferGeometry::create(), LineB geometry_->setAttribute("position", FloatBufferAttribute::create(vertices, 3)); geometry_->setAttribute("color", FloatBufferAttribute::create(colors, 3)); - material_->vertexColors = true; + materials_.front()->vertexColors = true; } std::shared_ptr AxesHelper::create(float size) { return std::shared_ptr(new AxesHelper(size)); } - -AxesHelper::~AxesHelper() { - - this->geometry_->dispose(); - this->material_->dispose(); -} diff --git a/src/threepp/helpers/Box3Helper.cpp b/src/threepp/helpers/Box3Helper.cpp index b6ca5efc..e8a9c1a7 100644 --- a/src/threepp/helpers/Box3Helper.cpp +++ b/src/threepp/helpers/Box3Helper.cpp @@ -13,7 +13,7 @@ Box3Helper::Box3Helper(const Box3& box, const Color& color) std::vector positions{1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1}; - auto lineMaterial = material_->as(); + auto lineMaterial = material()->as(); lineMaterial->color.copy(color); lineMaterial->toneMapped = false; diff --git a/src/threepp/helpers/BoxHelper.cpp b/src/threepp/helpers/BoxHelper.cpp index 177f3e57..31c31170 100644 --- a/src/threepp/helpers/BoxHelper.cpp +++ b/src/threepp/helpers/BoxHelper.cpp @@ -16,7 +16,7 @@ BoxHelper::BoxHelper(Object3D& object, const Color& color) geometry_->setIndex(indices); geometry_->setAttribute("position", FloatBufferAttribute::create(positions, 3)); - material_->setValues({{"color", color}, {"toneMapped", false}}); + material()->setValues({{"color", color}, {"toneMapped", false}}); this->matrixAutoUpdate = false; diff --git a/src/threepp/helpers/CameraHelper.cpp b/src/threepp/helpers/CameraHelper.cpp index 107e80b9..abd7df81 100644 --- a/src/threepp/helpers/CameraHelper.cpp +++ b/src/threepp/helpers/CameraHelper.cpp @@ -18,7 +18,7 @@ struct CameraHelper::Impl { explicit Impl(CameraHelper& scope, Camera& camera) : scope(scope), camera(camera) { - auto m = scope.material_->as(); + auto m = scope.material()->as(); m->toneMapped = false; m->vertexColors = true; m->color = 0xffffff; diff --git a/src/threepp/helpers/DirectionalLightHelper.cpp b/src/threepp/helpers/DirectionalLightHelper.cpp index 13e1ea7c..bb8e2dfb 100644 --- a/src/threepp/helpers/DirectionalLightHelper.cpp +++ b/src/threepp/helpers/DirectionalLightHelper.cpp @@ -48,7 +48,7 @@ void DirectionalLightHelper::update() { static Vector3 _v3; _v1.setFromMatrixPosition(*this->light.matrixWorld); - _v2.setFromMatrixPosition(*this->light.target->matrixWorld); + _v2.setFromMatrixPosition(*this->light.target().matrixWorld); _v3.subVectors(_v2, _v1); this->lightPlane->lookAt(_v2); diff --git a/src/threepp/helpers/GridHelper.cpp b/src/threepp/helpers/GridHelper.cpp index ee63bfd9..8254bde1 100644 --- a/src/threepp/helpers/GridHelper.cpp +++ b/src/threepp/helpers/GridHelper.cpp @@ -37,25 +37,15 @@ GridHelper::GridHelper(unsigned int size, unsigned int divisions, const Color& c k += step; } - auto geometry = BufferGeometry::create(); - geometry->setAttribute("position", FloatBufferAttribute::create(vertices, 3)); - geometry->setAttribute("color", FloatBufferAttribute::create(colors, 3)); + geometry_->setAttribute("position", FloatBufferAttribute::create(vertices, 3)); + geometry_->setAttribute("color", FloatBufferAttribute::create(colors, 3)); - auto material = LineBasicMaterial::create(); - material->vertexColors = true; - material->toneMapped = false; - - material_ = material; - geometry_ = geometry; + auto m = material()->as(); + m->vertexColors = true; + m->toneMapped = false; } std::shared_ptr GridHelper::create(unsigned int size, unsigned int divisions, const Color& color1, const Color& color2) { return std::shared_ptr(new GridHelper(size, divisions, color1, color2)); } - -GridHelper::~GridHelper() { - - this->geometry_->dispose(); - this->material_->dispose(); -} diff --git a/src/threepp/helpers/HemisphereLightHelper.cpp b/src/threepp/helpers/HemisphereLightHelper.cpp index 5cab170b..8888f487 100644 --- a/src/threepp/helpers/HemisphereLightHelper.cpp +++ b/src/threepp/helpers/HemisphereLightHelper.cpp @@ -110,4 +110,4 @@ std::shared_ptr threepp::HemisphereLightHelper::create(He return std::shared_ptr(new HemisphereLightHelper(light, size, color)); } -threepp::HemisphereLightHelper::~HemisphereLightHelper() = default; +HemisphereLightHelper::~HemisphereLightHelper() = default; diff --git a/src/threepp/helpers/PlaneHelper.cpp b/src/threepp/helpers/PlaneHelper.cpp index 753bb131..529a9d8e 100644 --- a/src/threepp/helpers/PlaneHelper.cpp +++ b/src/threepp/helpers/PlaneHelper.cpp @@ -15,9 +15,9 @@ PlaneHelper::PlaneHelper(const Plane& plane, float size, const Color& color) geometry_->setAttribute("position", FloatBufferAttribute::create(positions, 3)); geometry_->computeBoundingSphere(); - auto material = dynamic_cast(material_.get()); - material->color.copy(color); - material->toneMapped = false; + auto _material = material()->as(); + _material->color.copy(color); + _material->toneMapped = false; std::vector positions2{1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1}; diff --git a/src/threepp/helpers/PointLightHelper.cpp b/src/threepp/helpers/PointLightHelper.cpp index 919e919d..cd1e044a 100644 --- a/src/threepp/helpers/PointLightHelper.cpp +++ b/src/threepp/helpers/PointLightHelper.cpp @@ -1,6 +1,7 @@ #include "threepp/helpers/PointLightHelper.hpp" +#include "threepp/geometries/SphereGeometry.hpp" #include "threepp/lights/PointLight.hpp" #include "threepp/materials/MeshBasicMaterial.hpp" @@ -8,7 +9,7 @@ using namespace threepp; PointLightHelper::PointLightHelper(PointLight& light, float sphereSize, std::optional color) - : Mesh(nullptr, nullptr), light(light), color(color) { + : Mesh(nullptr, nullptr), light(&light), color(color) { geometry_ = SphereGeometry::create(sphereSize, 4, 2); @@ -18,9 +19,9 @@ PointLightHelper::PointLightHelper(PointLight& light, float sphereSize, std::opt material->toneMapped = false; this->materials_[0] = std::move(material); - this->light.updateMatrixWorld(); + this->light->updateMatrixWorld(); - this->matrix = this->light.matrixWorld; + this->matrix = this->light->matrixWorld; this->matrixAutoUpdate = false; update(); @@ -39,6 +40,6 @@ void PointLightHelper::update() { } else { - this->material()->as()->color.copy(this->light.color); + this->material()->as()->color.copy(this->light->color); } } diff --git a/src/threepp/helpers/PolarGridHelper.cpp b/src/threepp/helpers/PolarGridHelper.cpp index 5e5cc8b9..841054ed 100644 --- a/src/threepp/helpers/PolarGridHelper.cpp +++ b/src/threepp/helpers/PolarGridHelper.cpp @@ -70,7 +70,7 @@ PolarGridHelper::PolarGridHelper(float radius, unsigned int sectors, unsigned in geometry_->setAttribute("position", FloatBufferAttribute::create(vertices, 3)); geometry_->setAttribute("color", FloatBufferAttribute::create(colors, 3)); - material_->setValues({{"vertexColors", true}, {"toneMapped", false}}); + material()->setValues({{"vertexColors", true}, {"toneMapped", false}}); } diff --git a/src/threepp/helpers/SkeletonHelper.cpp b/src/threepp/helpers/SkeletonHelper.cpp index 6191d86f..9953b329 100644 --- a/src/threepp/helpers/SkeletonHelper.cpp +++ b/src/threepp/helpers/SkeletonHelper.cpp @@ -55,7 +55,7 @@ SkeletonHelper::SkeletonHelper(Object3D& object) geometry_->setAttribute("position", FloatBufferAttribute::create(vertices, 3)); geometry_->setAttribute("color", FloatBufferAttribute::create(colors, 3)); - auto m = material_->as(); + auto m = material()->as(); m->vertexColors = true; m->depthTest = false; m->depthWrite = false; diff --git a/src/threepp/helpers/SpotLightHelper.cpp b/src/threepp/helpers/SpotLightHelper.cpp index 10beb1d2..c520eddf 100644 --- a/src/threepp/helpers/SpotLightHelper.cpp +++ b/src/threepp/helpers/SpotLightHelper.cpp @@ -11,11 +11,11 @@ using namespace threepp; SpotLightHelper::SpotLightHelper(SpotLight& light, std::optional color) - : light(light), color(color) { + : light(&light), color(color) { - this->light.updateMatrixWorld(); + this->light->updateMatrixWorld(); - this->matrix = this->light.matrixWorld; + this->matrix = this->light->matrixWorld; this->matrixAutoUpdate = false; auto geometry = BufferGeometry::create(); @@ -43,8 +43,9 @@ SpotLightHelper::SpotLightHelper(SpotLight& light, std::optional color) material->fog = false; material->toneMapped = false; - this->cone = LineSegments::create(geometry, material); - this->add(this->cone); + auto _cone = LineSegments::create(geometry, material); + this->cone = _cone.get(); + this->add(_cone); this->update(); } @@ -56,15 +57,15 @@ std::shared_ptr SpotLightHelper::create(SpotLight& light, std:: void SpotLightHelper::update() { - this->light.updateMatrixWorld(); + this->light->updateMatrixWorld(); - const auto coneLength = (this->light.distance > 0) ? this->light.distance : 1000; - const auto coneWidth = coneLength * std::tan(this->light.angle); + const auto coneLength = (this->light->distance > 0) ? this->light->distance : 1000; + const auto coneWidth = coneLength * std::tan(this->light->angle); this->cone->scale.set(coneWidth, coneWidth, coneLength); static Vector3 _vector; - _vector.setFromMatrixPosition(*this->light.target->matrixWorld); + _vector.setFromMatrixPosition(*this->light->target().matrixWorld); this->cone->lookAt(_vector); @@ -74,12 +75,6 @@ void SpotLightHelper::update() { } else { - this->cone->material()->as()->color.copy(this->light.color); + this->cone->material()->as()->color.copy(this->light->color); } } - -SpotLightHelper::~SpotLightHelper() { - - this->cone->geometry()->dispose(); - this->cone->material()->dispose(); -} diff --git a/src/threepp/lights/LightShadow.cpp b/src/threepp/lights/LightShadow.cpp index 594af371..6a78de28 100644 --- a/src/threepp/lights/LightShadow.cpp +++ b/src/threepp/lights/LightShadow.cpp @@ -7,7 +7,7 @@ using namespace threepp; -LightShadow::LightShadow(std::shared_ptr camera) +LightShadow::LightShadow(std::unique_ptr camera) : camera(std::move(camera)) {} @@ -21,16 +21,16 @@ const Frustum& LightShadow::getFrustum() const { return this->_frustum; } -void LightShadow::updateMatrices(Light* light) { +void LightShadow::updateMatrices(Light& light) { auto& shadowCamera = this->camera; auto& shadowMatrix = this->matrix; - _lightPositionWorld.setFromMatrixPosition(*light->matrixWorld); + _lightPositionWorld.setFromMatrixPosition(*light.matrixWorld); shadowCamera->position.copy(_lightPositionWorld); - auto lightWithTarget = dynamic_cast(light); - _lookTarget.setFromMatrixPosition(*lightWithTarget->target->matrixWorld); + auto lightWithTarget = dynamic_cast(&light); + _lookTarget.setFromMatrixPosition(*lightWithTarget->target().matrixWorld); shadowCamera->lookAt(_lookTarget); shadowCamera->updateMatrixWorld(); diff --git a/src/threepp/lights/PointLightShadow.cpp b/src/threepp/lights/PointLightShadow.cpp index 9496f2f6..63514457 100644 --- a/src/threepp/lights/PointLightShadow.cpp +++ b/src/threepp/lights/PointLightShadow.cpp @@ -6,16 +6,9 @@ using namespace threepp; -namespace { - - Vector3 _lightPositionWorld; - Vector3 _lookTarget; - Matrix4 _projScreenMatrix; - -}// namespace PointLightShadow::PointLightShadow() - : LightShadow(PerspectiveCamera::create(90, 1, 0.5f, 500)), + : LightShadow(std::make_unique(90.f, 1.f, 0.5f, 500.f)), _cubeDirections({Vector3(1, 0, 0), Vector3(-1, 0, 0), Vector3(0, 0, 1), Vector3(0, 0, -1), Vector3(0, 1, 0), Vector3(0, -1, 0)}), _cubeUps({Vector3(0, 1, 0), Vector3(0, 1, 0), Vector3(0, 1, 0), diff --git a/src/threepp/lights/SpotLightShadow.cpp b/src/threepp/lights/SpotLightShadow.cpp index 610f58d7..b2224fa7 100644 --- a/src/threepp/lights/SpotLightShadow.cpp +++ b/src/threepp/lights/SpotLightShadow.cpp @@ -5,11 +5,11 @@ using namespace threepp; SpotLightShadow::SpotLightShadow() - : LightShadow(PerspectiveCamera::create(50, 1, 0.5f, 500)) {} + : LightShadow(std::make_unique(50.f, 1.f, 0.5f, 500.f)) {} -void SpotLightShadow::updateMatrices(Light* _light) { +void SpotLightShadow::updateMatrices(Light& _light) { - auto light = _light->as(); + auto light = _light.as(); const auto fov = math::RAD2DEG * 2 * light->angle * this->focus; const auto aspect = this->mapSize.x / this->mapSize.y; diff --git a/src/threepp/materials/Material.cpp b/src/threepp/materials/Material.cpp index 758b96b4..0c9a82b4 100644 --- a/src/threepp/materials/Material.cpp +++ b/src/threepp/materials/Material.cpp @@ -8,14 +8,21 @@ using namespace threepp; + Material::Material() : uuid_(math::generateUUID()) {} + std::string Material::uuid() const { return uuid_; } +unsigned int Material::version() const { + + return version_; +} + void Material::dispose() { if (!disposed_) { disposed_ = true; @@ -25,7 +32,7 @@ void Material::dispose() { void Material::needsUpdate() { - this->version++; + this->version_++; } void Material::copyInto(Material* m) const { diff --git a/src/threepp/objects/Line.cpp b/src/threepp/objects/Line.cpp index 3e9041e8..1daeadf5 100644 --- a/src/threepp/objects/Line.cpp +++ b/src/threepp/objects/Line.cpp @@ -20,7 +20,7 @@ namespace { Line::Line(std::shared_ptr geometry, std::shared_ptr material) : geometry_(geometry ? std::move(geometry) : BufferGeometry::create()), - material_(material ? std::move(material) : LineBasicMaterial::create()) {} + ObjectWithMaterials({material ? std::move(material) : LineBasicMaterial::create()}) {} std::string Line::type() const { @@ -36,18 +36,8 @@ void Line::setGeometry(const std::shared_ptr& geometry) { this->geometry_ = geometry; } -Material* Line::material() { - - return material_.get(); -} - -std::vector Line::materials() { - - return {material_.get()}; -} - std::shared_ptr Line::clone(bool recursive) { - auto clone = create(geometry_, material_); + auto clone = create(geometry_, materials_.front()); clone->copy(*this, recursive); return clone; diff --git a/src/threepp/objects/Mesh.cpp b/src/threepp/objects/Mesh.cpp index 46a61e76..4f0ea3fe 100644 --- a/src/threepp/objects/Mesh.cpp +++ b/src/threepp/objects/Mesh.cpp @@ -174,24 +174,10 @@ namespace { Mesh::Mesh(std::shared_ptr geometry, std::shared_ptr material) : geometry_(geometry ? std::move(geometry) : BufferGeometry::create()), - materials_{material ? std::move(material) : MeshBasicMaterial::create()} { -} + ObjectWithMaterials({material ? std::move(material) : MeshBasicMaterial::create()}) {} Mesh::Mesh(std::shared_ptr geometry, std::vector> materials) - : geometry_(std::move(geometry)), materials_{std::move(materials)} { -} - -Mesh::Mesh(Mesh&& other) noexcept: Object3D(std::move(other)) { - geometry_ = std::move(other.geometry_); - materials_ = std::move(other.materials_); -} - -std::vector Mesh::materials() { - - std::vector res(materials_.size()); - std::transform(materials_.begin(), materials_.end(), res.begin(), [](auto& m) { return m.get(); }); - - return res; + : geometry_(std::move(geometry)), ObjectWithMaterials{std::move(materials)} { } void Mesh::raycast(const Raycaster& raycaster, std::vector& intersects) { @@ -375,26 +361,6 @@ void Mesh::setGeometry(const std::shared_ptr& geometry) { geometry_ = geometry; } -Material* Mesh::material() { - - return materials_.front().get(); -} - -void Mesh::setMaterial(const std::shared_ptr& material) { - - setMaterials({material}); -} - -void Mesh::setMaterials(const std::vector>& materials) { - - materials_ = materials; -} - -size_t Mesh::numMaterials() const { - - return materials_.size(); -} - std::shared_ptr Mesh::create(std::shared_ptr geometry, std::shared_ptr material) { return std::make_shared(std::move(geometry), std::move(material)); diff --git a/src/threepp/objects/ObjectWithMaterials.cpp b/src/threepp/objects/ObjectWithMaterials.cpp new file mode 100644 index 00000000..9a6191cf --- /dev/null +++ b/src/threepp/objects/ObjectWithMaterials.cpp @@ -0,0 +1,38 @@ + +#include "threepp/objects/ObjectWithMaterials.hpp" + +#include + +using namespace threepp; + + +ObjectWithMaterials::ObjectWithMaterials(std::vector> materials) + : materials_(std::move(materials)) {} + + +Material* ObjectWithMaterials::material() { + + return materials_.front().get(); +} + +void ObjectWithMaterials::setMaterial(const std::shared_ptr& material) { + + setMaterials({material}); +} + +std::vector ObjectWithMaterials::materials() { + std::vector res(materials_.size()); + std::transform(materials_.begin(), materials_.end(), res.begin(), [](auto& m) { return m.get(); }); + + return res; +} + +void ObjectWithMaterials::setMaterials(const std::vector>& materials) { + + this->materials_ = materials; +} + +size_t ObjectWithMaterials::numMaterials() const { + + return materials_.size(); +} diff --git a/src/threepp/objects/Points.cpp b/src/threepp/objects/Points.cpp index 240e663c..4197b3f1 100644 --- a/src/threepp/objects/Points.cpp +++ b/src/threepp/objects/Points.cpp @@ -49,8 +49,7 @@ namespace { }// namespace Points::Points(std::shared_ptr geometry, std::shared_ptr material) - : geometry_(std::move(geometry)), material_(std::move(material)) { -} + : geometry_(std::move(geometry)), ObjectWithMaterials({std::move(material)}) {} std::string Points::type() const { @@ -66,18 +65,8 @@ void Points::setGeometry(const std::shared_ptr& geometry) { this->geometry_ = geometry; } -Material* Points::material() { - - return material_.get(); -} - -std::vector Points::materials() { - - return {material_.get()}; -} - std::shared_ptr Points::clone(bool recursive) { - auto clone = create(geometry_, material_); + auto clone = create(geometry_, materials_.front()); clone->copy(*this, recursive); return clone; diff --git a/src/threepp/objects/Sprite.cpp b/src/threepp/objects/Sprite.cpp index 2f56cd96..19cb610d 100644 --- a/src/threepp/objects/Sprite.cpp +++ b/src/threepp/objects/Sprite.cpp @@ -63,8 +63,8 @@ namespace { Sprite::Sprite(const std::shared_ptr& material) - : material(material), - _geometry(new BufferGeometry()) { + : _material(material ? material : SpriteMaterial::create()), + _geometry(BufferGeometry::create()) { std::vector float32Array{ -0.5f, -0.5f, 0.f, 0.f, 0.f, @@ -83,6 +83,16 @@ std::string Sprite::type() const { return "Sprite"; } +Material* Sprite::material() { + + return _material.get(); +} + +void Sprite::setMaterial(const std::shared_ptr& material) { + + this->_material = material; +} + BufferGeometry* Sprite::geometry() { return _geometry.get(); @@ -107,12 +117,12 @@ void Sprite::raycast(const Raycaster& raycaster, std::vector& inte _mvPosition.setFromMatrixPosition(this->modelViewMatrix); - if (raycaster.camera->is() && !this->material->sizeAttenuation) { + if (raycaster.camera->is() && !this->_material->sizeAttenuation) { _worldScale.multiplyScalar(-_mvPosition.z); } - float rotation = material->rotation; + float rotation = _material->rotation; std::optional> sincos; if (rotation != 0) { diff --git a/src/threepp/renderers/GLRenderer.cpp b/src/threepp/renderers/GLRenderer.cpp index cbf39b03..ff4f1e4a 100644 --- a/src/threepp/renderers/GLRenderer.cpp +++ b/src/threepp/renderers/GLRenderer.cpp @@ -480,12 +480,12 @@ struct GLRenderer::Impl { .applyMatrix4(_projScreenMatrix); } - auto geometry = objects.update(object); - auto material = sprite->material; + const auto geometry = objects.update(object); + const auto material = sprite->material(); if (material->visible) { - currentRenderList->push(object, geometry, material.get(), groupOrder, _vector3.z, std::nullopt); + currentRenderList->push(object, geometry, material, groupOrder, _vector3.z, std::nullopt); } } @@ -511,7 +511,7 @@ struct GLRenderer::Impl { } auto geometry = objects.update(object); - const auto& materials = object->materials(); + const auto& materials = object->as()->materials(); if (materials.size() > 1) { @@ -754,7 +754,7 @@ struct GLRenderer::Impl { bool isInstancedMesh = object->type() == "InstancedMesh"; bool isSkinnedMesh = object->type() == "SkinnedMesh"; - if (material->version == materialProperties->version) { + if (material->version() == materialProperties->version) { if (materialProperties->needsLights && (materialProperties->lightsStateVersion != lights.state.version)) { @@ -802,7 +802,7 @@ struct GLRenderer::Impl { } else { needsProgramChange = true; - materialProperties->version = material->version; + materialProperties->version = material->version(); } // diff --git a/src/threepp/renderers/gl/GLLights.cpp b/src/threepp/renderers/gl/GLLights.cpp index 03316cde..f6ba4094 100644 --- a/src/threepp/renderers/gl/GLLights.cpp +++ b/src/threepp/renderers/gl/GLLights.cpp @@ -17,7 +17,7 @@ namespace { bool shadowCastingLightsFirst(const Light* lightA, const Light* lightB) { - return (lightB->castShadow ? 1 : 0) > (lightA->castShadow ? 1 : 0); + return (lightB->castShadow ? 1 : 0) < (lightA->castShadow ? 1 : 0); } template @@ -46,14 +46,14 @@ void GLLights::setup(std::vector& lights) { int numPointShadows = 0; int numSpotShadows = 0; - std::stable_sort(lights.begin(), lights.end(), shadowCastingLightsFirst); + std::sort(lights.begin(), lights.end(), shadowCastingLightsFirst); for (auto light : lights) { - auto& color = light->color; - auto intensity = light->intensity; + const auto& color = light->color; + const auto intensity = light->intensity; - if (light->is()) { + if (light->type() == "AmbientLight") { r += color.r * intensity; g += color.g * intensity; @@ -61,7 +61,7 @@ void GLLights::setup(std::vector& lights) { } else if (light->type() == "LightProbe") { - auto l = light->as(); + const auto l = light->as(); for (unsigned j = 0; j < 9; ++j) { @@ -70,7 +70,7 @@ void GLLights::setup(std::vector& lights) { } else if (auto directionalLight = light->as()) { - auto uniforms = cache_.get(*light); + const auto uniforms = cache_.get(*light); std::get(uniforms->at("color")).copy(light->color).multiplyScalar(light->intensity); @@ -102,7 +102,7 @@ void GLLights::setup(std::vector& lights) { } else if (auto spotLight = light->as()) { - auto uniforms = cache_.get(*light); + const auto uniforms = cache_.get(*light); std::get(uniforms->at("position")).setFromMatrixPosition(*spotLight->matrixWorld); @@ -115,8 +115,8 @@ void GLLights::setup(std::vector& lights) { if (light->castShadow) { - auto& shadow = spotLight->shadow; - auto shadowUniforms = shadowCache_.get(*light); + const auto& shadow = spotLight->shadow; + const auto shadowUniforms = shadowCache_.get(*light); shadowUniforms->at("shadowBias") = shadow->bias; shadowUniforms->at("shadowNormalBias") = shadow->normalBias; @@ -140,7 +140,7 @@ void GLLights::setup(std::vector& lights) { } else if (auto pointLight = light->as()) { - auto uniforms = cache_.get(*light); + const auto uniforms = cache_.get(*light); std::get(uniforms->at("color")).copy(light->color).multiplyScalar(pointLight->intensity); uniforms->at("distance") = pointLight->distance; @@ -148,7 +148,7 @@ void GLLights::setup(std::vector& lights) { if (light->castShadow) { - auto& shadow = pointLight->shadow; + const auto& shadow = pointLight->shadow; LightUniforms* shadowUniforms = shadowCache_.get(*light); shadowUniforms->at("shadowBias") = shadow->bias; @@ -175,7 +175,7 @@ void GLLights::setup(std::vector& lights) { } else if (auto hemisphereLight = light->as()) { - auto uniforms = cache_.get(*light); + const auto uniforms = cache_.get(*light); std::get(uniforms->at("skyColor")).copy(hemisphereLight->color).multiplyScalar(intensity); std::get(uniforms->at("groundColor")).copy(hemisphereLight->groundColor).multiplyScalar(intensity); @@ -248,7 +248,7 @@ void GLLights::setupView(std::vector& lights, Camera* camera) { direction.setFromMatrixPosition(*light->matrixWorld); Vector3 vector3; - vector3.setFromMatrixPosition(*l->target->matrixWorld); + vector3.setFromMatrixPosition(*l->target().matrixWorld); direction.sub(vector3); direction.transformDirection(viewMatrix); @@ -268,7 +268,7 @@ void GLLights::setupView(std::vector& lights, Camera* camera) { direction.setFromMatrixPosition(*l->matrixWorld); Vector3 vector3; - vector3.setFromMatrixPosition(*l->target->matrixWorld); + vector3.setFromMatrixPosition(*l->target().matrixWorld); direction.sub(vector3); direction.transformDirection(viewMatrix); diff --git a/src/threepp/renderers/gl/GLLights.hpp b/src/threepp/renderers/gl/GLLights.hpp index 29ec4d9a..23adbe1d 100644 --- a/src/threepp/renderers/gl/GLLights.hpp +++ b/src/threepp/renderers/gl/GLLights.hpp @@ -22,10 +22,10 @@ namespace threepp::gl { if (lights.count(light.id)) { - return lights.at(light.id).get(); + return &lights.at(light.id); } - auto type = light.type(); + const auto type = light.type(); LightUniforms uniforms; if (type == "DirectionalLight") { @@ -60,13 +60,13 @@ namespace threepp::gl { {"groundColor", Color()}}; } - lights[light.id] = std::make_unique(uniforms); + lights[light.id] = LightUniforms(uniforms); - return lights.at(light.id).get(); + return &lights.at(light.id); } private: - std::unordered_map> lights; + std::unordered_map lights; }; struct ShadowUniformsCache { @@ -75,10 +75,10 @@ namespace threepp::gl { if (lights.count(light.id)) { - return lights.at(light.id).get(); + return &lights.at(light.id); } - auto type = light.type(); + const auto type = light.type(); LightUniforms uniforms; if (type == "DirectionalLight") { @@ -107,13 +107,13 @@ namespace threepp::gl { {"shadowCameraFar", 1000.f}}; } - lights[light.id] = std::make_unique(uniforms); + lights[light.id] = LightUniforms(uniforms); - return lights.at(light.id).get(); + return &lights.at(light.id); } private: - std::unordered_map> lights; + std::unordered_map lights; }; diff --git a/src/threepp/renderers/gl/GLMaterials.cpp b/src/threepp/renderers/gl/GLMaterials.cpp index 3feec8a7..81f8d3c0 100644 --- a/src/threepp/renderers/gl/GLMaterials.cpp +++ b/src/threepp/renderers/gl/GLMaterials.cpp @@ -484,54 +484,54 @@ struct GLMaterials::Impl { } else if (type == "MeshLambertMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, m); refreshUniformsLambert(uniforms, m); } else if (type == "MeshToonMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, m); refreshUniformsToon(uniforms, m); } else if (type == "MeshPhongMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, m); refreshUniformsPhong(uniforms, m); } else if (type == "MeshStandardMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, material); refreshUniformsStandard(uniforms, m); } else if (type == "MeshMatcapMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, m); refreshUniformsMatcap(uniforms, m); } else if (type == "MeshDepthMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsCommon(uniforms, m); refreshUniformsDepth(uniforms, m); } else if (type == "MeshDistanceMaterial") { auto m = material->as(); - refreshUniformsCommon(uniforms, m.get()); - refreshUniformsDistance(uniforms, m.get()); + refreshUniformsCommon(uniforms, m); + refreshUniformsDistance(uniforms, m); } else if (type == "LineBasicMaterial") { auto m = material->as(); - refreshUniformsLine(uniforms, m.get()); + refreshUniformsLine(uniforms, m); } else if (type == "PointsMaterial") { - auto m = material->as().get(); + auto m = material->as(); refreshUniformsPoints(uniforms, m, pixelRatio, static_cast(height)); } else if (type == "ShadowMaterial") { @@ -543,7 +543,7 @@ struct GLMaterials::Impl { } else if (type == "SpriteMaterial") { auto m = material->as(); - refreshUniformsSprites(uniforms, m.get()); + refreshUniformsSprites(uniforms, m); } else if (type == "ShaderMaterial") { diff --git a/src/threepp/renderers/gl/GLShadowMap.cpp b/src/threepp/renderers/gl/GLShadowMap.cpp index 02cbabd0..9a170e98 100644 --- a/src/threepp/renderers/gl/GLShadowMap.cpp +++ b/src/threepp/renderers/gl/GLShadowMap.cpp @@ -36,35 +36,6 @@ namespace { {Side::Back, Side::Front}, {Side::Double, Side::Double}}; - std::shared_ptr createShadowMaterialVertical() { - - auto shadowMaterialVertical = ShaderMaterial::create(); - shadowMaterialVertical->vertexShader = shaders::ShaderChunk::instance().get("vsm_vert"); - shadowMaterialVertical->fragmentShader = shaders::ShaderChunk::instance().get("vsm_frag"); - - shadowMaterialVertical->defines["SAMPLE_RATE"] = std::to_string(2.f / 8.f); - shadowMaterialVertical->defines["HALF_SAMPLE_RATE"] = std::to_string(1.f / 8.f); - - shadowMaterialVertical->uniforms = { - {"shadow_pass", Uniform()}, - {"resolution", Uniform(Vector2())}, - {"radius", Uniform(4.f)}}; - - return shadowMaterialVertical; - } - - - std::shared_ptr createShadowMaterialHorizontal() { - - auto horizontal = createShadowMaterialVertical(); - horizontal->defines["HORIZONTAL_PASS "] = "1"; - - return horizontal; - } - - std::shared_ptr shadowMaterialVertical = createShadowMaterialVertical(); - std::shared_ptr shadowMaterialHorizontal = createShadowMaterialHorizontal(); - }// namespace @@ -92,6 +63,7 @@ struct GLShadowMap::Impl { Impl(GLShadowMap* scope, GLObjects& objects) : scope(scope), _objects(objects), + _frustum(nullptr), _maxTextureSize(GLCapabilities::instance().maxTextureSize) { auto fullScreenTri = BufferGeometry::create(); @@ -241,7 +213,7 @@ struct GLShadowMap::Impl { object->modelViewMatrix.multiplyMatrices(shadowCamera->matrixWorldInverse, *object->matrixWorld); const auto geometry = _objects.update(object); - const auto material = object->materials(); + const auto material = object->as()->materials(); if (material.size() > 1) { @@ -384,7 +356,7 @@ struct GLShadowMap::Impl { if (auto pointLightShadow = std::dynamic_pointer_cast(shadow)) { pointLightShadow->updateMatrices(light->as(), vp); } else { - shadow->updateMatrices(light); + shadow->updateMatrices(*light); } _frustum = &shadow->getFrustum(); @@ -406,6 +378,36 @@ struct GLShadowMap::Impl { _renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel); } + +private: + static std::shared_ptr createShadowMaterialVertical() { + + auto shadowMaterialVertical = ShaderMaterial::create(); + shadowMaterialVertical->vertexShader = shaders::ShaderChunk::instance().get("vsm_vert"); + shadowMaterialVertical->fragmentShader = shaders::ShaderChunk::instance().get("vsm_frag"); + + shadowMaterialVertical->defines["SAMPLE_RATE"] = std::to_string(2.f / 8.f); + shadowMaterialVertical->defines["HALF_SAMPLE_RATE"] = std::to_string(1.f / 8.f); + + shadowMaterialVertical->uniforms = { + {"shadow_pass", Uniform()}, + {"resolution", Uniform(Vector2())}, + {"radius", Uniform(4.f)}}; + + return shadowMaterialVertical; + } + + + static std::shared_ptr createShadowMaterialHorizontal() { + + auto horizontal = createShadowMaterialVertical(); + horizontal->defines["HORIZONTAL_PASS "] = "1"; + + return horizontal; + } + + std::shared_ptr shadowMaterialVertical = createShadowMaterialVertical(); + std::shared_ptr shadowMaterialHorizontal = createShadowMaterialHorizontal(); }; GLShadowMap::GLShadowMap(GLObjects& objects) diff --git a/src/threepp/renderers/gl/GLUniforms.cpp b/src/threepp/renderers/gl/GLUniforms.cpp index 43adbf51..81e14841 100644 --- a/src/threepp/renderers/gl/GLUniforms.cpp +++ b/src/threepp/renderers/gl/GLUniforms.cpp @@ -356,6 +356,8 @@ namespace { glUniform1iv(addr, static_cast(n), units.data()); for (unsigned i = 0; i != n; ++i) { + auto value = data[i]; + if (!value) continue; textures->setTexture2D(*data[i], units[i]); } }; @@ -401,6 +403,8 @@ namespace { [&](std::vector*> arg) { for (auto& u : seq) { int index = utils::parseInt(u->id); + auto value = arg[index]; + if (!value) continue; u->setValue(*arg[index], textures); } }},