From 7a14aadb286640b57615426bf941e48ddf8fa774 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 23 Aug 2018 21:12:46 -0700 Subject: [PATCH] sample clean-up and new sphere object (#134) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing method to query the type of a light * IcoSphere now generates front facing triangles * Add a fairly generic sphere object to use in samples it provides an ico sphere with normal, and reuses the same vertex/index buffer for each new instance. Each instance can have its own material, size and position. currently it’s not possible to change the # of subdivisions. * FilamentApp now provides a “default” pbr material this makes it easier to create renderables for testing. * clean-up lightbulb and add spheres for each light lightbulb now has less hardcoded things and it spawns a small sphere for each light. --- .../src/main/cpp/LightManager.cpp | 7 + .../google/android/filament/LightManager.java | 7 + filament/include/filament/LightManager.h | 34 +++++ filament/src/components/LightManager.cpp | 6 + samples/CMakeLists.txt | 3 +- samples/app/Cube.cpp | 7 - samples/app/Cube.h | 2 - samples/app/FilamentApp.cpp | 9 ++ samples/app/FilamentApp.h | 2 + samples/app/IcoSphere.cpp | 8 +- samples/app/IcoSphere.h | 4 +- samples/app/Sphere.cpp | 132 ++++++++++++++++++ samples/app/Sphere.h | 67 +++++++++ samples/lightbulb.cpp | 115 ++++++++------- 14 files changed, 337 insertions(+), 66 deletions(-) create mode 100644 samples/app/Sphere.cpp create mode 100644 samples/app/Sphere.h diff --git a/android/filament-android/src/main/cpp/LightManager.cpp b/android/filament-android/src/main/cpp/LightManager.cpp index a67e0acfb9..9b07c75791 100644 --- a/android/filament-android/src/main/cpp/LightManager.cpp +++ b/android/filament-android/src/main/cpp/LightManager.cpp @@ -155,6 +155,13 @@ Java_com_google_android_filament_LightManager_nBuilderBuild(JNIEnv *env, jclass return jboolean(builder->build(*engine, (Entity &) entity) == LightManager::Builder::Success); } +extern "C" JNIEXPORT jint JNICALL +Java_com_google_android_filament_LightManager_nGetType(JNIEnv* env, + jclass type, jlong nativeLightManager, jint i) { + LightManager *lm = (LightManager *) nativeLightManager; + return (jint)lm->getType((LightManager::Instance) i); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_LightManager_nSetPosition(JNIEnv *env, jclass type, jlong nativeLightManager, jint i, jfloat x, jfloat y, jfloat z) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java index 7a8532d45d..b36f9c2ba3 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java +++ b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java @@ -172,6 +172,11 @@ public class LightManager { } } + @NonNull + public Type getType(@EntityInstance int i) { + return Type.values()[nGetType(mNativeObject, i)]; + } + public void setPosition(@EntityInstance int i, float x, float y, float z) { nSetPosition(mNativeObject, i, x, y, z); } @@ -283,6 +288,8 @@ public class LightManager { private static native void nBuilderHaloSize(long nativeBuilder, float haloSize); private static native void nBuilderHaloFalloff(long nativeBuilder, float haloFalloff); + + private static native int nGetType(long nativeLightManager, int i); private static native void nSetPosition(long nativeLightManager, int i, float x, float y, float z); private static native void nGetPosition(long nativeLightManager, int i, float[] out); private static native void nSetDirection(long nativeLightManager, int i, float x, float y, float z); diff --git a/filament/include/filament/LightManager.h b/filament/include/filament/LightManager.h index dd5e895bda..68a2d898ec 100644 --- a/filament/include/filament/LightManager.h +++ b/filament/include/filament/LightManager.h @@ -437,6 +437,40 @@ public: static constexpr float EFFICIENCY_FLUORESCENT = 0.0878f; //!< Typical efficiency of a fluorescent light bulb (8.7%) static constexpr float EFFICIENCY_LED = 0.1171f; //!< Typical efficiency of a LED light bulb (11.7%) + Type getType(Instance i) const noexcept; + + /** + * Helper function that returns if a light is a directional light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of directional light + */ + inline bool isDirectional(Instance i) const noexcept { + Type type = getType(i); + return type == Type::DIRECTIONAL || type == Type::SUN; + } + + /** + * Helper function that returns if a light is a point light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of point light + */ + inline bool isPointLight(Instance i) const noexcept { + return getType(i) == Type::POINT; + } + + /** + * Helper function that returns if a light is a spot light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of spot light + */ + inline bool isSpotLight(Instance i) const noexcept { + Type type = getType(i); + return type == Type::SPOT || type == Type::FOCUSED_SPOT; + } + /** * Dynamically updates the light's position. * diff --git a/filament/src/components/LightManager.cpp b/filament/src/components/LightManager.cpp index d9c530cbb9..ff73b1b9c9 100644 --- a/filament/src/components/LightManager.cpp +++ b/filament/src/components/LightManager.cpp @@ -22,6 +22,8 @@ #include #include +#include + using namespace math; using namespace utils; @@ -423,4 +425,8 @@ float LightManager::getSunHaloFalloff(Instance i) const noexcept { return upcast(this)->getSunHaloFalloff(i); } +LightManager::Type LightManager::getType(LightManager::Instance i) const noexcept { + return upcast(this)->getType(i); +} + } // namespace filament diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 726cdf534c..5c0030a704 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -69,7 +69,8 @@ set(APP_SRCS app/FilamentApp.cpp app/IBL.cpp app/Image.cpp - app/IcoSphere.cpp) + app/IcoSphere.cpp + app/Sphere.cpp) if (APPLE) list(APPEND APP_SRCS app/NativeWindowHelperCocoa.mm) diff --git a/samples/app/Cube.cpp b/samples/app/Cube.cpp index db4d09acc8..d058aec317 100644 --- a/samples/app/Cube.cpp +++ b/samples/app/Cube.cpp @@ -22,10 +22,7 @@ #include #include -#include - using namespace math; -using namespace filamat; using namespace filament; const uint32_t Cube::mIndices[] = { @@ -141,7 +138,3 @@ Cube::~Cube() { em.destroy(mSolidRenderable); em.destroy(mWireFrameRenderable); } - -VertexBuffer* Cube::getVertexBuffer() { - return mVertexBuffer; -} diff --git a/samples/app/Cube.h b/samples/app/Cube.h index 0572aee58c..a7a134c4d4 100644 --- a/samples/app/Cube.h +++ b/samples/app/Cube.h @@ -43,8 +43,6 @@ public: void mapFrustum(filament::Engine& engine, math::mat4 const& transform); void mapAabb(filament::Engine& engine, filament::Box const& box); - filament::VertexBuffer* getVertexBuffer(); - private: static constexpr size_t WIREFRAME_OFFSET = 3*2*6; static const uint32_t mIndices[]; diff --git a/samples/app/FilamentApp.cpp b/samples/app/FilamentApp.cpp index daaa2dcf20..96414ea433 100644 --- a/samples/app/FilamentApp.cpp +++ b/samples/app/FilamentApp.cpp @@ -49,6 +49,10 @@ using namespace filagui; using namespace math; using namespace utils; +static constexpr uint8_t AI_DEFAULT_MAT_PACKAGE[] = { + #include "generated/material/aiDefaultMat.inc" +}; + static constexpr uint8_t TRANSPARENT_COLOR_PACKAGE[] = { #include "generated/material/transparentColor.inc" }; @@ -86,6 +90,10 @@ void FilamentApp::run(const Config& config,SetupCallback setupCallback, .package((void*) TRANSPARENT_COLOR_PACKAGE, sizeof(TRANSPARENT_COLOR_PACKAGE)) .build(*mEngine); + mDefaultMaterial = Material::Builder() + .package((void*) AI_DEFAULT_MAT_PACKAGE, sizeof(AI_DEFAULT_MAT_PACKAGE)) + .build(*mEngine); + std::unique_ptr window( new FilamentApp::Window(this, config, config.title, width, height)); @@ -374,6 +382,7 @@ void FilamentApp::run(const Config& config,SetupCallback setupCallback, mIBL.reset(); mEngine->destroy(mDepthMI); mEngine->destroy(mDepthMaterial); + mEngine->destroy(mDefaultMaterial); mEngine->destroy(mTransparentMaterial); mEngine->destroy(mScene); Engine::destroy(&mEngine); diff --git a/samples/app/FilamentApp.h b/samples/app/FilamentApp.h index 8db7c0acab..21595a7adc 100644 --- a/samples/app/FilamentApp.h +++ b/samples/app/FilamentApp.h @@ -69,6 +69,7 @@ public: PostRenderCallback postRender = PostRenderCallback(), size_t width = 1024, size_t height = 640); + filament::Material const* getDefaultMaterial() const noexcept { return mDefaultMaterial; } filament::Material const* getTransparentMaterial() const noexcept { return mTransparentMaterial; } IBL* getIBL() const noexcept { return mIBL.get(); } @@ -193,6 +194,7 @@ private: bool mClosed = false; uint64_t mTime = 0; + filament::Material const* mDefaultMaterial = nullptr; filament::Material const* mTransparentMaterial = nullptr; filament::Material const* mDepthMaterial = nullptr; filament::MaterialInstance* mDepthMI = nullptr; diff --git a/samples/app/IcoSphere.cpp b/samples/app/IcoSphere.cpp index 8fa766f24f..56bdd45b81 100644 --- a/samples/app/IcoSphere.cpp +++ b/samples/app/IcoSphere.cpp @@ -29,10 +29,10 @@ const IcoSphere::VertexList IcoSphere::sVertices = { }; const IcoSphere::TriangleList IcoSphere::sTriangles = { - { 0, 4, 1 }, { 0, 9, 4 }, { 9, 5, 4 }, { 4, 5, 8 }, { 4, 8, 1 }, - { 8, 10, 1 }, { 8, 3, 10 }, { 5, 3, 8 }, { 5, 2, 3 }, { 2, 7, 3 }, - { 7, 10, 3 }, { 7, 6, 10 }, { 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 }, - { 6, 1, 10 }, { 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 }, { 7, 2, 11 } + { 1, 4, 0 }, { 4, 9, 0 }, { 4, 5, 9 }, { 8, 5, 4 }, { 1, 8, 4 }, + { 1, 10, 8 }, { 10, 3, 8 }, { 8, 3, 5 }, { 3, 2, 5 }, { 3, 7, 2 }, + { 3, 10, 7 }, { 10, 6, 7 }, { 6, 11, 7 }, { 6, 0, 11 }, { 6, 1, 0 }, + { 10, 1, 6 }, { 11, 0, 9 }, { 2, 11, 9 }, { 5, 2, 9 }, { 11, 2, 7 } }; IcoSphere::IcoSphere(size_t subdivisions) { diff --git a/samples/app/IcoSphere.h b/samples/app/IcoSphere.h index 6cbbdf6b0d..f13c1a1de6 100644 --- a/samples/app/IcoSphere.h +++ b/samples/app/IcoSphere.h @@ -37,10 +37,9 @@ public: using TriangleList = std::vector; using VertexList = std::vector; - using Lookup = std::map, Index>; using IndexedMesh = std::pair; - IcoSphere(size_t subdivisions); + explicit IcoSphere(size_t subdivisions); IndexedMesh const& getMesh() const { return mMesh; } VertexList const& getVertices() const { return mMesh.first; } @@ -50,6 +49,7 @@ private: static const IcoSphere::VertexList sVertices; static const IcoSphere::TriangleList sTriangles; + using Lookup = std::map, Index>; Index vertex_for_edge(Lookup& lookup, VertexList& vertices, Index first, Index second); TriangleList subdivide(VertexList& vertices, TriangleList const& triangles); IndexedMesh make_icosphere(int subdivisions); diff --git a/samples/app/Sphere.cpp b/samples/app/Sphere.cpp new file mode 100644 index 0000000000..e060558cf4 --- /dev/null +++ b/samples/app/Sphere.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "Sphere.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "IcoSphere.h" + +using namespace filament; +using namespace math; +using namespace utils; + + +struct Geometry { + IcoSphere sphere = IcoSphere{ 2 }; + std::vector tangents; + filament::VertexBuffer* vertexBuffer = nullptr; + filament::IndexBuffer* indexBuffer = nullptr; +}; + +// note: this will be leaked since we don't have a good time to free it. +// this should be a cache indexed on the sphere's subdivisions +static Geometry* gGeometry = nullptr; + +Sphere::Sphere(Engine& engine, Material const* material, bool culling) + : mEngine(engine) { + Geometry* geometry = gGeometry; + + static_assert(sizeof(IcoSphere::Triangle) == sizeof(IcoSphere::Index) * 3, + "indices are not packed"); + + if (geometry == nullptr) { + geometry = gGeometry = new Geometry; + + auto const& indices = geometry->sphere.getIndices(); + auto const& vertices = geometry->sphere.getVertices(); + uint32_t indexCount = (uint32_t)(indices.size() * 3); + + for (auto const& vertice : vertices) { + float3 n = vertice; + // todo produce correct u,v + float3 b = cross(n, float3{ 1, 0, 0 }); + float3 t = cross(b, n); + quatf q = mat3f::packTangentFrame({ t, b, n }); + geometry->tangents.push_back(packSnorm16(q.xyzw)); + } + + geometry->vertexBuffer = VertexBuffer::Builder() + .vertexCount((uint32_t)vertices.size()) + .bufferCount(2) + .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) + .attribute(VertexAttribute::TANGENTS, 1, VertexBuffer::AttributeType::SHORT4) + .normalized(VertexAttribute::TANGENTS) + .build(engine); + + geometry->vertexBuffer->setBufferAt(engine, 0, + VertexBuffer::BufferDescriptor(vertices.data(), vertices.size() * sizeof(float3))); + + geometry->vertexBuffer->setBufferAt(engine, 1, + VertexBuffer::BufferDescriptor(geometry->tangents.data(), geometry->tangents.size() * sizeof(math::short4))); + + + geometry->indexBuffer = IndexBuffer::Builder() + .bufferType(IndexBuffer::IndexType::USHORT) + .indexCount(indexCount) + .build(engine); + + geometry->indexBuffer->setBuffer(engine, + IndexBuffer::BufferDescriptor(indices.data(), indexCount * sizeof(IcoSphere::Index))); + } + + if (material) { + mMaterialInstance = material->createInstance(); + } + + utils::EntityManager& em = utils::EntityManager::get(); + mRenderable = em.create(); + RenderableManager::Builder(1) + .boundingBox({{0}, {1}}) + .material(0, mMaterialInstance) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, geometry->vertexBuffer, geometry->indexBuffer) + .culling(culling) + .build(engine, mRenderable); +} + +Sphere::~Sphere() { + mEngine.destroy(mMaterialInstance); + mEngine.destroy(mRenderable); + utils::EntityManager& em = utils::EntityManager::get(); + em.destroy(mRenderable); +} + +Sphere& Sphere::setPosition(math::float3 const& position) noexcept { + auto& tcm = mEngine.getTransformManager(); + auto ci = tcm.getInstance(mRenderable); + mat4f model = tcm.getTransform(ci); + model[3].xyz = position; + tcm.setTransform(ci, model); + return *this; +} + +Sphere& Sphere::setRadius(float radius) noexcept { + auto& tcm = mEngine.getTransformManager(); + auto ci = tcm.getInstance(mRenderable); + mat4f model = tcm.getTransform(ci); + model[0].x = radius; + model[1].y = radius; + model[2].z = radius; + tcm.setTransform(ci, model); + return *this; +} diff --git a/samples/app/Sphere.h b/samples/app/Sphere.h new file mode 100644 index 0000000000..b71ad5e30d --- /dev/null +++ b/samples/app/Sphere.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TNT_FILAMENT_SAMPLE_SPHERE_H +#define TNT_FILAMENT_SAMPLE_SPHERE_H + +#include +#include + +namespace filament { +class Engine; +class IndexBuffer; +class Material; +class MaterialInstance; +class VertexBuffer; +} + +class Sphere { +public: + Sphere( filament::Engine& engine, + filament::Material const* material, + bool culling = true); + ~Sphere(); + + Sphere(Sphere const&) = delete; + Sphere& operator = (Sphere const&) = delete; + + Sphere(Sphere&& rhs) noexcept + : mEngine(rhs.mEngine), + mMaterialInstance(rhs.mMaterialInstance), + mRenderable(rhs.mRenderable) { + rhs.mMaterialInstance = {}; + rhs.mRenderable = {}; + } + + utils::Entity getSolidRenderable() const { + return mRenderable; + } + + filament::MaterialInstance* getMaterialInstance() { + return mMaterialInstance; + } + + Sphere& setPosition(math::float3 const& position) noexcept; + Sphere& setRadius(float radius) noexcept; + +private: + filament::Engine& mEngine; + filament::MaterialInstance* mMaterialInstance = nullptr; + utils::Entity mRenderable; + +}; + +#endif //TNT_FILAMENT_SAMPLE_SPHERE_H diff --git a/samples/lightbulb.cpp b/samples/lightbulb.cpp index 01d822f019..7b919ea512 100644 --- a/samples/lightbulb.cpp +++ b/samples/lightbulb.cpp @@ -38,6 +38,7 @@ #include "app/MeshAssimp.h" #include "app/Cube.h" #include "app/IcoSphere.h" +#include "app/Sphere.h" using namespace math; using namespace filament; @@ -53,15 +54,11 @@ static std::vector g_filenames; std::map g_materialLibrary; std::unique_ptr g_meshSet; std::unique_ptr g_meshAabb; -static Entity g_light; -// optional lights -static Entity g_light1; -static Entity g_light2; -static Entity g_light3; -static Entity g_light4; -static Entity g_light5; + +static std::vector g_spheres; +static std::vector g_lights; + static Entity g_discoBallEntity; -static std::vector g_discoBallLights; static float g_discoAngle = 0; static float g_discoAngularSpeed = 0.25f * float(M_PI); // rad/s @@ -70,6 +67,7 @@ static bool g_moreLights = false; static bool g_shadowPlane = false; static bool g_discoBall = false; + static void printUsage(char* name) { std::string exec_name(Path(name).getName()); std::string usage( @@ -175,22 +173,9 @@ static void cleanup(Engine* engine, View* view, Scene* scene) { auto& em = EntityManager::get(); - engine->destroy(g_light); - em.destroy(g_light); - if (g_moreLights) { - engine->destroy(g_light1); - engine->destroy(g_light2); - engine->destroy(g_light3); - engine->destroy(g_light4); - engine->destroy(g_light5); - em.destroy(g_light1); - em.destroy(g_light2); - em.destroy(g_light3); - em.destroy(g_light4); - em.destroy(g_light5); - } + g_spheres.clear(); - for (Entity e : g_discoBallLights) { + for (Entity e : g_lights) { engine->destroy(e); em.destroy(e); } @@ -226,7 +211,7 @@ static void setup(Engine* engine, View* view, Scene* scene) { } auto& em = EntityManager::get(); - g_light = em.create(); + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::SUN) .color(Color::toLinear(sRGBColor(0.98f, 0.92f, 0.89f))) @@ -234,22 +219,22 @@ static void setup(Engine* engine, View* view, Scene* scene) { .direction({ 0.7, -1, -0.8 }) .sunAngularRadius(1.9f) .castShadows(true) - .build(*engine, g_light); - scene->addEntity(g_light); + .build(*engine, g_lights.back()); + scene->addEntity(g_lights.back()); if (g_moreLights) { - g_light1 = em.create(); - g_light2 = em.create(); - g_light3 = em.create(); - g_light4 = em.create(); - g_light5 = em.create(); + auto& lcm = engine->getLightManager(); + + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::POINT) .color(Color::toLinear(sRGBColor(0.98f, 0.92f, 0.89f))) .intensity(1000.0f, LightManager::EFFICIENCY_LED) .position({ 0.0f, -0.2f, -3.0f }) .falloff(4.0f) - .build(*engine, g_light1); + .build(*engine, g_lights.back()); + + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::FOCUSED_SPOT) .color(Color::toLinear(sRGBColor(0.98f, 0.12f, 0.19f))) .intensity(2000.0f, LightManager::EFFICIENCY_LED) @@ -257,62 +242,92 @@ static void setup(Engine* engine, View* view, Scene* scene) { .direction({ -1.0f, 0.0f, 0.0f }) .spotLightCone(static_cast(M_PI / 8), static_cast((M_PI / 8) * 1.1)) .falloff(4.0f) - .build(*engine, g_light2); + .build(*engine, g_lights.back()); + + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::POINT) .color(Color::toLinear(sRGBColor(0.18f, 0.12f, 0.89f))) .intensity(1000.0f, LightManager::EFFICIENCY_LED) - .position({ -0.6f, 0.6f, -3.2f }) + .position({ -0.6f, 0.3f, -3.2f }) .falloff(2.0f) - .build(*engine, g_light3); + .build(*engine, g_lights.back()); + + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::POINT) .color(Color::toLinear(sRGBColor(0.88f, 0.82f, 0.29f))) .intensity(1000.0f, LightManager::EFFICIENCY_LED) .position({ 0.0f, 1.5f, -3.5f }) .falloff(2.0f) - .build(*engine, g_light4); + .build(*engine, g_lights.back()); + + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::FOCUSED_SPOT) .color(Color::toLinear(sRGBColor(0.12f, 0.98f, 0.19f))) .intensity(2000.0f, LightManager::EFFICIENCY_LED) - .position({ 0.6f, 0.6f, -3.2f }) + .position({ 0.0f, 0.6f, -3.2f }) .direction({ 1.0f, 0.0f, 0.0f }) .spotLightCone(static_cast(M_PI / 8), static_cast((M_PI / 8) * 1.1)) .falloff(4.0f) - .build(*engine, g_light5); + .build(*engine, g_lights.back()); - scene->addEntity(g_light1); - scene->addEntity(g_light2); - scene->addEntity(g_light3); - scene->addEntity(g_light4); - scene->addEntity(g_light5); + for (const auto& light : g_lights) { + scene->addEntity(light); + const LightManager::Instance& instance = lcm.getInstance(light); + if (!lcm.isDirectional(instance)) { + g_spheres.emplace_back(*engine, FilamentApp::get().getDefaultMaterial()); + g_spheres.back() + .setRadius(0.025f) + .setPosition(lcm.getPosition(instance)); + + auto mi = g_spheres.back().getMaterialInstance(); + mi->setParameter("baseColor", RgbaType::LINEAR, LinearColorA{ lcm.getColor(instance), 1.0f }); + mi->setParameter("roughness", 0.2f); + mi->setParameter("metallic", 0.0f); + } + } + + for (const auto& sphere : g_spheres) { + scene->addEntity(sphere.getSolidRenderable()); + } } if (g_discoBall) { IcoSphere sphere(2); auto const& vertices = sphere.getVertices(); - g_discoBallLights.resize(vertices.size()); - auto n = g_discoBallLights.size(); + auto n = vertices.size(); + g_lights.resize(g_lights.size() + n); slog.d << "light count = " << n << io::endl; - em.create(n, g_discoBallLights.data()); Entity discoBall = em.create(); tcm.create(discoBall, {}, mat4f::translate(float4{ 0, 3, -14, 1 })); auto parent = tcm.getInstance(discoBall); for (size_t i = 0, c = n; i < c; i++) { + g_lights.push_back(em.create()); LightManager::Builder(LightManager::Type::FOCUSED_SPOT) .color(abs(vertices[i])) .intensity(1000.0f, LightManager::EFFICIENCY_HALOGEN) .direction(vertices[i]) .spotLightCone(0.0174f * 0.5f, 0.0174f * 2.0f) .falloff(20.0f) - .build(*engine, g_discoBallLights[i]); + .build(*engine, g_lights.back()); - tcm.create(g_discoBallLights[i], parent, {}); + tcm.create(g_lights.back(), parent, {}); - scene->addEntity(g_discoBallLights[i]); + scene->addEntity(g_lights.back()); } g_discoBallEntity = discoBall; - } + + g_spheres.emplace_back(*engine, FilamentApp::get().getDefaultMaterial()); + g_spheres.back().setRadius(0.2f); + auto mi = g_spheres.back().getMaterialInstance(); + mi->setParameter("baseColor", RgbaType::LINEAR, LinearColorA{ 1, 1, 1, 1 }); + mi->setParameter("roughness", 0.01f); + mi->setParameter("metallic", 1.0f); + scene->addEntity(g_spheres.back().getSolidRenderable()); + // parent the sphere representing the disco ball to the discoball transform -- w00t. + tcm.setParent(tcm.getInstance(g_spheres.back().getSolidRenderable()), tcm.getInstance(discoBall)); + } g_meshAabb.reset(new Cube(*engine, FilamentApp::get().getTransparentMaterial(), {0,0,1}));