mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 19:22:57 +02:00
Moving shape definition to a shared location
This commit is contained in:
parent
cb40cfbead
commit
2c02c963d4
4 changed files with 284 additions and 230 deletions
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <FSTReader.h>
|
#include <FSTReader.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
#include <shared/Shapes.h>
|
||||||
|
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "RenderUtilsLogging.h"
|
#include "RenderUtilsLogging.h"
|
||||||
|
@ -54,7 +55,7 @@ static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
||||||
static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT32;
|
static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT32;
|
||||||
static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint32);
|
static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint32);
|
||||||
|
|
||||||
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const VertexVector& vertices) {
|
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) {
|
||||||
vertexBuffer->append(vertices);
|
vertexBuffer->append(vertices);
|
||||||
|
|
||||||
_positionView = gpu::BufferView(vertexBuffer, 0,
|
_positionView = gpu::BufferView(vertexBuffer, 0,
|
||||||
|
@ -63,7 +64,7 @@ void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, c
|
||||||
vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const IndexVector& indices, const IndexVector& wireIndices) {
|
void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) {
|
||||||
_indices = indexBuffer;
|
_indices = indexBuffer;
|
||||||
if (!indices.empty()) {
|
if (!indices.empty()) {
|
||||||
_indexOffset = indexBuffer->getSize() / SHAPE_INDEX_SIZE;
|
_indexOffset = indexBuffer->getSize() / SHAPE_INDEX_SIZE;
|
||||||
|
@ -126,90 +127,19 @@ size_t GeometryCache::getCubeTriangleCount() {
|
||||||
return getShapeTriangleCount(Cube);
|
return getShapeTriangleCount(Cube);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Index = uint32_t;
|
|
||||||
using IndexPair = uint64_t;
|
using IndexPair = uint64_t;
|
||||||
using IndexPairs = std::unordered_set<IndexPair>;
|
using IndexPairs = std::unordered_set<IndexPair>;
|
||||||
|
|
||||||
template <size_t N>
|
static IndexPair indexToken(geometry::Index a, geometry::Index b) {
|
||||||
using Face = std::array<Index, N>;
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
using FaceVector = std::vector<Face<N>>;
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
struct Solid {
|
|
||||||
VertexVector vertices;
|
|
||||||
FaceVector<N> faces;
|
|
||||||
|
|
||||||
Solid<N>& fitDimension(float newMaxDimension) {
|
|
||||||
float maxDimension = 0;
|
|
||||||
for (const auto& vertex : vertices) {
|
|
||||||
maxDimension = std::max(maxDimension, std::max(std::max(vertex.x, vertex.y), vertex.z));
|
|
||||||
}
|
|
||||||
float multiplier = newMaxDimension / maxDimension;
|
|
||||||
for (auto& vertex : vertices) {
|
|
||||||
vertex *= multiplier;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 getFaceNormal(size_t faceIndex) const {
|
|
||||||
vec3 result;
|
|
||||||
const auto& face = faces[faceIndex];
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
result += vertices[face[i]];
|
|
||||||
}
|
|
||||||
result /= N;
|
|
||||||
return glm::normalize(result);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
static size_t triangulatedFaceTriangleCount() {
|
|
||||||
return N - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
static size_t triangulatedFaceIndexCount() {
|
|
||||||
return triangulatedFaceTriangleCount<N>() * VERTICES_PER_TRIANGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IndexPair indexToken(Index a, Index b) {
|
|
||||||
if (a > b) {
|
if (a > b) {
|
||||||
std::swap(a, b);
|
std::swap(a, b);
|
||||||
}
|
}
|
||||||
return (((IndexPair)a) << 32) | ((IndexPair)b);
|
return (((IndexPair)a) << 32) | ((IndexPair)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Solid<3> tesselate(Solid<3> solid, int count) {
|
|
||||||
float length = glm::length(solid.vertices[0]);
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
Solid<3> result { solid.vertices, {} };
|
|
||||||
result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 3);
|
|
||||||
for (size_t f = 0; f < solid.faces.size(); ++f) {
|
|
||||||
Index baseVertex = (Index)result.vertices.size();
|
|
||||||
const Face<3>& oldFace = solid.faces[f];
|
|
||||||
const vec3& a = solid.vertices[oldFace[0]];
|
|
||||||
const vec3& b = solid.vertices[oldFace[1]];
|
|
||||||
const vec3& c = solid.vertices[oldFace[2]];
|
|
||||||
vec3 ab = glm::normalize(a + b) * length;
|
|
||||||
vec3 bc = glm::normalize(b + c) * length;
|
|
||||||
vec3 ca = glm::normalize(c + a) * length;
|
|
||||||
result.vertices.push_back(ab);
|
|
||||||
result.vertices.push_back(bc);
|
|
||||||
result.vertices.push_back(ca);
|
|
||||||
result.faces.push_back(Face<3>{ { oldFace[0], baseVertex, baseVertex + 2 } });
|
|
||||||
result.faces.push_back(Face<3>{ { baseVertex, oldFace[1], baseVertex + 1 } });
|
|
||||||
result.faces.push_back(Face<3>{ { baseVertex + 1, oldFace[2], baseVertex + 2 } });
|
|
||||||
result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } });
|
|
||||||
}
|
|
||||||
solid = result;
|
|
||||||
}
|
|
||||||
return solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void setupFlatShape(GeometryCache::ShapeData& shapeData, const Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||||
|
using namespace geometry;
|
||||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||||
VertexVector vertices;
|
VertexVector vertices;
|
||||||
IndexVector solidIndices, wireIndices;
|
IndexVector solidIndices, wireIndices;
|
||||||
|
@ -259,7 +189,8 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const Solid<N>& shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void setupSmoothShape(GeometryCache::ShapeData& shapeData, const Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||||
|
using namespace geometry;
|
||||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||||
|
|
||||||
VertexVector vertices;
|
VertexVector vertices;
|
||||||
|
@ -303,147 +234,6 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const Solid<N>& shape
|
||||||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The golden ratio
|
|
||||||
static const float PHI = 1.61803398874f;
|
|
||||||
|
|
||||||
static const Solid<3>& tetrahedron() {
|
|
||||||
static const auto A = vec3(1, 1, 1);
|
|
||||||
static const auto B = vec3(1, -1, -1);
|
|
||||||
static const auto C = vec3(-1, 1, -1);
|
|
||||||
static const auto D = vec3(-1, -1, 1);
|
|
||||||
static const Solid<3> TETRAHEDRON = Solid<3>{
|
|
||||||
{ A, B, C, D },
|
|
||||||
FaceVector<3>{
|
|
||||||
Face<3> { { 0, 1, 2 } },
|
|
||||||
Face<3> { { 3, 1, 0 } },
|
|
||||||
Face<3> { { 2, 3, 0 } },
|
|
||||||
Face<3> { { 2, 1, 3 } },
|
|
||||||
}
|
|
||||||
}.fitDimension(0.5f);
|
|
||||||
return TETRAHEDRON;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Solid<4>& cube() {
|
|
||||||
static const auto A = vec3(1, 1, 1);
|
|
||||||
static const auto B = vec3(-1, 1, 1);
|
|
||||||
static const auto C = vec3(-1, 1, -1);
|
|
||||||
static const auto D = vec3(1, 1, -1);
|
|
||||||
static const Solid<4> CUBE = Solid<4>{
|
|
||||||
{ A, B, C, D, -A, -B, -C, -D },
|
|
||||||
FaceVector<4>{
|
|
||||||
Face<4> { { 3, 2, 1, 0 } },
|
|
||||||
Face<4> { { 0, 1, 7, 6 } },
|
|
||||||
Face<4> { { 1, 2, 4, 7 } },
|
|
||||||
Face<4> { { 2, 3, 5, 4 } },
|
|
||||||
Face<4> { { 3, 0, 6, 5 } },
|
|
||||||
Face<4> { { 4, 5, 6, 7 } },
|
|
||||||
}
|
|
||||||
}.fitDimension(0.5f);
|
|
||||||
return CUBE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Solid<3>& octahedron() {
|
|
||||||
static const auto A = vec3(0, 1, 0);
|
|
||||||
static const auto B = vec3(0, -1, 0);
|
|
||||||
static const auto C = vec3(0, 0, 1);
|
|
||||||
static const auto D = vec3(0, 0, -1);
|
|
||||||
static const auto E = vec3(1, 0, 0);
|
|
||||||
static const auto F = vec3(-1, 0, 0);
|
|
||||||
static const Solid<3> OCTAHEDRON = Solid<3>{
|
|
||||||
{ A, B, C, D, E, F},
|
|
||||||
FaceVector<3> {
|
|
||||||
Face<3> { { 0, 2, 4, } },
|
|
||||||
Face<3> { { 0, 4, 3, } },
|
|
||||||
Face<3> { { 0, 3, 5, } },
|
|
||||||
Face<3> { { 0, 5, 2, } },
|
|
||||||
Face<3> { { 1, 4, 2, } },
|
|
||||||
Face<3> { { 1, 3, 4, } },
|
|
||||||
Face<3> { { 1, 5, 3, } },
|
|
||||||
Face<3> { { 1, 2, 5, } },
|
|
||||||
}
|
|
||||||
}.fitDimension(0.5f);
|
|
||||||
return OCTAHEDRON;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Solid<5>& dodecahedron() {
|
|
||||||
static const float P = PHI;
|
|
||||||
static const float IP = 1.0f / PHI;
|
|
||||||
static const vec3 A = vec3(IP, P, 0);
|
|
||||||
static const vec3 B = vec3(-IP, P, 0);
|
|
||||||
static const vec3 C = vec3(-1, 1, 1);
|
|
||||||
static const vec3 D = vec3(0, IP, P);
|
|
||||||
static const vec3 E = vec3(1, 1, 1);
|
|
||||||
static const vec3 F = vec3(1, 1, -1);
|
|
||||||
static const vec3 G = vec3(-1, 1, -1);
|
|
||||||
static const vec3 H = vec3(-P, 0, IP);
|
|
||||||
static const vec3 I = vec3(0, -IP, P);
|
|
||||||
static const vec3 J = vec3(P, 0, IP);
|
|
||||||
|
|
||||||
static const Solid<5> DODECAHEDRON = Solid<5>{
|
|
||||||
{
|
|
||||||
A, B, C, D, E, F, G, H, I, J,
|
|
||||||
-A, -B, -C, -D, -E, -F, -G, -H, -I, -J,
|
|
||||||
},
|
|
||||||
FaceVector<5> {
|
|
||||||
Face<5> { { 0, 1, 2, 3, 4 } },
|
|
||||||
Face<5> { { 0, 5, 18, 6, 1 } },
|
|
||||||
Face<5> { { 1, 6, 19, 7, 2 } },
|
|
||||||
Face<5> { { 2, 7, 15, 8, 3 } },
|
|
||||||
Face<5> { { 3, 8, 16, 9, 4 } },
|
|
||||||
Face<5> { { 4, 9, 17, 5, 0 } },
|
|
||||||
Face<5> { { 14, 13, 12, 11, 10 } },
|
|
||||||
Face<5> { { 11, 16, 8, 15, 10 } },
|
|
||||||
Face<5> { { 12, 17, 9, 16, 11 } },
|
|
||||||
Face<5> { { 13, 18, 5, 17, 12 } },
|
|
||||||
Face<5> { { 14, 19, 6, 18, 13 } },
|
|
||||||
Face<5> { { 10, 15, 7, 19, 14 } },
|
|
||||||
}
|
|
||||||
}.fitDimension(0.5f);
|
|
||||||
return DODECAHEDRON;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Solid<3>& icosahedron() {
|
|
||||||
static const float N = 1.0f / PHI;
|
|
||||||
static const float P = 1.0f;
|
|
||||||
static const auto A = vec3(N, P, 0);
|
|
||||||
static const auto B = vec3(-N, P, 0);
|
|
||||||
static const auto C = vec3(0, N, P);
|
|
||||||
static const auto D = vec3(P, 0, N);
|
|
||||||
static const auto E = vec3(P, 0, -N);
|
|
||||||
static const auto F = vec3(0, N, -P);
|
|
||||||
|
|
||||||
static const Solid<3> ICOSAHEDRON = Solid<3> {
|
|
||||||
{
|
|
||||||
A, B, C, D, E, F,
|
|
||||||
-A, -B, -C, -D, -E, -F,
|
|
||||||
},
|
|
||||||
FaceVector<3> {
|
|
||||||
Face<3> { { 1, 2, 0 } },
|
|
||||||
Face<3> { { 2, 3, 0 } },
|
|
||||||
Face<3> { { 3, 4, 0 } },
|
|
||||||
Face<3> { { 4, 5, 0 } },
|
|
||||||
Face<3> { { 5, 1, 0 } },
|
|
||||||
|
|
||||||
Face<3> { { 1, 10, 2 } },
|
|
||||||
Face<3> { { 11, 2, 10 } },
|
|
||||||
Face<3> { { 2, 11, 3 } },
|
|
||||||
Face<3> { { 7, 3, 11 } },
|
|
||||||
Face<3> { { 3, 7, 4 } },
|
|
||||||
Face<3> { { 8, 4, 7 } },
|
|
||||||
Face<3> { { 4, 8, 5 } },
|
|
||||||
Face<3> { { 9, 5, 8 } },
|
|
||||||
Face<3> { { 5, 9, 1 } },
|
|
||||||
Face<3> { { 10, 1, 9 } },
|
|
||||||
|
|
||||||
Face<3> { { 8, 7, 6 } },
|
|
||||||
Face<3> { { 9, 8, 6 } },
|
|
||||||
Face<3> { { 10, 9, 6 } },
|
|
||||||
Face<3> { { 11, 10, 6 } },
|
|
||||||
Face<3> { { 7, 11, 6 } },
|
|
||||||
}
|
|
||||||
}.fitDimension(0.5f);
|
|
||||||
return ICOSAHEDRON;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME solids need per-face vertices, but smooth shaded
|
// FIXME solids need per-face vertices, but smooth shaded
|
||||||
// components do not. Find a way to support using draw elements
|
// components do not. Find a way to support using draw elements
|
||||||
|
@ -451,24 +241,24 @@ static const Solid<3>& icosahedron() {
|
||||||
// Maybe special case cone and cylinder since they combine flat
|
// Maybe special case cone and cylinder since they combine flat
|
||||||
// and smooth shading
|
// and smooth shading
|
||||||
void GeometryCache::buildShapes() {
|
void GeometryCache::buildShapes() {
|
||||||
|
using namespace geometry;
|
||||||
auto vertexBuffer = std::make_shared<gpu::Buffer>();
|
auto vertexBuffer = std::make_shared<gpu::Buffer>();
|
||||||
auto indexBuffer = std::make_shared<gpu::Buffer>();
|
auto indexBuffer = std::make_shared<gpu::Buffer>();
|
||||||
// Cube
|
// Cube
|
||||||
setupFlatShape(_shapes[Cube], cube(), _shapeVertices, _shapeIndices);
|
setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices);
|
||||||
// Tetrahedron
|
// Tetrahedron
|
||||||
setupFlatShape(_shapes[Tetrahedron], tetrahedron(), _shapeVertices, _shapeIndices);
|
setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices);
|
||||||
// Icosahedron
|
// Icosahedron
|
||||||
setupFlatShape(_shapes[Icosahedron], icosahedron(), _shapeVertices, _shapeIndices);
|
setupFlatShape(_shapes[Icosahedron], geometry::icosahedron(), _shapeVertices, _shapeIndices);
|
||||||
// Octahedron
|
// Octahedron
|
||||||
setupFlatShape(_shapes[Octahedron], octahedron(), _shapeVertices, _shapeIndices);
|
setupFlatShape(_shapes[Octahedron], geometry::octahedron(), _shapeVertices, _shapeIndices);
|
||||||
// Dodecahedron
|
// Dodecahedron
|
||||||
setupFlatShape(_shapes[Dodecahedron], dodecahedron(), _shapeVertices, _shapeIndices);
|
setupFlatShape(_shapes[Dodecahedron], geometry::dodecahedron(), _shapeVertices, _shapeIndices);
|
||||||
|
|
||||||
// Sphere
|
// Sphere
|
||||||
// FIXME this uses way more vertices than required. Should find a way to calculate the indices
|
// FIXME this uses way more vertices than required. Should find a way to calculate the indices
|
||||||
// using shared vertices for better vertex caching
|
// using shared vertices for better vertex caching
|
||||||
Solid<3> sphere = icosahedron();
|
auto sphere = geometry::tesselate(geometry::icosahedron(), ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT);
|
||||||
sphere = tesselate(sphere, ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT);
|
|
||||||
sphere.fitDimension(1.0f);
|
sphere.fitDimension(1.0f);
|
||||||
setupSmoothShape(_shapes[Sphere], sphere, _shapeVertices, _shapeIndices);
|
setupSmoothShape(_shapes[Sphere], sphere, _shapeVertices, _shapeIndices);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
|
#include <shared/Shapes.h>
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <gpu/Stream.h>
|
#include <gpu/Stream.h>
|
||||||
|
|
||||||
|
@ -121,9 +123,6 @@ inline uint qHash(const Vec4PairVec4Pair& v, uint seed) {
|
||||||
seed);
|
seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
using IndexVector = std::vector<uint32_t>;
|
|
||||||
using VertexVector = std::vector<glm::vec3>;
|
|
||||||
|
|
||||||
/// Stores cached geometry.
|
/// Stores cached geometry.
|
||||||
class GeometryCache : public Dependency {
|
class GeometryCache : public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
@ -297,8 +296,8 @@ public:
|
||||||
gpu::BufferView _normalView;
|
gpu::BufferView _normalView;
|
||||||
gpu::BufferPointer _indices;
|
gpu::BufferPointer _indices;
|
||||||
|
|
||||||
void setupVertices(gpu::BufferPointer& vertexBuffer, const VertexVector& vertices);
|
void setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices);
|
||||||
void setupIndices(gpu::BufferPointer& indexBuffer, const IndexVector& indices, const IndexVector& wireIndices);
|
void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices);
|
||||||
void setupBatch(gpu::Batch& batch) const;
|
void setupBatch(gpu::Batch& batch) const;
|
||||||
void draw(gpu::Batch& batch) const;
|
void draw(gpu::Batch& batch) const;
|
||||||
void drawWire(gpu::Batch& batch) const;
|
void drawWire(gpu::Batch& batch) const;
|
||||||
|
|
186
libraries/shared/src/shared/Shapes.cpp
Normal file
186
libraries/shared/src/shared/Shapes.cpp
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/26
|
||||||
|
// Copyright 2013-2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Shapes.h"
|
||||||
|
|
||||||
|
namespace geometry {
|
||||||
|
|
||||||
|
using glm::vec3;
|
||||||
|
|
||||||
|
// The golden ratio
|
||||||
|
static const float PHI = 1.61803398874f;
|
||||||
|
|
||||||
|
Solid<3> tesselate(const Solid<3>& solid_, int count) {
|
||||||
|
Solid<3> solid = solid_;
|
||||||
|
float length = glm::length(solid.vertices[0]);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
Solid<3> result { solid.vertices, {} };
|
||||||
|
result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 3);
|
||||||
|
for (size_t f = 0; f < solid.faces.size(); ++f) {
|
||||||
|
Index baseVertex = (Index)result.vertices.size();
|
||||||
|
const Face<3>& oldFace = solid.faces[f];
|
||||||
|
const vec3& a = solid.vertices[oldFace[0]];
|
||||||
|
const vec3& b = solid.vertices[oldFace[1]];
|
||||||
|
const vec3& c = solid.vertices[oldFace[2]];
|
||||||
|
vec3 ab = glm::normalize(a + b) * length;
|
||||||
|
vec3 bc = glm::normalize(b + c) * length;
|
||||||
|
vec3 ca = glm::normalize(c + a) * length;
|
||||||
|
result.vertices.push_back(ab);
|
||||||
|
result.vertices.push_back(bc);
|
||||||
|
result.vertices.push_back(ca);
|
||||||
|
result.faces.push_back(Face<3>{ { oldFace[0], baseVertex, baseVertex + 2 } });
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex, oldFace[1], baseVertex + 1 } });
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex + 1, oldFace[2], baseVertex + 2 } });
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } });
|
||||||
|
}
|
||||||
|
solid = result;
|
||||||
|
}
|
||||||
|
return solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Solid<3>& tetrahedron() {
|
||||||
|
static const auto A = vec3(1, 1, 1);
|
||||||
|
static const auto B = vec3(1, -1, -1);
|
||||||
|
static const auto C = vec3(-1, 1, -1);
|
||||||
|
static const auto D = vec3(-1, -1, 1);
|
||||||
|
static const Solid<3> TETRAHEDRON = Solid<3>{
|
||||||
|
{ A, B, C, D },
|
||||||
|
FaceVector<3>{
|
||||||
|
Face<3> { { 0, 1, 2 } },
|
||||||
|
Face<3> { { 3, 1, 0 } },
|
||||||
|
Face<3> { { 2, 3, 0 } },
|
||||||
|
Face<3> { { 2, 1, 3 } },
|
||||||
|
}
|
||||||
|
}.fitDimension(0.5f);
|
||||||
|
return TETRAHEDRON;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Solid<4>& cube() {
|
||||||
|
static const auto A = vec3(1, 1, 1);
|
||||||
|
static const auto B = vec3(-1, 1, 1);
|
||||||
|
static const auto C = vec3(-1, 1, -1);
|
||||||
|
static const auto D = vec3(1, 1, -1);
|
||||||
|
static const Solid<4> CUBE = Solid<4>{
|
||||||
|
{ A, B, C, D, -A, -B, -C, -D },
|
||||||
|
FaceVector<4>{
|
||||||
|
Face<4> { { 3, 2, 1, 0 } },
|
||||||
|
Face<4> { { 0, 1, 7, 6 } },
|
||||||
|
Face<4> { { 1, 2, 4, 7 } },
|
||||||
|
Face<4> { { 2, 3, 5, 4 } },
|
||||||
|
Face<4> { { 3, 0, 6, 5 } },
|
||||||
|
Face<4> { { 4, 5, 6, 7 } },
|
||||||
|
}
|
||||||
|
}.fitDimension(0.5f);
|
||||||
|
return CUBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Solid<3>& octahedron() {
|
||||||
|
static const auto A = vec3(0, 1, 0);
|
||||||
|
static const auto B = vec3(0, -1, 0);
|
||||||
|
static const auto C = vec3(0, 0, 1);
|
||||||
|
static const auto D = vec3(0, 0, -1);
|
||||||
|
static const auto E = vec3(1, 0, 0);
|
||||||
|
static const auto F = vec3(-1, 0, 0);
|
||||||
|
static const Solid<3> OCTAHEDRON = Solid<3>{
|
||||||
|
{ A, B, C, D, E, F},
|
||||||
|
FaceVector<3> {
|
||||||
|
Face<3> { { 0, 2, 4, } },
|
||||||
|
Face<3> { { 0, 4, 3, } },
|
||||||
|
Face<3> { { 0, 3, 5, } },
|
||||||
|
Face<3> { { 0, 5, 2, } },
|
||||||
|
Face<3> { { 1, 4, 2, } },
|
||||||
|
Face<3> { { 1, 3, 4, } },
|
||||||
|
Face<3> { { 1, 5, 3, } },
|
||||||
|
Face<3> { { 1, 2, 5, } },
|
||||||
|
}
|
||||||
|
}.fitDimension(0.5f);
|
||||||
|
return OCTAHEDRON;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Solid<5>& dodecahedron() {
|
||||||
|
static const float P = PHI;
|
||||||
|
static const float IP = 1.0f / PHI;
|
||||||
|
static const vec3 A = vec3(IP, P, 0);
|
||||||
|
static const vec3 B = vec3(-IP, P, 0);
|
||||||
|
static const vec3 C = vec3(-1, 1, 1);
|
||||||
|
static const vec3 D = vec3(0, IP, P);
|
||||||
|
static const vec3 E = vec3(1, 1, 1);
|
||||||
|
static const vec3 F = vec3(1, 1, -1);
|
||||||
|
static const vec3 G = vec3(-1, 1, -1);
|
||||||
|
static const vec3 H = vec3(-P, 0, IP);
|
||||||
|
static const vec3 I = vec3(0, -IP, P);
|
||||||
|
static const vec3 J = vec3(P, 0, IP);
|
||||||
|
|
||||||
|
static const Solid<5> DODECAHEDRON = Solid<5>{
|
||||||
|
{
|
||||||
|
A, B, C, D, E, F, G, H, I, J,
|
||||||
|
-A, -B, -C, -D, -E, -F, -G, -H, -I, -J,
|
||||||
|
},
|
||||||
|
FaceVector<5> {
|
||||||
|
Face<5> { { 0, 1, 2, 3, 4 } },
|
||||||
|
Face<5> { { 0, 5, 18, 6, 1 } },
|
||||||
|
Face<5> { { 1, 6, 19, 7, 2 } },
|
||||||
|
Face<5> { { 2, 7, 15, 8, 3 } },
|
||||||
|
Face<5> { { 3, 8, 16, 9, 4 } },
|
||||||
|
Face<5> { { 4, 9, 17, 5, 0 } },
|
||||||
|
Face<5> { { 14, 13, 12, 11, 10 } },
|
||||||
|
Face<5> { { 11, 16, 8, 15, 10 } },
|
||||||
|
Face<5> { { 12, 17, 9, 16, 11 } },
|
||||||
|
Face<5> { { 13, 18, 5, 17, 12 } },
|
||||||
|
Face<5> { { 14, 19, 6, 18, 13 } },
|
||||||
|
Face<5> { { 10, 15, 7, 19, 14 } },
|
||||||
|
}
|
||||||
|
}.fitDimension(0.5f);
|
||||||
|
return DODECAHEDRON;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Solid<3>& icosahedron() {
|
||||||
|
static const float N = 1.0f / PHI;
|
||||||
|
static const float P = 1.0f;
|
||||||
|
static const auto A = vec3(N, P, 0);
|
||||||
|
static const auto B = vec3(-N, P, 0);
|
||||||
|
static const auto C = vec3(0, N, P);
|
||||||
|
static const auto D = vec3(P, 0, N);
|
||||||
|
static const auto E = vec3(P, 0, -N);
|
||||||
|
static const auto F = vec3(0, N, -P);
|
||||||
|
|
||||||
|
static const Solid<3> ICOSAHEDRON = Solid<3> {
|
||||||
|
{
|
||||||
|
A, B, C, D, E, F,
|
||||||
|
-A, -B, -C, -D, -E, -F,
|
||||||
|
},
|
||||||
|
FaceVector<3> {
|
||||||
|
Face<3> { { 1, 2, 0 } },
|
||||||
|
Face<3> { { 2, 3, 0 } },
|
||||||
|
Face<3> { { 3, 4, 0 } },
|
||||||
|
Face<3> { { 4, 5, 0 } },
|
||||||
|
Face<3> { { 5, 1, 0 } },
|
||||||
|
|
||||||
|
Face<3> { { 1, 10, 2 } },
|
||||||
|
Face<3> { { 11, 2, 10 } },
|
||||||
|
Face<3> { { 2, 11, 3 } },
|
||||||
|
Face<3> { { 7, 3, 11 } },
|
||||||
|
Face<3> { { 3, 7, 4 } },
|
||||||
|
Face<3> { { 8, 4, 7 } },
|
||||||
|
Face<3> { { 4, 8, 5 } },
|
||||||
|
Face<3> { { 9, 5, 8 } },
|
||||||
|
Face<3> { { 5, 9, 1 } },
|
||||||
|
Face<3> { { 10, 1, 9 } },
|
||||||
|
|
||||||
|
Face<3> { { 8, 7, 6 } },
|
||||||
|
Face<3> { { 9, 8, 6 } },
|
||||||
|
Face<3> { { 10, 9, 6 } },
|
||||||
|
Face<3> { { 11, 10, 6 } },
|
||||||
|
Face<3> { { 7, 11, 6 } },
|
||||||
|
}
|
||||||
|
}.fitDimension(0.5f);
|
||||||
|
return ICOSAHEDRON;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
79
libraries/shared/src/shared/Shapes.h
Normal file
79
libraries/shared/src/shared/Shapes.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/26
|
||||||
|
// Copyright 2013-2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef hifi_shared_shapes
|
||||||
|
#define hifi_shared_shapes
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace geometry {
|
||||||
|
|
||||||
|
using Index = uint32_t;
|
||||||
|
using Vec = glm::vec3;
|
||||||
|
using VertexVector = std::vector<Vec>;
|
||||||
|
using IndexVector = std::vector<Index>;
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
using Face = std::array<Index, N>;
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
using FaceVector = std::vector<Face<N>>;
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
struct Solid {
|
||||||
|
VertexVector vertices;
|
||||||
|
FaceVector<N> faces;
|
||||||
|
|
||||||
|
Solid<N>& fitDimension(float newMaxDimension) {
|
||||||
|
float maxDimension = 0;
|
||||||
|
for (const auto& vertex : vertices) {
|
||||||
|
maxDimension = std::max(maxDimension, std::max(std::max(vertex.x, vertex.y), vertex.z));
|
||||||
|
}
|
||||||
|
float multiplier = newMaxDimension / maxDimension;
|
||||||
|
for (auto& vertex : vertices) {
|
||||||
|
vertex *= multiplier;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec getFaceNormal(size_t faceIndex) const {
|
||||||
|
vec3 result;
|
||||||
|
const auto& face = faces[faceIndex];
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
result += vertices[face[i]];
|
||||||
|
}
|
||||||
|
result /= N;
|
||||||
|
return glm::normalize(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
size_t triangulatedFaceTriangleCount() {
|
||||||
|
return N - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
size_t triangulatedFaceIndexCount() {
|
||||||
|
return triangulatedFaceTriangleCount<N>() * VERTICES_PER_TRIANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Solid<3> tesselate(const Solid<3>& solid, int count);
|
||||||
|
const Solid<3>& tetrahedron();
|
||||||
|
const Solid<4>& cube();
|
||||||
|
const Solid<3>& octahedron();
|
||||||
|
const Solid<5>& dodecahedron();
|
||||||
|
const Solid<3>& icosahedron();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue