| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "BsShapeMeshes3D.h"
- #include "BsRect2.h"
- #include "BsMesh.h"
- #include "BsTime.h"
- #include "BsVector2.h"
- #include "BsQuaternion.h"
- #include "BsSphere.h"
- #include "BsMaterial.h"
- #include "BsPass.h"
- #include "BsCoreApplication.h"
- #include "BsRenderQueue.h"
- #include "BsException.h"
- #include "BsCCamera.h"
- #include "BsBuiltinResources.h"
- #include "BsVertexDataDesc.h"
- // DEBUG ONLY
- #include "BsDebug.h"
- namespace BansheeEngine
- {
- const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
- const UINT32 ShapeMeshes3D::NUM_INDICES_AA_LINE = 30;
- inline UINT8* writeVector3(UINT8* buffer, UINT32 stride, const Vector3& value)
- {
- *(Vector3*)buffer = value;
- return buffer + stride;
- }
- void ShapeMeshes3D::wireAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- assert((vertexOffset + 8) <= meshData->getNumVertices());
- assert((indexOffset + 24) <= meshData->getNumIndices());
- wireAABox(box, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::solidAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* normalData = meshData->getElementData(VES_NORMAL);
- assert((vertexOffset + 24) <= meshData->getNumVertices());
- assert((indexOffset + 36) <= meshData->getNumIndices());
- solidAABox(box, positionData, normalData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::wireSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT32 requiredNumVertices, requiredNumIndices;
- getNumElementsWireSphere(quality, requiredNumVertices, requiredNumIndices);
- assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
- assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
- UINT32 verticesPerArc = (quality + 1) * 5;
- UINT32 indicesPerArc = (verticesPerArc - 1) * 2;
- wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_X, meshData,
- vertexOffset, indexOffset, quality);
- wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Y, meshData,
- vertexOffset + verticesPerArc, indexOffset + indicesPerArc, quality);
- wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Z, meshData,
- vertexOffset + verticesPerArc * 2, indexOffset + indicesPerArc * 2, quality);
- }
- void ShapeMeshes3D::solidSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* normalData = meshData->getElementData(VES_NORMAL);
- UINT32 requiredNumVertices, requiredNumIndices;
- getNumElementsSphere(quality, requiredNumVertices, requiredNumIndices);
- assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
- assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
- solidSphere(sphere, positionData, normalData, vertexOffset,
- meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
- }
- void ShapeMeshes3D::wireDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
- UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- wireArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
- }
- void ShapeMeshes3D::solidDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
- UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- solidArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
- }
- void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
- const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT32 requiredNumVertices, requiredNumIndices;
- getNumElementsWireArc(quality, requiredNumVertices, requiredNumIndices);
- assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
- assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
- wireArc(center, radius, normal, startAngle, amountAngle, positionData, vertexOffset,
- meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
- }
- void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
- const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* normalData = meshData->getElementData(VES_NORMAL);
- UINT32 requiredNumVertices, requiredNumIndices;
- getNumElementsArc(quality, requiredNumVertices, requiredNumIndices);
- assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
- assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
- solidArc(center, radius, normal, startAngle, amountAngle, positionData, normalData, vertexOffset,
- meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
- }
- void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
- const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- assert((vertexOffset + 8) <= meshData->getNumVertices());
- assert((indexOffset + 24) <= meshData->getNumIndices());
- wireFrustum(position, aspect, FOV, near, far, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
- const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* normalData = meshData->getElementData(VES_NORMAL);
- UINT32 requiredNumVertices, requiredNumIndices;
- getNumElementsCone(quality, requiredNumVertices, requiredNumIndices);
- assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
- assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
- solidCone(base, normal, height, radius, positionData, normalData, vertexOffset,
- meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
- }
- void ShapeMeshes3D::solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* normalData = meshData->getElementData(VES_NORMAL);
- assert((vertexOffset + 8) <= meshData->getNumVertices());
- assert((indexOffset + 12) <= meshData->getNumIndices());
- solidQuad(area, positionData, normalData, vertexOffset,
- meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- assert((vertexOffset + 2) <= meshData->getNumVertices());
- assert((indexOffset + 2) <= meshData->getNumIndices());
- pixelLine(a, b, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth,
- const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* colorData = meshData->getElementData(VES_COLOR);
- assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
- assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
- antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
- }
- void ShapeMeshes3D::pixelLineList(const Vector<Vector3>& linePoints, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- assert(linePoints.size() % 2 == 0);
- assert((vertexOffset + linePoints.size() * 2) <= meshData->getNumVertices());
- assert((indexOffset + linePoints.size() * 2) <= meshData->getNumIndices());
- UINT32 curVertOffset = vertexOffset;
- UINT32 curIdxOffset = indexOffset;
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT32 numPoints = (UINT32)linePoints.size();
- for (UINT32 i = 0; i < numPoints; i += 2)
- {
- pixelLine(linePoints[i], linePoints[i + 1], positionData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
- curVertOffset += 2;
- curIdxOffset += 2;
- }
- }
- void ShapeMeshes3D::antialiasedLineList(const Vector<Vector3>& linePoints, const Vector3& up, float width, float borderWidth,
- const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
- {
- assert(linePoints.size() % 2 == 0);
- assert((vertexOffset + linePoints.size() * 4) <= meshData->getNumVertices());
- assert((indexOffset + linePoints.size() * 15) <= meshData->getNumIndices());
- UINT32 curVertOffset = vertexOffset;
- UINT32 curIdxOffset = indexOffset;
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT8* colorData = meshData->getElementData(VES_COLOR);
- UINT32 numPoints = (UINT32)linePoints.size();
- for (UINT32 i = 0; i < numPoints; i += 2)
- {
- antialiasedLine(linePoints[i], linePoints[i + 1], up, width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
- curVertOffset += NUM_VERTICES_AA_LINE;
- curIdxOffset += NUM_INDICES_AA_LINE;
- }
- }
- /************************************************************************/
- /* ELEMENT COUNT */
- /************************************************************************/
- void ShapeMeshes3D::getNumElementsAABox(UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = 24;
- numIndices = 36;
- }
- void ShapeMeshes3D::getNumElementsWireAABox(UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = 8;
- numIndices = 24;
- }
- void ShapeMeshes3D::getNumElementsSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = 20 * (3 * ((UINT32)std::pow(4, quality)));
- numIndices = numVertices;
- }
- void ShapeMeshes3D::getNumElementsWireSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- getNumElementsWireArc(quality, numVertices, numIndices);
- numVertices *= 3;
- numIndices *= 3;
- }
- void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = ((quality + 1) * 5 + 1) * 2;
- numIndices = ((quality + 1) * 5 - 1) * 6;
- }
- void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = (quality + 1) * 5;
- numIndices = ((quality + 1) * 5 - 1) * 2;
- }
- void ShapeMeshes3D::getNumElementsDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- getNumElementsArc(quality, numVertices, numIndices);
- }
- void ShapeMeshes3D::getNumElementsWireDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- getNumElementsWireArc(quality, numVertices, numIndices);
- }
- void ShapeMeshes3D::getNumElementsCone(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = ((quality + 1) * 4) * 3 + 1;
- numIndices = ((quality + 1) * 4) * 6;
- }
- void ShapeMeshes3D::getNumElementsQuad(UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = 8;
- numIndices = 12;
- }
- void ShapeMeshes3D::getNumElementsFrustum(UINT32& numVertices, UINT32& numIndices)
- {
- numVertices = 8;
- numIndices = 36;
- }
- void ShapeMeshes3D::wireAABox(const AABox& box, UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- outVertices += vertexOffset * vertexStride;
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
- outIndices += indexOffset;
- // Front
- outIndices[0] = vertexOffset + 0;
- outIndices[1] = vertexOffset + 1;
- outIndices[2] = vertexOffset + 1;
- outIndices[3] = vertexOffset + 2;
- outIndices[4] = vertexOffset + 2;
- outIndices[5] = vertexOffset + 3;
- outIndices[6] = vertexOffset + 3;
- outIndices[7] = vertexOffset + 0;
- // Center
- outIndices[8] = vertexOffset + 0;
- outIndices[9] = vertexOffset + 5;
- outIndices[10] = vertexOffset + 1;
- outIndices[11] = vertexOffset + 4;
- outIndices[12] = vertexOffset + 2;
- outIndices[13] = vertexOffset + 7;
- outIndices[14] = vertexOffset + 3;
- outIndices[15] = vertexOffset + 6;
- // Back
- outIndices[16] = vertexOffset + 4;
- outIndices[17] = vertexOffset + 5;
- outIndices[18] = vertexOffset + 5;
- outIndices[19] = vertexOffset + 6;
- outIndices[20] = vertexOffset + 6;
- outIndices[21] = vertexOffset + 7;
- outIndices[22] = vertexOffset + 7;
- outIndices[23] = vertexOffset + 4;
- }
- void ShapeMeshes3D::solidAABox(const AABox& box, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride,
- UINT32* outIndices, UINT32 indexOffset)
- {
- outVertices += (vertexOffset * vertexStride);
- Vector3* corners = (Vector3*)outVertices;
- // Front face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
- // Back face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
- // Left face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
- // Right face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
- // Top face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
- // Bottom face
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
- outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
- static const Vector3 faceNormals[6] =
- {
- Vector3(0, 0, 1),
- Vector3(0, 0, -1),
- Vector3(-1, 0, 0),
- Vector3(1, 0, 0),
- Vector3(0, 1, 0),
- Vector3(0, -1, 0)
- };
- outNormals += (vertexOffset * vertexStride);
- for (UINT32 face = 0; face < 6; face++)
- {
- outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
- outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
- outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
- outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
- }
- UINT32* indices = outIndices + indexOffset;
- for (UINT32 face = 0; face < 6; face++)
- {
- UINT32 faceVertOffset = vertexOffset + face * 4;
- indices[face * 6 + 0] = faceVertOffset + 2;
- indices[face * 6 + 1] = faceVertOffset + 1;
- indices[face * 6 + 2] = faceVertOffset + 0;
- indices[face * 6 + 3] = faceVertOffset + 0;
- indices[face * 6 + 4] = faceVertOffset + 3;
- indices[face * 6 + 5] = faceVertOffset + 2;
- }
- }
- void ShapeMeshes3D::solidSphere(const Sphere& sphere, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset,
- UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
- {
- // Create icosahedron
- static const float x = 0.525731112119133606f;
- static const float z = 0.850650808352039932f;
- static const Vector3 vertices[12] =
- {
- Vector3(-x, 0.0f, z),
- Vector3(x, 0.0f, z),
- Vector3(-x, 0.0f, -z),
- Vector3(x, 0.0f, -z),
- Vector3(0.0f, z, x),
- Vector3(0.0f, z, -x),
- Vector3(0.0f, -z, x),
- Vector3(0.0f, -z, -x),
- Vector3(z, x, 0.0f),
- Vector3(-z, x, 0.0f),
- Vector3(z, -x, 0.0f),
- Vector3(-z, -x, 0.0f)
- };
- static const UINT32 triangles[20][3] =
- {
- { 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 }
- };
- // Tessellate it
- UINT32 curVertOffset = vertexOffset;
- for (int i = 0; i < 20; ++i)
- {
- curVertOffset += subdivideTriangleOnSphere(sphere.getCenter(), sphere.getRadius(), quality,
- vertices[triangles[i][2]], vertices[triangles[i][1]], vertices[triangles[i][0]],
- outVertices, outNormals, curVertOffset, vertexStride);
- }
- // Create indices
- outIndices += indexOffset;
- UINT32 numIndices = 20 * (3 * (UINT32)std::pow(4, quality));
- for (UINT32 i = 0; i < numIndices; i += 3)
- {
- outIndices[i] = vertexOffset + i + 2;
- outIndices[i + 1] = vertexOffset + i + 1;
- outIndices[i + 2] = vertexOffset + i + 0;
- }
- }
- void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
- UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
- {
- UINT32 numVertices = (quality + 1) * 5;
- generateArcVertices(center, normal, radius, startAngle, amountAngle,
- numVertices, outVertices, vertexOffset, vertexStride);
- outIndices += indexOffset;
- UINT32 numLines = numVertices - 1;
- for (UINT32 i = 0; i < numLines; i++)
- {
- outIndices[i * 2 + 0] = vertexOffset + i;
- outIndices[i * 2 + 1] = vertexOffset + i + 1;
- }
- }
- void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
- UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
- {
- outVertices += vertexOffset * vertexStride;
- outNormals += vertexOffset * vertexStride;
- outIndices += indexOffset;
- bool reverseOrder = amountAngle.valueDegrees() < 0.0f;
- Vector3 visibleNormal = normal;
- outVertices = writeVector3(outVertices, vertexStride, center);
- outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
- UINT32 numArcVertices = (quality + 1) * 5;
- generateArcVertices(center, normal, radius, startAngle, amountAngle,
- numArcVertices, outVertices, vertexOffset, vertexStride);
- UINT8* otherSideVertices = outVertices + (numArcVertices * vertexStride);
- UINT8* otherSideNormals = outNormals + (numArcVertices * vertexStride);
- otherSideVertices = writeVector3(otherSideVertices, vertexStride, center);
- otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
- for (UINT32 i = 0; i < numArcVertices; i++)
- {
- otherSideVertices = writeVector3(otherSideVertices, vertexStride, *(Vector3*)outVertices);
- outVertices += vertexStride;
- outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
- otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
- }
- UINT32 numTriangles = numArcVertices - 1;
- // If angle is negative the order of vertices is reversed so we need to reverse the indexes too
- UINT32 frontSideOffset = vertexOffset + (reverseOrder ? (numArcVertices + 1) : 0);
- UINT32 backSideOffset = vertexOffset + (!reverseOrder ? (numArcVertices + 1) : 0);
- for (UINT32 i = 0; i < numTriangles; i++)
- {
- outIndices[i * 6 + 0] = frontSideOffset + 0;
- outIndices[i * 6 + 1] = frontSideOffset + i + 1;
- outIndices[i * 6 + 2] = frontSideOffset + i;
- outIndices[i * 6 + 3] = backSideOffset + 0;
- outIndices[i * 6 + 4] = backSideOffset + i;
- outIndices[i * 6 + 5] = backSideOffset + i + 1;
- }
- }
- void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
- UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- float fovTan = Math::tan(FOV * 0.5f);
- Vector3 nearPoint(0, 0, near);
- Vector3 nearWidth(near * fovTan * aspect, 0, 0);
- Vector3 nearHeight(0, (near * fovTan) / aspect, 0);
- Vector3 farPoint(0, 0, far);
- Vector3 farWidth(far * fovTan * aspect, 0, 0);
- Vector3 farHeight(0, (far * fovTan) / aspect, 0);
- Vector3 points[8] =
- {
- nearPoint + nearWidth + nearHeight,
- nearPoint - nearWidth + nearHeight,
- nearPoint - nearWidth - nearHeight,
- nearPoint + nearWidth - nearHeight,
- farPoint + farWidth + farHeight,
- farPoint - farWidth + farHeight,
- farPoint - farWidth - farHeight,
- farPoint + farWidth - farHeight
- };
- outVertices += vertexOffset * vertexStride;
- for (UINT32 i = 0; i < 8; i++)
- outVertices = writeVector3(outVertices, vertexStride, position + points[i]);
- outIndices += indexOffset;
- // Front
- outIndices[0] = vertexOffset + 0; outIndices[1] = vertexOffset + 1;
- outIndices[2] = vertexOffset + 1; outIndices[3] = vertexOffset + 2;
- outIndices[4] = vertexOffset + 2; outIndices[5] = vertexOffset + 3;
- outIndices[6] = vertexOffset + 3; outIndices[7] = vertexOffset + 0;
- // Center
- outIndices[8] = vertexOffset + 0; outIndices[9] = vertexOffset + 4;
- outIndices[10] = vertexOffset + 1; outIndices[11] = vertexOffset + 5;
- outIndices[12] = vertexOffset + 2; outIndices[13] = vertexOffset + 6;
- outIndices[14] = vertexOffset + 3; outIndices[15] = vertexOffset + 7;
- // Back
- outIndices[16] = vertexOffset + 4; outIndices[17] = vertexOffset + 5;
- outIndices[18] = vertexOffset + 5; outIndices[19] = vertexOffset + 6;
- outIndices[20] = vertexOffset + 6; outIndices[21] = vertexOffset + 7;
- outIndices[22] = vertexOffset + 7; outIndices[23] = vertexOffset + 4;
- }
- void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
- UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
- {
- outVertices += vertexOffset * vertexStride;
- outIndices += indexOffset;
- if (outNormals != nullptr)
- outNormals += vertexOffset * vertexStride;
- // Generate base disc
- UINT32 numArcVertices = (quality + 1) * 4;
- generateArcVertices(base, normal, radius, Degree(0), Degree(360),
- numArcVertices + 1, outVertices, 0, vertexStride);
- outVertices += numArcVertices * vertexStride;
- outVertices = writeVector3(outVertices, vertexStride, base); // Write base vertex
- UINT32 baseIdx = numArcVertices;
- if (outNormals != nullptr)
- {
- UINT32 totalNumBaseVertices = numArcVertices + 1;
- for (UINT32 i = 0; i < totalNumBaseVertices; i++)
- outNormals = writeVector3(outNormals, vertexStride, -normal);
- }
- UINT32 numTriangles = numArcVertices;
- for (UINT32 i = 0; i < numTriangles - 1; i++)
- {
- outIndices[i * 3 + 0] = vertexOffset + baseIdx;
- outIndices[i * 3 + 1] = vertexOffset + i;
- outIndices[i * 3 + 2] = vertexOffset + i + 1;
- }
- {
- UINT32 i = numTriangles - 1;
- outIndices[i * 3 + 0] = vertexOffset + baseIdx;
- outIndices[i * 3 + 1] = vertexOffset + i;
- outIndices[i * 3 + 2] = vertexOffset + 0;
- }
- //// Generate cone
- // Base vertices
- generateArcVertices(base, normal, radius, Degree(0), Degree(360),
- numArcVertices + 1, outVertices, 0, vertexStride);
- Vector3 topVertex = base + normal * height;
- // Normals
- if (outNormals != nullptr)
- {
- UINT8* outNormalsBase = outNormals;
- UINT8* outNormalsTop = outNormals + numArcVertices * vertexStride;
- for (INT32 i = 0; i < (INT32)numArcVertices; i++)
- {
- int offsetA = i == 0 ? numArcVertices - 1 : i - 1;
- int offsetB = i;
- int offsetC = (i + 1) % numArcVertices;
- Vector3* a = (Vector3*)(outVertices + (offsetA * vertexStride));
- Vector3* b = (Vector3*)(outVertices + (offsetB * vertexStride));
- Vector3* c = (Vector3*)(outVertices + (offsetC * vertexStride));
- Vector3 toTop = topVertex - *b;
- Vector3 normalLeft = Vector3::cross(toTop, *a - *b);
- normalLeft.normalize();
- Vector3 normalRight = Vector3::cross(*c - *b, toTop);
- normalRight.normalize();
- Vector3 triNormal = Vector3::normalize(normalLeft + normalRight);
- outNormalsBase = writeVector3(outNormalsBase, vertexStride, triNormal);
- outNormalsTop = writeVector3(outNormalsTop, vertexStride, triNormal);
- }
- }
- // Top vertices (All same position, but need them separate because of different normals)
- outVertices += numArcVertices * vertexStride;
- for (UINT32 i = 0; i < numArcVertices; i++)
- outVertices = writeVector3(outVertices, vertexStride, topVertex);
- outIndices += numTriangles * 3;
- UINT32 curVertBaseOffset = vertexOffset + numArcVertices + 1;
- UINT32 curVertTopOffset = curVertBaseOffset + numArcVertices;
- for (UINT32 i = 0; i < numTriangles - 1; i++)
- {
- outIndices[i * 3 + 0] = curVertTopOffset + i;
- outIndices[i * 3 + 1] = curVertBaseOffset + i + 1;
- outIndices[i * 3 + 2] = curVertBaseOffset + i;
- }
- {
- UINT32 i = numTriangles - 1;
- outIndices[i * 3 + 0] = curVertTopOffset + i;
- outIndices[i * 3 + 1] = curVertBaseOffset + 0;
- outIndices[i * 3 + 2] = curVertBaseOffset + i;
- }
- }
- void ShapeMeshes3D::solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- outVertices += (vertexOffset * vertexStride);
- Vector3 topLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
- Vector3 topRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
- Vector3 botRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
- Vector3 botLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
- outVertices = writeVector3(outVertices, vertexStride, topLeft);
- outVertices = writeVector3(outVertices, vertexStride, topRight);
- outVertices = writeVector3(outVertices, vertexStride, botRight);
- outVertices = writeVector3(outVertices, vertexStride, botLeft);
- outVertices = writeVector3(outVertices, vertexStride, topLeft);
- outVertices = writeVector3(outVertices, vertexStride, topRight);
- outVertices = writeVector3(outVertices, vertexStride, botRight);
- outVertices = writeVector3(outVertices, vertexStride, botLeft);
- Vector3 normal = area.getAxisHorz().cross(area.getAxisVert());
- Vector3 reverseNormal = -normal;
- outNormals += (vertexOffset * vertexStride);
- outNormals = writeVector3(outNormals, vertexStride, normal);
- outNormals = writeVector3(outNormals, vertexStride, normal);
- outNormals = writeVector3(outNormals, vertexStride, normal);
- outNormals = writeVector3(outNormals, vertexStride, normal);
- outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
- outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
- outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
- outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
- outIndices += indexOffset;
- outIndices[0] = vertexOffset;
- outIndices[1] = vertexOffset + 1;
- outIndices[2] = vertexOffset + 2;
- outIndices[3] = vertexOffset;
- outIndices[4] = vertexOffset + 2;
- outIndices[5] = vertexOffset + 3;
- outIndices[6] = vertexOffset + 4;
- outIndices[7] = vertexOffset + 6;
- outIndices[8] = vertexOffset + 5;
- outIndices[9] = vertexOffset + 4;
- outIndices[10] = vertexOffset + 7;
- outIndices[11] = vertexOffset + 6;
- }
- Vector3 ShapeMeshes3D::calcCenter(UINT8* vertices, UINT32 numVertices, UINT32 vertexStride)
- {
- Vector3 center = Vector3::ZERO;
- for(UINT32 i = 0; i < numVertices; i++)
- {
- Vector3* curVert = (Vector3*)vertices;
- center += *curVert;
- vertices += vertexStride;
- }
- center /= (float)numVertices;
- return center;
- }
- void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, UINT8* outVertices,
- UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- outVertices += (vertexOffset * vertexStride);
- Vector3* vertices = (Vector3*)outVertices;
- (*vertices) = a;
- vertices = (Vector3*)(outVertices + vertexStride);
- (*vertices) = b;
- outIndices += indexOffset;
- outIndices[0] = vertexOffset + 0;
- outIndices[1] = vertexOffset + 1;
- }
- void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
- UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- Vector3 dir = b - a;
- dir.normalize();
- Vector3 right = dir.cross(up);
- right.normalize();
- Vector<Vector3> points(4);
- float r = width * 0.5f;
- dir = dir * r;
- right = right * r;
- Vector3 v0 = a - dir - right;
- Vector3 v1 = a - dir + right;
- Vector3 v2 = b + dir + right;
- Vector3 v3 = b + dir - right;
- points[0] = v0;
- points[1] = v1;
- points[2] = v2;
- points[3] = v3;
- antialiasedPolygon(points, up, borderWidth, color, outVertices, outColors, vertexOffset, vertexStride, outIndices, indexOffset);
- }
- void ShapeMeshes3D::pixelSolidPolygon(const Vector<Vector3>& points, UINT8* outVertices,
- UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- outVertices += (vertexOffset * vertexStride);
- for (auto& point : points)
- {
- Vector3* vertices = (Vector3*)outVertices;
- (*vertices) = point;
- outVertices += vertexStride;
- }
- outIndices += indexOffset;
- INT32 numPoints = (INT32)points.size();
- UINT32 idxCnt = 0;
- for (int i = 2; i < numPoints; i++)
- {
- outIndices[idxCnt++] = vertexOffset;
- outIndices[idxCnt++] = vertexOffset + i - 1;
- outIndices[idxCnt++] = vertexOffset + i;
- }
- }
- void ShapeMeshes3D::pixelWirePolygon(const Vector<Vector3>& points, UINT8* outVertices,
- UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- INT32 numPoints = (INT32)points.size();
- UINT32 curVertOffset = vertexOffset;
- UINT32 curIdxOffset = indexOffset;
- for (INT32 i = 0, j = numPoints - 1; i < numPoints; j = i++)
- {
- pixelLine(points[j], points[i], outVertices, curVertOffset, vertexStride, outIndices, curIdxOffset);
- curVertOffset += 2;
- curIdxOffset += 2;
- }
- }
- void ShapeMeshes3D::antialiasedPolygon(const Vector<Vector3>& points, const Vector3& up, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
- UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
- {
- UINT32 numCoords = (UINT32)points.size();
- outVertices += vertexOffset * vertexStride;
- outColors += vertexOffset * vertexStride;
- Vector<Vector3> tempNormals(numCoords);
- for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
- {
- const Vector3& v0 = points[j];
- const Vector3& v1 = points[i];
- Vector3 dir = v1 - v0;
- Vector3 right = dir.cross(up);
- right.normalize();
- tempNormals[j] = right;
- // Also start populating the vertex array
- Vector3* vertices = (Vector3*)outVertices;
- *vertices = v1;
- UINT32* colors = (UINT32*)outColors;
- *colors = color.getAsRGBA();
- outVertices += vertexStride;
- outColors += vertexStride;
- }
- Color transparentColor = color;
- transparentColor.a = 0.0f;
- for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
- {
- const Vector3& n0 = tempNormals[j];
- const Vector3& n1 = tempNormals[i];
- Vector3 avgNrm = (n0 + n1) * 0.5f;
- float magSqrd = avgNrm.squaredLength();
- if (magSqrd > 0.000001f)
- {
- float scale = 1.0f / magSqrd;
- if (scale > 10.0f)
- scale = 10.0f;
- avgNrm = avgNrm * scale;
- }
- Vector3 tempCoord = points[i] + avgNrm * borderWidth;
- // Move it to the vertex array
- Vector3* vertices = (Vector3*)outVertices;
- *vertices = tempCoord;
- UINT32* colors = (UINT32*)outColors;
- *colors = transparentColor.getAsRGBA();
- outVertices += vertexStride;
- outColors += vertexStride;
- }
- // Populate index buffer
- outIndices += indexOffset;
- UINT32 idxCnt = 0;
- for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
- {
- outIndices[idxCnt++] = vertexOffset + i;
- outIndices[idxCnt++] = vertexOffset + j;
- outIndices[idxCnt++] = vertexOffset + numCoords + j;
- outIndices[idxCnt++] = vertexOffset + numCoords + j;
- outIndices[idxCnt++] = vertexOffset + numCoords + i;
- outIndices[idxCnt++] = vertexOffset + i;
- }
- for (UINT32 i = 2; i < numCoords; ++i)
- {
- outIndices[idxCnt++] = vertexOffset + 0;
- outIndices[idxCnt++] = vertexOffset + i - 1;
- outIndices[idxCnt++] = vertexOffset + i;
- }
- }
- UINT32 ShapeMeshes3D::subdivideTriangleOnSphere(const Vector3& center, float radius, UINT32 numLevels,
- const Vector3& a, const Vector3& b, const Vector3& c,
- UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride)
- {
- outVertices += (vertexOffset * vertexStride);
- if (outNormals != nullptr)
- outNormals += (vertexOffset * vertexStride);
- UINT32 numVertices = 0;
- if (numLevels > 0)
- {
- Vector3 sub1 = Vector3::normalize((a + b) * 0.5f);
- Vector3 sub2 = Vector3::normalize((b + c) * 0.5f);
- Vector3 sub3 = Vector3::normalize((c + a) * 0.5f);
- numLevels--;
- numVertices += subdivideTriangleOnSphere(center, radius, numLevels, a, sub1, sub3, outVertices,
- outNormals, numVertices, vertexStride);
- numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, b, sub2, outVertices,
- outNormals, numVertices, vertexStride);
- numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, sub2, sub3, outVertices,
- outNormals, numVertices, vertexStride);
- numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub3, sub2, c, outVertices,
- outNormals, numVertices, vertexStride);
- }
- else
- {
- *((Vector3*)outVertices) = center + a * radius;
- outVertices += vertexStride;
-
- *((Vector3*)outVertices) = center + b * radius;
- outVertices += vertexStride;
-
- *((Vector3*)outVertices) = center + c * radius;
- outVertices += vertexStride;
- if (outNormals != nullptr)
- {
- *((Vector3*)outNormals) = a;
- outNormals += vertexStride;
- *((Vector3*)outNormals) = b;
- outNormals += vertexStride;
- *((Vector3*)outNormals) = c;
- outNormals += vertexStride;
- }
- numVertices += 3;
- }
- return numVertices;
- }
- void ShapeMeshes3D::generateArcVertices(const Vector3& center, const Vector3& up, float radius, Degree startAngle, Degree angleAmount, UINT32 numVertices,
- UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride)
- {
- assert(numVertices >= 2);
- Quaternion alignWithStart = Quaternion(-Vector3::UNIT_Y, startAngle);
- Quaternion alignWithUp = Quaternion::getRotationFromTo(Vector3::UNIT_Y, up);
- Vector3 right = alignWithUp.rotate(alignWithStart.rotate(Vector3::UNIT_X));
- right.normalize();
- Quaternion increment(up, angleAmount / (float)(numVertices - 1));
- outVertices += vertexOffset * vertexStride;
- Vector3 curDirection = right * radius;
- for (UINT32 i = 0; i < numVertices; i++)
- {
- outVertices = writeVector3(outVertices, vertexStride, center + curDirection);
- curDirection = increment.rotate(curDirection);
- }
- }
- }
|