blob: 8deaad908e3574cf28401158cd6ddb7d78ece84d [file] [log] [blame]
// This file allows multiple includes.
#if !defined(RT_VERTEX_POSITION) || !defined(RT_VERTEX_NORMAL) || !defined(RT_VERTEX_TEXTURE1) || !defined(RT_VERTEX_TEXTURE2) || !defined(RT_VERTEX_TEXTURE3) || !defined(RT_VERTEX_TEXTURE4) || !defined(RT_FACE_NORMAL) || !defined(RT_MATERIAL) || !defined(RT_MATERIAL)
#error not all required macros are defined in RTMesh.hxx invocation.
#endif
// Just to allow warning-less compilation of some pathological cases
// (which shoudn't be used anyway).
#pragma warning(push)
#ifdef __INTEL_COMPILER
#pragma warning(disable: 504) // initial value of reference to non-const must be an lvalue
#pragma warning(disable: 473) // returning reference to local temporary
#endif
#ifdef _MSC_VER
#pragma warning(disable: 4172) // returning address of local variable or temporary
#endif
// Just to make the coding simpler...
#if RTMESH_COMPONENT(RT_VERTEX_POSITION)
#define STORE_VERTEX_POSITION(s) s
#else
#define STORE_VERTEX_POSITION(s)
#endif
#if RTMESH_COMPONENT(RT_VERTEX_NORMAL)
#define STORE_VERTEX_NORMAL(s) s
#else
#define STORE_VERTEX_NORMAL(s)
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE1)
#define STORE_VERTEX_TEXTURE1(s) s
#else
#define STORE_VERTEX_TEXTURE1(s)
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE2)
#define STORE_VERTEX_TEXTURE2(s) s
#else
#define STORE_VERTEX_TEXTURE2(s)
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE2)
#define STORE_VERTEX_TEXTURE2(s) s
#else
#define STORE_VERTEX_TEXTURE2(s)
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE4)
#define STORE_VERTEX_TEXTURE4(s) s
#else
#define STORE_VERTEX_TEXTURE4(s)
#endif
#if RTMESH_COMPONENT(RT_FACE_NORMAL)
#define STORE_FACE_NORMAL(s) s
#else
#define STORE_FACE_NORMAL(s)
#endif
#if RTMESH_COMPONENT(RT_MATERIAL)
#define STORE_MATERIAL(s) s
#else
#define STORE_MATERIAL(s)
#endif
// Size for the additional vertex/traingle members
// (beyond RT_* semanthics), defaulted to 0.
#ifndef RT_VERTEX_DATA
#define RT_VERTEX_DATA 0
#endif
#ifndef RT_FACE_DATA
#define RT_FACE_DATA 0
#endif
// Data types for indices and data
// (defaulted to int and float if not defined in the includer).
#ifndef IndexType
#define IndexType int
#endif
#ifndef FloatType
#define FloatType float
#endif
namespace RTTL {
/// \class RTTriangleMesh
/// Vertices (for indexed meshes), primitives (triangles),
/// texture coordinates, materials, and geometric normals.
/// Some of the entries might never be used.
///
/// We will define here a partially specialized instantiation of RTTriangleMesh
/// (with template parameter equal to RT_MESH_DESCRIPTOR).
/// Non-specialized instantiations of RTTriangleMesh are prohibited by law.
template<>
class RTTriangleMesh<RT_MESH_DESCRIPTOR> {
public:
// 2 possibilities:
typedef RTVec_t<3, FloatType> vec3f;
// typedef RTVec_t<3, FloatType, RTAlignedData_t<3, FloatType> > vec3f;
typedef RTVec_t<2, FloatType> vec2f;
typedef RTVec_t<3, IndexType> vec3i;
// Vertices do not exist in 'fat triangle' layout.
#if RTMESH_COMPONENT(RT_VERTEX_POSITION)
#if defined(STL_MESH_VECTORS)
typedef RTVec_t<VERTEX_SIZE, FloatType, 0> VertexAsVector;
#else
typedef RTVec_t<VERTEX_SIZE, FloatType, 16> VertexAsVector;
_ALIGN(16) // will not work with stl::vector (at least for current stl implementations).
#endif
class Vertex {
public:
/// Empty default ctor (still need it). There will be other ctors down below.
Vertex() {}
/// static typing -- it might be necessary to change it to dynamic at certain stage
/// though it will be unfortunate...
static const int m_type = RT_VERTEX_TYPE;
static _INLINE int type() { return m_type; }
/// Return # of floats in Vertex.
static _INLINE int size() { return VERTEX_SIZE; }
/// Linearization: overloaded operator* facilitates arithmetic ops over vertices.
const VertexAsVector& operator*() const { return *(VertexAsVector*)this; }
VertexAsVector& operator*() { return *(VertexAsVector*)this; }
Vertex(const VertexAsVector& vd) {
*(VertexAsVector*)this = vd;
}
explicit Vertex(const FloatType* v, int n = VERTEX_SIZE) {
// Only if it is really really needed...
memcpy((FloatType*)this, v, sizeof(FloatType) * n);
}
const VertexAsVector& operator=(const VertexAsVector& vd) {
return *(VertexAsVector*)this = vd;
}
// These are public members though should rarely be accessed directly
// (better use RTTriangleMesh access member functions).
#if RT_VERTEX_POSITION == RT_INDEXED
vec3f m_vertex_position;
#endif
#if RT_VERTEX_NORMAL == RT_VERTEXDATA
vec3f m_vertex_normal;
#endif
#if RT_VERTEX_TEXTURE1 == RT_VERTEXDATA
vec2f m_vertex_texture1;
#endif
#if RT_VERTEX_TEXTURE2 == RT_VERTEXDATA
vec2f m_vertex_texture2;
#endif
#if RT_VERTEX_TEXTURE3 == RT_VERTEXDATA
vec2f m_vertex_texture3;
#endif
#if RT_VERTEX_TEXTURE4 == RT_VERTEXDATA
vec2f m_vertex_texture4;
#endif
// Application-specific data
#if RT_VERTEX_DATA > 0
FloatType m_vertex_data[RT_VERTEX_DATA];
#endif
};
#endif
class Triangle {
public:
// These are public members though should rarely be accessed directly
// (better use RTTriangleMesh access member functions).
// Per vertex data
#if RT_VERTEX_POSITION == RT_INDEXED
vec3i m_vertex_position_index;
#elif RT_VERTEX_POSITION == RT_EMBEDDED
vec3f m_vertex_position[3];
#endif
#if RT_VERTEX_NORMAL == RT_INDEXED
vec3i m_vertex_normal_index;
#elif RT_VERTEX_NORMAL == RT_EMBEDDED
vec3f m_vertex_normal[3];
#endif
#if RT_VERTEX_TEXTURE1 == RT_INDEXED
vec3i m_vertex_texture1_index;
#elif RT_VERTEX_TEXTURE1 == RT_EMBEDDED
vec2f m_vertex_texture1[3];
#endif
#if RT_VERTEX_TEXTURE2 == RT_INDEXED
vec3i m_vertex_texture2_index;
#elif RT_VERTEX_TEXTURE2 == RT_EMBEDDED
vec2f m_vertex_texture2[3];
#endif
#if RT_VERTEX_TEXTURE2 == RT_INDEXED
vec3i m_vertex_texture3_index;
#elif RT_VERTEX_TEXTURE3 == RT_EMBEDDED
vec2f m_vertex_texture3[3];
#endif
#if RT_VERTEX_TEXTURE4 == RT_INDEXED
vec3i m_vertex_texture4_index;
#elif RT_VERTEX_TEXTURE4 == RT_EMBEDDED
vec2f m_vertex_texture4[3];
#endif
// Per triangle data
#if RT_FACE_NORMAL == RT_INDEXED
IndexType m_face_normal_index;
#elif RT_FACE_NORMAL == RT_EMBEDDED
vec3f m_face_normal;
#endif
#if RT_MATERIAL == RT_INDEXED
IndexType m_material_index;
#elif RT_MATERIAL == RT_EMBEDDED
RTMaterial m_material;
#endif
// Application-specific data
#if RT_FACE_DATA > 0
FloatType m_data[RT_FACE_DATA];
#endif
};
// RTTriangleMesh() {}
// ~RTTriangleMesh() {}
long long descriptor() const { return RT_MESH_DESCRIPTOR; }
_INLINE void clear() {
// reserve(0) forces delete.
m_triangle.reserve(0);
STORE_VERTEX_POSITION(m_vertex.reserve(0));
STORE_VERTEX_NORMAL (m_vertex_normal.reserve(0));
STORE_VERTEX_TEXTURE1(m_vertex_texture1.reserve(0));
STORE_VERTEX_TEXTURE2(m_vertex_texture2.reserve(0));
STORE_VERTEX_TEXTURE2(m_vertex_texture3.reserve(0));
STORE_VERTEX_TEXTURE4(m_vertex_texture4.reserve(0));
STORE_FACE_NORMAL (m_face_normal.reserve(0));
STORE_MATERIAL (m_material.reserve(0));
}
/// Better not to use these 2 functions directly.
Triangle& triangle(int ti) { return m_triangle[ti]; }
const Triangle& triangle(int ti) const { return m_triangle[ti]; }
template<typename T>
_INLINE T* vertexData(int ti, int vi) {
#if RT_VERTEX_DATA > 0
#if RT_VERTEX_POSITION == RT_INDEXED
int i = m_triangle[ti].m_vertex_position_index[vi];
return (T*)m_vertex[i].m_vertex_data;
#elif RT_VERTEX_POSITION == RT_COMMON
int i = 3*ti+vi;
return (T*)m_vertex[i].m_vertex_data;
#else
FATAL("vertexData");
#endif
#else
return 0;
#endif
}
template<typename T>
_INLINE T* vertexData(int vi) {
#if RT_FACE_DATA > 0
return (T*)m_vertex[vi].m_vertex_data;
#else
return 0;
#endif
}
template<typename T>
_INLINE T* triangleData(int ti) {
#if RT_FACE_DATA > 0
return (T*)m_triangle[ti].m_data;
#else
return 0;
#endif
}
// const access functions are implemented through casting to non-const ones,
// which may not be up to the highest standards, but saves space.
_INLINE const vec3f& vertexPosition(int ti, int vi) const { return (const vec3f&)((RTTriangleMesh*)this)->vertexPosition(ti, vi); }
_INLINE vec3f& vertexPosition(int ti, int vi) {
#if RT_VERTEX_POSITION == RT_EMBEDDED
return m_triangle[ti].m_vertex_position[vi];
#elif RT_VERTEX_POSITION == RT_INDEXED
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_position;
#elif RT_VERTEX_POSITION == RT_COMMON
return m_vertex[3*ti+vi].m_vertex_position;
#endif
}
_INLINE const vec3f& vertexNormal(int ti, int vi) const { return (const vec3f&)((RTTriangleMesh*)this)->vertexNormal(ti, vi); }
_INLINE vec3f& vertexNormal(int ti, int vi) {
#if RT_VERTEX_NORMAL == RT_EMBEDDED
return m_triangle[ti].m_vertex_normal[vi];
#elif RT_VERTEX_NORMAL == RT_INDEXED
int i = m_triangle[ti].m_vertex_normal_index[vi];
return m_vertex_normal[i];
#elif RT_VERTEX_NORMAL == RT_COMMON
return m_vertex_normal[3*ti+vi];
#elif RT_VERTEX_NORMAL == RT_VERTEXDATA
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_normal;
#endif
}
_INLINE const vec3f& faceNormal(int ti) const { return (const vec3f&)((RTTriangleMesh*)this)->faceNormal(ti); }
_INLINE vec3f& faceNormal(int ti) {
#if RT_FACE_NORMAL == RT_EMBEDDED
return m_triangle[ti].m_face_normal;
#elif RT_FACE_NORMAL == RT_INDEXED
int i = m_triangle[ti].m_face_normal_index;
return m_face_normal[i];
#elif RT_FACE_NORMAL == RT_COMMON
return m_face_normal[ti];
#elif RT_FACE_NORMAL == RT_NOTSET
const vec3f& v0 = vertexPosition(ti, 0);
const vec3f& v1 = vertexPosition(ti, 1);
const vec3f& v2 = vertexPosition(ti, 2);
return (v0 - v1) ^ (v0 - v2);
#endif
}
/// Per-triangle material.
_INLINE const RTMaterial& material(int ti) const { return (const RTMaterial&)((RTTriangleMesh*)this)->material(ti); }
_INLINE RTMaterial& material(int ti) {
#if RT_MATERIAL == RT_EMBEDDED
return m_triangle[ti].m_material;
#elif RT_MATERIAL == RT_INDEXED
int i = m_triangle[ti].m_material_index;
return m_material[i];
#elif RT_MATERIAL == RT_COMMON
return m_material[ti];
#endif
}
/// There isn't anything better than replication...
_INLINE const vec2f& texture1(int ti, int vi) const { return (const vec2f&)((RTTriangleMesh*)this)->texture1(ti, vi); }
_INLINE vec2f& texture1(int ti, int vi) {
#if RT_VERTEX_TEXTURE1 == RT_EMBEDDED
return m_triangle[ti].m_vertex_texture1[vi];
#elif RT_VERTEX_TEXTURE1 == RT_INDEXED
int i = m_triangle[ti].m_vertex_texture1_index[vi];
return m_vertex_texture1[i];
#elif RT_VERTEX_TEXTURE1 == RT_COMMON
return m_vertex_texture1[3*ti+vi];
#elif RT_VERTEX_TEXTURE1 == RT_VERTEXDATA
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_texture1;
#elif RT_VERTEX_TEXTURE1 == RT_NOTSET
return vec2f(-1, -1);
#endif
}
_INLINE const vec2f& texture2(int ti, int vi) const { return (const vec2f&)((RTTriangleMesh*)this)->texture2(ti, vi); }
_INLINE vec2f& texture2(int ti, int vi) {
#if RT_VERTEX_TEXTURE2 == RT_EMBEDDED
return m_triangle[ti].m_vertex_texture2[vi];
#elif RT_VERTEX_TEXTURE2 == RT_INDEXED
int i = m_triangle[ti].m_vertex_texture2_index[vi];
return m_vertex_texture2[i];
#elif RT_VERTEX_TEXTURE2 == RT_COMMON
return m_vertex_texture2[3*ti+vi];
#elif RT_VERTEX_TEXTURE2 == RT_VERTEXDATA
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_texture2;
#else
return vec2f(-1, -1);
#endif
}
_INLINE const vec2f& texture3(int ti, int vi) const { return (const vec2f&)((RTTriangleMesh*)this)->texture3(ti, vi); }
_INLINE vec2f& texture3(int ti, int vi) {
#if RT_VERTEX_TEXTURE3 == RT_EMBEDDED
return m_triangle[ti].m_vertex_texture3[vi];
#elif RT_VERTEX_TEXTURE3 == RT_INDEXED
int i = m_triangle[ti].m_vertex_texture3_index[vi];
return m_vertex_texture3[i];
#elif RT_VERTEX_TEXTURE3 == RT_COMMON
return m_vertex_texture3[3*ti+vi];
#elif RT_VERTEX_TEXTURE3 == RT_VERTEXDATA
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_texture3;
#else
return vec2f(-1, -1);
#endif
}
_INLINE const vec2f& texture4(int ti, int vi) const { return (const vec2f&)((RTTriangleMesh*)this)->texture4(ti, vi); }
_INLINE vec2f& texture4(int ti, int vi) {
#if RT_VERTEX_TEXTURE4 == RT_EMBEDDED
return m_triangle[ti].m_vertex_texture4[vi];
#elif RT_VERTEX_TEXTURE4 == RT_INDEXED
int i = m_triangle[ti].m_vertex_texture4_index[vi];
return m_vertex_texture4[i];
#elif RT_VERTEX_TEXTURE4 == RT_COMMON
return m_vertex_texture4[3*ti+vi];
#elif RT_VERTEX_TEXTURE4 == RT_VERTEXDATA
int i = m_triangle[ti].m_vertex_position_index[vi];
return m_vertex[i].m_vertex_texture4;
#else
return vec2f(-1, -1);
#endif
}
_INLINE int numberOfTriangles() { return m_triangle.size(); }
STORE_VERTEX_POSITION(_INLINE int numberOfVertices() { return m_vertex.size(); })
STORE_VERTEX_NORMAL (_INLINE int numberOfVertexNormals() { return m_vertex_normal.size(); })
STORE_VERTEX_TEXTURE1(_INLINE int numberOfTextureCoordinates1() { return m_vertex_texture1.size(); })
STORE_VERTEX_TEXTURE2(_INLINE int numberOfTextureCoordinates2() { return m_vertex_texture2.size(); })
STORE_VERTEX_TEXTURE2(_INLINE int numberOfTextureCoordinates3() { return m_vertex_texture3.size(); })
STORE_VERTEX_TEXTURE4(_INLINE int numberOfTextureCoordinates4() { return m_vertex_texture4.size(); })
STORE_FACE_NORMAL (_INLINE int numberOfFaceNormals() { return m_face_normal.size(); })
STORE_MATERIAL (_INLINE int numberOfMaterials() { return m_material.size(); })
/// Reservations are not necessary, but advised :)
_INLINE void setNumberOfTriangles(int n) { m_triangle.reserve(n); }
STORE_VERTEX_POSITION(_INLINE void setNumberOfVertices(int n) { m_vertex.reserve(n); })
STORE_VERTEX_NORMAL (_INLINE void setNumberOfVertexNormals(int n) { m_vertex_normal.reserve(n); })
STORE_VERTEX_TEXTURE1(_INLINE void setNumberOfTextureCoordinates1(int n) { m_vertex_texture1.reserve(n); })
STORE_VERTEX_TEXTURE2(_INLINE void setNumberOfTextureCoordinates2(int n) { m_vertex_texture2.reserve(n); })
STORE_VERTEX_TEXTURE2(_INLINE void setNumberOfTextureCoordinates3(int n) { m_vertex_texture3.reserve(n); })
STORE_VERTEX_TEXTURE4(_INLINE void setNumberOfTextureCoordinates4(int n) { m_vertex_texture4.reserve(n); })
STORE_FACE_NORMAL (_INLINE void setNumberOfFaceNormals(int n) { m_face_normal.reserve(n); })
STORE_MATERIAL (_INLINE void setNumberOfMaterials(int n) { m_material.reserve(n); })
// Multiple flavors of addSomething functions.
int addVertexPosition(const vec3f& v0, int vi = -1) {
#if RT_VERTEX_POSITION == RT_EMBEDDED
FATAL("addVertexPosition");
#else
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_position = v0;
#endif
return vi;
}
int addVertexNormal(const vec3f& v0, int vi = -1) {
#if RT_VERTEX_NORMAL == RT_EMBEDDED
FATAL("addVertexNormal");
#elif RT_VERTEX_NORMAL == RT_COMMON || RT_VERTEX_NORMAL == RT_INDEXED
if (vi == -1) vi = m_vertex_normal.add();
m_vertex_normal[vi] = v0;
#elif RT_VERTEX_NORMAL == RT_VERTEXDATA
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_normal = v0;
#endif
return vi;
}
int addVertexTexture1(const vec2f& v0, int vi = -1) {
#if RT_VERTEX_TEXTURE1 == RT_EMBEDDED
FATAL("addVertexTexture1");
#elif RT_VERTEX_TEXTURE1 == RT_COMMON || RT_VERTEX_TEXTURE1 == RT_INDEXED
if (vi == -1) vi = m_vertex_texture1.add();
m_vertex_texture1[vi] = v0;
#elif RT_VERTEX_TEXTURE1 == RT_VERTEXDATA
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_texture1 = v0;
#endif
return vi;
}
int addVertexTexture2(const vec2f& v0, int vi = -1) {
#if RT_VERTEX_TEXTURE2 == RT_EMBEDDED
FATAL("addVertexTexture2");
#elif RT_VERTEX_TEXTURE2 == RT_COMMON || RT_VERTEX_TEXTURE2 == RT_INDEXED
if (vi == -1) vi = m_vertex_texture2.add();
m_vertex_texture2[vi] = v0;
#elif RT_VERTEX_TEXTURE2 == RT_VERTEXDATA
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_texture2 = v0;
#endif
return vi;
}
int addVertexTexture3(const vec2f& v0, int vi = -1) {
#if RT_VERTEX_TEXTURE3 == RT_EMBEDDED
FATAL("addVertexTexture3");
#elif RT_VERTEX_TEXTURE3 == RT_COMMON || RT_VERTEX_TEXTURE3 == RT_INDEXED
if (vi == -1) vi = m_vertex_texture3.add();
m_vertex_texture3[vi] = v0;
#elif RT_VERTEX_TEXTURE3 == RT_VERTEXDATA
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_texture3 = v0;
#endif
return vi;
}
int addVertexTexture4(const vec2f& v0, int vi = -1) {
#if RT_VERTEX_TEXTURE4 == RT_EMBEDDED
FATAL("addVertexTexture4");
#elif RT_VERTEX_TEXTURE4 == RT_COMMON || RT_VERTEX_TEXTURE4 == RT_INDEXED
if (vi == -1) vi = m_vertex_texture4.add();
m_vertex_texture4[vi] = v0;
#elif RT_VERTEX_TEXTURE4 == RT_VERTEXDATA
if (vi == -1) vi = m_vertex.add();
m_vertex[vi].m_vertex_texture4 = v0;
#endif
return vi;
}
/// Some possible combinations are implemented here;
/// all other data could be added by obtianing index with addTriangle()
/// and then using data access functions for specific layouts.
/// Indices:
/// ti -- triangle index
/// vi -- vertex position index
/// ni -- vertex normal index
/// mi -- material index
/// fi -- face normal index
_INLINE int addTriangle() {
// Return index of the next triangle.
return m_triangle.add();
}
_INLINE int addTriangle(int i0, int i1, int i2) {
return addTriangle(RTVec3i(i0, i1, i2));
}
_INLINE int addTriangle(const RTVec3i& vi) {
int ti = addTriangle();
#if RT_VERTEX_POSITION == RT_INDEXED
m_triangle[ti].m_vertex_position_index = vi;
#endif
return ti;
}
_INLINE int addTriangle(const RTVec3i& vi, int mi) {
int ti = addTriangle(vi);
#if RT_MATERIAL == RT_INDEXED
m_triangle[ti].m_material_index = mi;
#endif
return ti;
}
_INLINE int addTriangle(const RTVec3i& vi, const RTVec3i& ni) {
int ti = addTriangle(vi);
#if RT_VERTEX_NORMAL == RT_INDEXED
m_triangle[ti].m_vertex_normal_index = vi;
#endif
return ti;
}
_INLINE int addTriangle(const RTVec3i& vi, const RTVec3i& ni, int mi) {
int ti = addTriangle(vi, ni);
#if RT_VERTEX_NORMAL == RT_INDEXED
m_triangle[ti].m_vertex_normal_index = vi;
#endif
return ti;
}
_INLINE int addTriangleNormal(int ti = -1) {
if (ti == -1) {
// Use the last triangle if ti is not defined.
ti = m_triangle.size() - 1;
}
// Compute it on the fly and store in apropriate place.
const vec3f& v0 = vertexPosition(ti, 0);
const vec3f& v1 = vertexPosition(ti, 1);
const vec3f& v2 = vertexPosition(ti, 2);
vec3f n = (v0 - v1) ^ (v0 - v2);
// n.normalize(); // do we care?
return addTriangleNormal(ti, n);
}
_INLINE int addTriangleNormal(int ti, const vec3f& n) {
// Store it in apropriate place.
#if RT_FACE_NORMAL == RT_INDEXED
m_triangle[ti].m_face_normal_index = m_face_normal.add(n);
#elif RT_FACE_NORMAL == RT_EMBEDDED
m_triangle[ti].m_face_normal = n;
#endif
return ti;
}
_INLINE int addTriangleNormal(int ti, int fi) {
// Store it in apropriate place.
#if RT_FACE_NORMAL == RT_INDEXED
m_triangle[ti].m_face_normal_index = fi;
#elif RT_FACE_NORMAL == RT_EMBEDDED
FATAL("addTriangleNormal");
#endif
return ti;
}
protected:
// Mesh components (defined by RT_* macro definitions in the caller, like RTmesh.hxx).
// Not using plural noons since all these entries are arrays.
/// Triangles
RTArray_t<Triangle> m_triangle;
/// Vertices (indexed in m_triangle).
#if RTMESH_COMPONENT(RT_VERTEX_POSITION)
RTArray_t<Vertex> m_vertex;
#endif
/// Extra vertex data (indexed in m_triangle or implicitly).
/// If it is not here, than it is inside m_vertex or RT_NOTSET).
#if RTMESH_COMPONENT(RT_VERTEX_NORMAL)
RTArray_t<vec3f> m_vertex_normal;
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE1)
RTArray_t<vec2f, -1> m_vertex_texture1;
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE2)
RTArray_t<vec2f, -1> m_vertex_texture2;
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE2)
RTArray_t<vec2f, -1> m_vertex_texture3;
#endif
#if RTMESH_COMPONENT(RT_VERTEX_TEXTURE4)
RTArray_t<vec2f, -1> m_vertex_texture4;
#endif
/// Extra vertex data (indexed in m_triangle or implicitly).
/// If it is not here, than it is inside m_vertex or RT_NOTSET).
#if RTMESH_COMPONENT(RT_FACE_NORMAL)
RTArray_t<vec3f> m_face_normal;
#endif
#if RTMESH_COMPONENT(RT_MATERIAL)
RTArray_t<RTMaterial, -1> m_material;
#endif
};
/// Streaming.
#if RTMESH_COMPONENT(RT_VERTEX_POSITION)
_INLINE ostream& operator<<(ostream& out, const RTTriangleMesh<RT_MESH_DESCRIPTOR>::Vertex& v) {
FloatType* data = (FloatType*)&v;
bool not_defined = false;
int i;
for (i = 0; i < v.size(); i++) not_defined |= NOTINITIALIZED(data[i]);
if (not_defined) {
out << "[not defined]";
goto done;
}
out << "[" << data[0];
for (i = 1; i < v.size(); i++) {
not_defined |= NOTINITIALIZED(data[i]);
out << "," << (i!=3 && i!=6? " ":"\t");
out << data[i];
}
out << "]";
done:
return out;
}
#endif
_INLINE ostream& operator<<(ostream& out, const RTTriangleMesh<RT_MESH_DESCRIPTOR>::Triangle& t) {
// There is a limited output functionality for a triangle without underlying mesh,
// mostly for debugging.
// Per vertex data
#if RT_VERTEX_POSITION == RT_INDEXED
out << "m_vertex_position_index\t= ";
if (NOTINITIALIZED(t.m_vertex_position_index))
out << "not defined\n";
else
out << t.m_vertex_position_index << endl;
#elif RT_VERTEX_POSITION == RT_EMBEDDED
out << "m_vertex_position\t = [";
if (NOTINITIALIZED(t.m_vertex_position[0]) || NOTINITIALIZED(t.m_vertex_position[1]) || NOTINITIALIZED(t.m_vertex_position[2]))
out << "not defined\n";
else
out << t.m_vertex_position[0] << ", " << t.m_vertex_position[1] << ", " << t.m_vertex_position[2] << "]" << endl;
#endif
#if RT_VERTEX_NORMAL == RT_INDEXED
out << "m_vertex_normal_index\t = ";
if (NOTINITIALIZED(t.m_vertex_normal_index))
out << "not defined\n";
else
out << t.m_vertex_normal_index << endl;
#elif RT_VERTEX_NORMAL == RT_EMBEDDED
out << "m_vertex_normal\t = [";
if (NOTINITIALIZED(t.m_vertex_normal[0]) || NOTINITIALIZED(t.m_vertex_normal[1]) || NOTINITIALIZED(t.m_vertex_normal[2]))
out << "not defined]\n";
else
out << t.m_vertex_normal[0] << ", " << t.m_vertex_normal[1] << ", " << t.m_vertex_normal[2] << "]" << endl;
#endif
#if RT_VERTEX_TEXTURE1 == RT_INDEXED
out << "m_vertex_texture1_index\t = ";
if (NOTINITIALIZED(t.m_vertex_texture1_index))
out << "not defined\n";
else
out << t.m_vertex_texture1_index << endl;
#elif RT_VERTEX_TEXTURE1 == RT_EMBEDDED
out << "m_vertex_texture1\t = [";
if (NOTINITIALIZED(t.m_vertex_texture1[0]) || NOTINITIALIZED(t.m_vertex_texture1[1]))
out << "not defined]\n";
else
out << t.m_vertex_texture1[0] << ", " << t.m_vertex_texture1[1] << "]" << endl;
#endif
#if RT_VERTEX_TEXTURE2 == RT_INDEXED
out << "m_vertex_texture2_index\t = ";
if (NOTINITIALIZED(t.m_vertex_texture2_index))
out << "not defined\n";
else
out << t.m_vertex_texture2_index << endl;
#elif RT_VERTEX_TEXTURE2 == RT_EMBEDDED
out << "m_vertex_texture2\t = [";
if (NOTINITIALIZED(t.m_vertex_texture2[0]) || NOTINITIALIZED(t.m_vertex_texture2[1]))
out << "not defined]\n";
else
out << t.m_vertex_texture2[0] << ", " << t.m_vertex_texture2[1] << ", " << t.m_vertex_texture2[2] << "]" << endl;
#endif
#if RT_VERTEX_TEXTURE2 == RT_INDEXED
out << "m_vertex_texture3_index\t = ";
if (NOTINITIALIZED(t.m_vertex_texture1[0]) || NOTINITIALIZED(t.m_vertex_texture1[1]))
if (NOTINITIALIZED(t.m_vertex_texture3_index))
out << "not defined\n";
else
out << t.m_vertex_texture3_index << endl;
#elif RT_VERTEX_TEXTURE3 == RT_EMBEDDED
out << "m_vertex_texture3\t = [";
if (NOTINITIALIZED(t.m_vertex_texture3[0]) || NOTINITIALIZED(t.m_vertex_texture3[1]))
out << "not defined]\n";
else
out << t.m_vertex_texture3[0] << ", " << t.m_vertex_texture3[1] << ", " << t.m_vertex_texture3[2] << "]" << endl;
#endif
#if RT_VERTEX_TEXTURE4 == RT_INDEXED
out << "m_vertex_texture4_index\t = ";
if (NOTINITIALIZED(t.m_vertex_texture4_index))
out << "not defined\n";
else
out << t.m_vertex_texture4_index << endl;
#elif RT_VERTEX_TEXTURE4 == RT_EMBEDDED
out << "m_vertex_texture4\t = [";
if (NOTINITIALIZED(t.m_vertex_texture4[0]) || NOTINITIALIZED(t.m_vertex_texture4[1]))
out << "not defined]\n";
else
out << t.m_vertex_texture4[0] << ", " << t.m_vertex_texture4[1] << ", " << t.m_vertex_texture4[2] << "]" << endl;
#endif
// Per triangle data
#if RT_FACE_NORMAL == RT_INDEXED
out << "m_face_normal_index\t = ";
if (NOTINITIALIZED(t.m_face_normal_index))
out << "not defined\n";
else
out << t.m_face_normal_index << endl;
#elif RT_FACE_NORMAL == RT_EMBEDDED
out << "m_face_normal\t = ";
if (NOTINITIALIZED(t.m_face_normal.x) || NOTINITIALIZED(t.m_face_normal.y) || NOTINITIALIZED(t.m_face_normal.z))
out << "[not defined]\n";
else
out << t.m_face_normal << endl;
#endif
#if RT_MATERIAL == RT_INDEXED
out << "m_material_index\t = ";
if (NOTINITIALIZED(t.m_material_index))
out << "not defined\n";
else
out << t.m_material_index << endl;
#elif RT_MATERIAL == RT_EMBEDDED
out << "m_material\t = ";
if (NOTINITIALIZED(t.m_material))
out << "not defined\n";
else
out << t.m_material << endl;
#endif
#if RT_FACE_DATA > 0
out << "extra data\t = [";
if (NOTINITIALIZED(t.m_data[0])) {
out << "not defined]\n";
} else {
out << t.m_data[0];
for (int i = 1; i < RT_FACE_DATA; i++) {
out << ", " << t.m_data[i];
}
out << "]" << endl;
}
#endif
return out;
}
// Undefined these definitions to allow a new invocation of this file.
#undef RT_VERTEX_POSITION
#undef RT_VERTEX_NORMAL
#undef RT_VERTEX_TEXTURE1
#undef RT_VERTEX_TEXTURE2
#undef RT_VERTEX_TEXTURE3
#undef RT_VERTEX_TEXTURE4
#undef RT_FACE_NORMAL
#undef RT_MATERIAL
#undef STORE_VERTEX_POSITION
#undef STORE_VERTEX_NORMAL
#undef STORE_VERTEX_TEXTURE1
#undef STORE_VERTEX_TEXTURE2
#undef STORE_VERTEX_TEXTURE2
#undef STORE_VERTEX_TEXTURE4
#undef STORE_FACE_NORMAL
#undef STORE_MATERIAL
#undef RT_VERTEX_DATA
#undef RT_FACE_DATA
#undef IndexType
#undef FloatType
#pragma warning(pop)
};