/* * Copyright (C) 2019 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 "Wireframe.h" #include "FFilamentAsset.h" #include #include #include #include #include #include #include #include #include using namespace filament; using namespace filament::math; using namespace std; using namespace utils; static const auto FREE_CALLBACK = [](void* mem, size_t, void*) { free(mem); }; namespace gltfio { struct FFilamentAsset; Wireframe::Wireframe(FFilamentAsset* asset) : mAsset(asset) { Engine* engine = mAsset->mEngine; TransformManager& tm = engine->getTransformManager(); RenderableManager& rm = engine->getRenderableManager(); // Traverse the transform hierachy and count renderables. function count; count = [&count, &tm, &rm](Entity node) { uint32_t n = rm.getInstance(node) ? 1 : 0; auto transformable = tm.getInstance(node); vector children(tm.getChildCount(transformable)); tm.getChildren(transformable, children.data(), children.size()); for (auto ce : children) { n += count(ce); } return n; }; size_t renderableCount = count(mAsset->mRoot); size_t vertCount = renderableCount * 8; size_t indCount = renderableCount * 24; float3* verts = (float3*) malloc(sizeof(float3) * vertCount); uint32_t* inds = (uint32_t*) malloc(sizeof(uint32_t) * indCount); // Traverse the hierarchy a second time to populate the vertex & index buffers. function create; float3* pvert = verts; uint32_t* pindx = inds; create = [&create, &pvert, &pindx, &rm, &tm, verts](Entity node) { auto transformable = tm.getInstance(node); auto renderable = rm.getInstance(node); if (renderable) { Box aabb = rm.getAxisAlignedBoundingBox(renderable); float3 minpt = aabb.getMin(); float3 maxpt = aabb.getMax(); mat4f worldTransform = tm.getWorldTransform(transformable); // Write coordinates for the 8 corners of the cuboid. pvert[0] = (worldTransform * float4(minpt.x, minpt.y, minpt.z, 1.0)).xyz; pvert[1] = (worldTransform * float4(minpt.x, minpt.y, maxpt.z, 1.0)).xyz; pvert[2] = (worldTransform * float4(minpt.x, maxpt.y, minpt.z, 1.0)).xyz; pvert[3] = (worldTransform * float4(minpt.x, maxpt.y, maxpt.z, 1.0)).xyz; pvert[4] = (worldTransform * float4(maxpt.x, minpt.y, minpt.z, 1.0)).xyz; pvert[5] = (worldTransform * float4(maxpt.x, minpt.y, maxpt.z, 1.0)).xyz; pvert[6] = (worldTransform * float4(maxpt.x, maxpt.y, minpt.z, 1.0)).xyz; pvert[7] = (worldTransform * float4(maxpt.x, maxpt.y, maxpt.z, 1.0)).xyz; uint32_t i = pvert - verts; pvert += 8; // Generate 4 lines around face at -X. pindx[0] = i + 0; pindx[1] = i + 1; pindx[2] = i + 1; pindx[3] = i + 3; pindx[4] = i + 3; pindx[5] = i + 2; pindx[6] = i + 2; pindx[7] = i + 0; // Generate 4 lines around face at +X. pindx[ 8] = i + 4; pindx[ 9] = i + 5; pindx[10] = i + 5; pindx[11] = i + 7; pindx[12] = i + 7; pindx[13] = i + 6; pindx[14] = i + 6; pindx[15] = i + 4; // Generate 2 horizontal lines at -Z. pindx[16] = i + 0; pindx[17] = i + 4; pindx[18] = i + 2; pindx[19] = i + 6; // Generate 2 horizontal lines at +Z. pindx[20] = i + 1; pindx[21] = i + 5; pindx[22] = i + 3; pindx[23] = i + 7; pindx += 24; } vector children(tm.getChildCount(transformable)); tm.getChildren(transformable, children.data(), children.size()); for (auto ce : children) { create(ce); } }; create(mAsset->mRoot); mVertexBuffer = VertexBuffer::Builder() .bufferCount(1) .vertexCount(vertCount) .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) .build(*engine); mIndexBuffer = IndexBuffer::Builder() .indexCount(indCount) .bufferType(IndexBuffer::IndexType::UINT) .build(*engine); mVertexBuffer->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor( verts, mVertexBuffer->getVertexCount() * sizeof(float3), FREE_CALLBACK)); mIndexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor( inds, mIndexBuffer->getIndexCount() * sizeof(uint32_t), FREE_CALLBACK)); mEntity = EntityManager::get().create(); RenderableManager::Builder(1) .culling(false) .castShadows(false) .receiveShadows(false) .geometry(0, RenderableManager::PrimitiveType::LINES, mVertexBuffer, mIndexBuffer) .build(*engine, mEntity); } Wireframe::~Wireframe() { Engine* engine = mAsset->mEngine; engine->destroy(mEntity); engine->destroy(mVertexBuffer); engine->destroy(mIndexBuffer); } } // namsepace gltfio