LightsprintSDK 2021.08.08
|
#include <RRMesh.h>
Classes | |
struct | PreImportNumber |
struct | TangentBasis |
struct | Triangle |
struct | TriangleBody |
struct | TriangleMapping |
struct | TriangleNormals |
Public Types | |
enum | { UNDEFINED = UINT_MAX } |
enum | TangentSpaceState { TSS_PERFECT , TSS_NOT_ORTHOGONAL , TSS_DENORMALIZED , TSS_INVALID , TSS_MISSING } |
enum | Format { UINT8 = 0 , UINT16 = 1 , UINT32 = 2 , FLOAT32 = 4 } |
enum | Flags { TRI_LIST = 0 , TRI_STRIP = (1<<0) , OPTIMIZED_VERTICES = (1<<1) , OPTIMIZED_TRIANGLES = (1<<2) } |
typedef RRVec3 | Vertex |
Public Member Functions | |
RRMesh () | |
virtual | ~RRMesh () |
virtual unsigned | getNumVertices () const =0 |
virtual void | getVertex (unsigned v, Vertex &out) const =0 |
virtual unsigned | getNumTriangles () const =0 |
virtual void | getTriangle (unsigned t, Triangle &out) const =0 |
virtual void | getTriangleBody (unsigned t, TriangleBody &out) const |
virtual bool | getTrianglePlane (unsigned t, RRVec4 &out) const |
virtual RRReal | getTriangleArea (unsigned t) const |
virtual void | getTriangleNormals (unsigned t, TriangleNormals &out) const |
virtual bool | getTriangleMapping (unsigned t, TriangleMapping &out, unsigned channel) const |
virtual PreImportNumber | getPreImportVertex (unsigned postImportVertex, unsigned postImportTriangle) const |
virtual unsigned | getPostImportVertex (PreImportNumber preImportVertex, PreImportNumber preImportTriangle) const |
virtual PreImportNumber | getPreImportTriangle (unsigned postImportTriangle) const |
virtual unsigned | getPostImportTriangle (PreImportNumber preImportTriangle) const |
unsigned | getNumPreImportVertices () const |
virtual void | getUvChannels (RRVector< unsigned > &out) const |
virtual void | getAABB (RRVec3 *mini, RRVec3 *maxi, RRVec3 *center) const |
virtual RRReal | getAverageVertexDistance () const |
virtual RRReal | getMappingDensity (unsigned channel) const |
virtual RRReal | findGroundLevel () const |
virtual RRHash | getHash () const |
TangentSpaceState | checkNormals () const |
TangentSpaceState | checkTangents () const |
virtual unsigned | checkConsistency (unsigned lightmapTexcoord, const char *meshName, class NumReports *numReports=nullptr) const |
RRMesh * | createTransformed (const RRMatrix3x4Ex *transform) const |
const RRMesh * | createOptimizedVertices (float maxDistanceBetweenVerticesToMerge, float maxRadiansBetweenNormalsToMerge, float maxDistanceBetweenUvsToMerge, const RRVector< unsigned > *texcoords) const |
const RRMesh * | createOptimizedTriangles () const |
const RRMesh * | createAccelerated () const |
RRMesh * | createVertexBufferRuler () const |
class RRMeshArrays * | createArrays (bool indexed, const RRVector< unsigned > &texcoords, bool tangents) const |
Public Member Functions inherited from rr::RRUniformlyAllocated | |
void * | operator new (std::size_t n) |
void * | operator new[] (std::size_t n) |
void | operator delete (void *p, std::size_t n) |
void | operator delete[] (void *p, std::size_t n) |
Static Public Member Functions | |
static RRMesh * | create (unsigned flags, Format vertexFormat, void *vertexBuffer, unsigned vertexCount, unsigned vertexStride) |
static RRMesh * | createIndexed (unsigned flags, Format vertexFormat, void *vertexBuffer, unsigned vertexCount, unsigned vertexStride, Format indexFormat, void *indexBuffer, unsigned indexCount, float vertexStitchMaxDistance=0) |
static const RRMesh * | createMultiMesh (const RRMesh *const *meshes, unsigned numMeshes, bool fast) |
Protected Attributes | |
struct AABBCache * | aabbCache |
Additional Inherited Members | |
Protected Member Functions inherited from rr::RRUniformlyAllocatedNonCopyable | |
RRUniformlyAllocatedNonCopyable () | |
~RRUniformlyAllocatedNonCopyable () | |
Common interface for any standard or proprietary triangle mesh structure.
RRMesh is typically only several bytes big adaptor, it provides unified interface to your mesh, but it uses your mesh data, no data need to be duplicated.
Thread safe: yes, may be accessed by any number of threads simultaneously.
RRMesh has built-in support for standard mesh formats used by rendering APIs - vertex and index buffers using triangle lists or triangle strips. See create() and createIndexed().
RRMesh has built-in support for baking multiple meshes into one mesh (without need for additional memory). This may simplify mesh oprations or improve performance in some situations. See createMultiMesh().
RRMesh has built-in support for creating self-contained mesh copies. See createCopy(). While importers created from vertex buffer doesn't allocate more memory and depend on vertex buffer, self-contained copy contains all mesh data and doesn't depend on any other objects.
For other mesh formats (heightfield, realtime generated etc), you may easily derive from RRMesh and create your own mesh adaptor.
RRMesh may help you with mesh optimizations if requested, for example by removing duplicate vertices or degenerated triangles.
All data provided by RRMesh must be constant in time. Built-in importers guarantee constancy if you don't change their vertex/index buffers. Constancy of mesh copy is guaranteed always.
RRMesh operates with two types of vertex and triangle indices.
All Pre-Post conversion functions must accept all unsigned values. When query makes no sense, they return UNDEFINED. This is because
All other function use PostImport numbers and may support only their 0..num-1 range. When called with out of range value, result is undefined. Debug version may return arbitrary number or throw assert. Release version may return arbitrary number or crash. This is because
For correct lighting, it's important to know where front and back sides of triangle are. Materials (see RRMaterial) define some properties separately for both sides of triangle. Renderers render both sides of triangle differently.
When you see triangle vertices in CCW order, you see triangle's front side. In this situation triangle's normal must point to your (front) hemisphere.
Some applications are known to define front/back differently:
How to swap front/back sides, when importing data from such applications?
typedef RRVec3 rr::RRMesh::Vertex |
One vertex 3d space.
anonymous enum |
enum rr::RRMesh::Format |
enum rr::RRMesh::Flags |
Flags that help to specify your create() or createIndexed() request.
rr::RRMesh::RRMesh | ( | ) |
|
virtual |
|
pure virtual |
Returns number of vertices in mesh.
Implemented in rr::RRMeshArrays.
|
pure virtual |
Writes position of v-th vertex in mesh to out.
Make sure you provide valid v is in range <0..getNumVertices()-1>. Implementations are allowed to expect valid v, result is undefined for invalid v (possible assert in debug, crash in release).
What exactly is vertex, do boxes have 8 or 24 vertices?
RRMesh, RRCollider and RRObject create no constraints, you are free to use your favorite approach - create box with 8 or 24 or any other number of vertices greater than 8, collisions and illumination will be computed correctly. (24 because each one of 8 vertices is used by 3 sides with different normal)
RRSolver depends on vertex list defined here. If you request vertex buffer with per-vertex illumination, vertex buffer will have getNumVertices() items. So when writing new RRMesh implementations, create vertex list so that vertex buffers with the same size and vertex order are compatible with your renderer.
Implemented in rr::RRMeshArrays.
|
pure virtual |
Returns number of triangles in mesh.
Implemented in rr::RRMeshArrays.
|
pure virtual |
Writes t-th triangle in mesh to out.
Make sure you provide valid t in range <0..getNumTriangles()-1>. Implementators are allowed to expect valid t (performance reasons, may be called very often), so result is completely undefined for invalid t (possible crash).
Order of vertices in triangle has influence on what side of triangle is front, which is important for lighting. See more details in Front/back side.
Implemented in rr::RRMeshArrays.
|
virtual |
Writes t-th triangle in mesh to out.
Make sure you provide valid t in range <0..getNumTriangles()-1>. Implementators are allowed to expect valid t, so result is completely undefined for invalid t (possible crash).
There is default implementation, but if you know format of your data well, you may provide faster one.
Speed of this function is important for intersection tests performance.
Reimplemented in rr::RRMeshArrays.
|
virtual |
Writes t-th triangle plane to out.
Be sure to provide valid t is in range <0..getNumTriangles()-1>. Implementators are allowed to expect valid t, so result is completely undefined for invalid t (possible crash).
There is default implementation, but if you know format of your data well, you may provide faster one.
|
virtual |
Returns area of t-th triangle.
Be sure to provide valid t is in range <0..getNumTriangles()-1>. Implementators are allowed to expect valid t, so result is completely undefined for invalid t (possible crash).
There is default implementation, but if you know format of your data well, you may provide faster one.
|
virtual |
Writes tangent bases in triangle vertices to out. Normals are part of bases.
Tangent bases are used by global illumination solver and renderer. Normals should point to front side hemisphere, see Front/back side.
Default implementation writes all vertex normals equal to triangle plane normal and constructs appropriate tangent space.
t | Index of triangle. Valid t is in range <0..getNumTriangles()-1>. |
out | Caller provided storage for result. For valid t, requested normals are written to out. For invalid t, out stays unmodified. |
Reimplemented in rr::RRMeshArrays.
|
virtual |
Writes t-th triangle's uv mapping to out.
t | Index of triangle. Valid t is in range <0..getNumTriangles()-1>. |
out | Caller provided storage for result. For valid t, requested mapping is written to out. For invalid t, out stays unmodified. |
channel | Texcoord channel to use, RRMaterial::diffuseReflectance.texcoord for diffuse texture mapping, RRMaterial::lightmap.texcoord for unwrap used by lightmaps etc. Note that for proper lighting, unwrap must have all coordinates in <0..1> range and triangles must not overlap. Unwrap may be imported or automatically generated by RRObjects::buildUnwrap(). |
Reimplemented in rr::RRMeshArrays.
|
inlinevirtual |
Returns PreImport index of given vertex or UNDEFINED for invalid inputs.
|
inlinevirtual |
Returns PostImport index of given vertex or UNDEFINED for invalid inputs.
|
inlinevirtual |
Returns PreImport index of given triangle or UNDEFINED for invalid inputs.
|
inlinevirtual |
Returns PostImport index of given triangle or UNDEFINED for invalid inputs.
unsigned rr::RRMesh::getNumPreImportVertices | ( | ) | const |
Returns highest PreImport vertex number+1.
PreImport numbers are used as positions of vertices in vertex buffer, so returned number is also size of vertex buffer. Very slow (checks all vertices).
|
virtual |
Fills out with uv channels provided by mesh, in ascending order. Default implementation queries presence of channels 0 to 100, ignores higher channels.
Reimplemented in rr::RRMeshArrays.
Returns axis aligned bounding box and center of mesh. Fast (cached).
mini | nullptr or pointer to vec3 to be filled with minimum of computed AABB. |
maxi | nullptr or pointer to vec3 to be filled with maximum of computed AABB. |
center | nullptr or pointer to vec3 to be filled with average vertex position. |
Reimplemented in rr::RRMeshArrays.
|
virtual |
Returns average distance between two vertices. Slow (not cached).
|
virtual |
Returns median of (edge_length / edge_length_in_texture_space). Slow (not cached).
|
virtual |
Returns y coordinate of plane where triangles facing straight up have the biggest total area. In CG scenes, this is usually flat ground. Slow (not cached).
|
virtual |
Returns hash of mesh geometry (positions, not normals and uvs). Slow (not cached).
TangentSpaceState rr::RRMesh::checkNormals | ( | ) | const |
TangentSpaceState rr::RRMesh::checkTangents | ( | ) | const |
|
virtual |
Reports inconsistencies found in mesh.
lightmapTexcoord | Optional lightmap texcoord channel (it is stored in RRMaterial::lightmap.texcoord). UINT_MAX disables unwrap check. |
meshName | Optional mesh name included in report if inconsistency is found. May be nullptr. |
numReports | Reserved, keep it nullptr. |
|
static |
Creates RRMesh from your vertex buffer.
flags | See Flags. Note that optimizations are not implemented for triangle lists, OPTIMIZE_XXX flags will be silently ignored. |
vertexFormat | Format of data in your vertex buffer. See Format. Currently only FLOAT32 is supported. |
vertexBuffer | Your vertex buffer. |
vertexCount | Number of vertices in your vertex buffer. |
vertexStride | Distance (in bytes) between n-th and (n+1)th vertex in your vertex buffer. |
|
static |
Creates RRMesh from your vertex and index buffers.
flags | See Flags. |
vertexFormat | Format of data in your your vertex buffer. See Format. Currently only FLOAT32 is supported. |
vertexBuffer | Your vertex buffer. |
vertexCount | Number of vertices in your vertex buffer. |
vertexStride | Distance (in bytes) between n-th and (n+1)th vertex in your vertex buffer. |
indexFormat | Format of data in your index buffer. See Format. Only UINT8, UINT16 and UINT32 is supported. |
indexBuffer | Your index buffer. |
indexCount | Number of indices in your index buffer. |
vertexStitchMaxDistance | Max distance for vertex stitching. For default 0, vertices with equal coordinates are stitched and get equal vertex index (number of vertices returned by getNumVertices() is then lower). For negative value, no stitching is performed. For positive value, also vertices in lower or equal distance will be stitched. |
RRMesh * rr::RRMesh::createTransformed | ( | const RRMatrix3x4Ex * | transform | ) | const |
Creates and returns transformed mesh.
Created instance doesn't require additional memory, but it depends on 'this' mesh and 'transform' matrix, both must stay alive for whole life of created instance. You can even modify 'this' and 'transform' later and created mesh gets modified too.
Usually used when mesh in world space is needed and we have mesh in local space. In this case, world space matrix (the one that transforms from local to world) should be passed in transform.
Only positions/normals/tangent space are transformed, custom channels are left untouched.
Non-uniform transformations break tangent space orthogonality.
|
static |
Creates and returns union of multiple meshes (contains vertices and triangles of all meshes).
Created instance (MultiMesh) doesn't require additional memory, but it depends on all meshes from array, they must stay alive for whole life of MultiMesh.
This can be used to accelerate calculations, as one big object is nearly always faster than multiple small objects.
This can be used to simplify calculations, as processing one object may be simpler than processing array of objects.
For array with 1 element, pointer to that element may be returned.
If you need to locate original triangles and vertices in MultiMesh, you have two choices:
meshes | Array of meshes, source data for MultiMesh. |
numMeshes | Length of 'meshes' array. |
fast | With false, multimesh has fixed size of several bytes. With true, multimesh allocates 8 bytes per triangle, but it is faster, especially in scenes made of hundreds of small meshes. |
const RRMesh * rr::RRMesh::createOptimizedVertices | ( | float | maxDistanceBetweenVerticesToMerge, |
float | maxRadiansBetweenNormalsToMerge, | ||
float | maxDistanceBetweenUvsToMerge, | ||
const RRVector< unsigned > * | texcoords | ||
) | const |
Creates and returns nearly identical mesh with optimized set of vertices (removes unused and redundant ones).
Merges identical or similar vertices so that number of vertices in returned mesh decreases. Only vertex positions, normals and uvs are tested, so vertices with completely different tangents may be merged.
Created instance requires only small amount of additional memory, but it depends on 'this' mesh, 'this' must stay alive for whole life of created instance. If no vertex can be removed, 'this' is returned.
maxDistanceBetweenVerticesToMerge | Vertices are not merged if their positions differ more. If negative, vertices are never merged, but unused ones can still be removed. |
maxRadiansBetweenNormalsToMerge | Vertices are not merged if their normals differ more. If negative, vertices are never merged, but unused ones can still be removed. |
maxDistanceBetweenUvsToMerge | Vertices are not merged if their uvs from texcoords differ more. |
texcoords | Vertices are not merged if their uvs from texcoords differ more than maxDistanceBetweenUvsToMerge. May be nullptr. Uvs not listed in texcoords are ignored, differences in such channels don't prevent merging. |
const RRMesh * rr::RRMesh::createOptimizedTriangles | ( | ) | const |
Creates and returns identical mesh with optimized set of triangles (removes degenerated triangles).
Created instance requires only small amount of additional memory, but it depends on 'this' mesh, 'this' must stay alive for whole life of created instance. If 'this' is already optimal, 'this' is returned. Note that after removal of degenrated triangles, there might be unused vertices in mesh; you can use createOptimizedVertices() to remove them.
const RRMesh * rr::RRMesh::createAccelerated | ( | ) | const |
Creates and returns accelerated mesh.
Created instance caches all TriangleBase and TriangleNormals for whole mesh, so it allocates 144 bytes per triangle. It still depends on 'this' mesh, 'this' must stay alive for whole life of created instance.
It is very efficient when applied on multimesh made of hundreds of smaller meshes. It accelerates getTriangleBase() and getTriangleNormals(). These functions are critical for performance of BSP_COMPACT and BSP_FAST colliders. Colliders are critical for performance of lightmap building.
In practice, this function is not needed for lightmap building, use collider types BSP_COMPACT, BSP_FAST, BSP_FASTER, BSP_FASTEST in RRSolver::setStaticObjects() to trade performance / memory.
RRMesh * rr::RRMesh::createVertexBufferRuler | ( | ) | const |
Creates and returns identical mesh with all optimizations and filters previously applied baked.
Created instance doesn't require additional memory, but it depends on 'this' mesh, 'this' must stay alive for whole life of created instance.
All other mesh filters and optimizers let you convert between original and new triangle and vertex numbers using getPreImportVertex() and getPreImportTriangle(). This filter only erases original (preImport) numbers and sets them equal to current (postImport) numbers. PreImport numbers are used by RRSolver for vertex buffer layout, so this filter adjusts layout of generated vertex buffers to use current vertex numbers.
class RRMeshArrays * rr::RRMesh::createArrays | ( | bool | indexed, |
const RRVector< unsigned > & | texcoords, | ||
bool | tangents | ||
) | const |
Creates mesh with direct read-write access to internal data arrays.
Created mesh does not depend on the old one, it's safe to delete the old one.
Note that created mesh contains reduced set of data
|
protected |