167 lines
5.8 KiB
C++
167 lines
5.8 KiB
C++
/*
|
|
* 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 <filament/Box.h>
|
|
#include <filament/Engine.h>
|
|
#include <filament/MaterialEnums.h>
|
|
#include <filament/RenderableManager.h>
|
|
#include <filament/TransformManager.h>
|
|
|
|
#include <utils/EntityManager.h>
|
|
|
|
#include <math/vec3.h>
|
|
#include <math/mat4.h>
|
|
|
|
#include <functional>
|
|
|
|
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<uint32_t(utils::Entity)> count;
|
|
count = [&count, &tm, &rm](Entity node) {
|
|
uint32_t n = rm.getInstance(node) ? 1 : 0;
|
|
auto transformable = tm.getInstance(node);
|
|
vector<Entity> 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<void(utils::Entity)> 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<Entity> 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
|