364 lines
11 KiB
C++
364 lines
11 KiB
C++
/*
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
Copyright (c) 2007-2012 by Wenzel Jakob and others.
|
|
|
|
Mitsuba is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License Version 3
|
|
as published by the Free Software Foundation.
|
|
|
|
Mitsuba is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
#if !defined(__MITSUBA_RENDER_TRIMESH_H_)
|
|
#define __MITSUBA_RENDER_TRIMESH_H_
|
|
|
|
#include <mitsuba/core/triangle.h>
|
|
#include <mitsuba/core/pmf.h>
|
|
#include <mitsuba/render/shape.h>
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
/**
|
|
* \brief Simple tangent space storage for surfaces
|
|
*
|
|
* Note that the \ref dpdu and \ref dpdv vectors are not
|
|
* necessarily orthogonal.
|
|
*
|
|
* \ingroup librender
|
|
*/
|
|
struct TangentSpace {
|
|
/// Position partial with respect to the U parameter of the local chart
|
|
Vector dpdu;
|
|
|
|
/// Position partial with respect to the V parameter of the local chart
|
|
Vector dpdv;
|
|
|
|
inline TangentSpace() { }
|
|
inline TangentSpace(Stream *stream) :
|
|
dpdu(stream), dpdv(stream) {
|
|
}
|
|
|
|
inline void serialize(Stream *stream) {
|
|
dpdu.serialize(stream);
|
|
dpdv.serialize(stream);
|
|
}
|
|
};
|
|
|
|
/** \brief Abstract triangle mesh base class
|
|
* \ingroup librender
|
|
* \ingroup libpython
|
|
*/
|
|
class MTS_EXPORT_RENDER TriMesh : public Shape {
|
|
public:
|
|
/// Create a new, empty triangle mesh with the specified state
|
|
TriMesh(const std::string &name,
|
|
size_t triangleCount, size_t vertexCount,
|
|
bool hasNormals = false,
|
|
bool hasTexcoords = false,
|
|
bool hasVertexColors = false,
|
|
bool flipNormals = false,
|
|
bool faceNormals = false);
|
|
|
|
/// Unserialize a triangle mesh
|
|
TriMesh(Stream *stream, InstanceManager *manager);
|
|
|
|
/**
|
|
* Unserialize a triangle mesh - this is an alternative
|
|
* routine, which only loads triangle data (no BSDF,
|
|
* Sub-surface integrator, etc.) in a format that
|
|
* will remain stable as Mitsuba evolves. The files
|
|
* can optionally contain multiple meshes -- in that case,
|
|
* the specified index determines which one to load.
|
|
*/
|
|
TriMesh(Stream *stream, int idx = 0);
|
|
|
|
// =============================================================
|
|
//! @{ \name General query functions
|
|
// =============================================================
|
|
|
|
/// Return the name of this shape (e.g. the filename)
|
|
std::string getName() const;
|
|
|
|
/// Return the total surface area
|
|
Float getSurfaceArea() const;
|
|
|
|
/// Return a bounding box containing the mesh
|
|
AABB getAABB() const;
|
|
|
|
/// Return a bounding box containing the mesh
|
|
inline AABB &getAABB() { return m_aabb; }
|
|
|
|
/**
|
|
* \brief Create a triangle mesh approximation of this shape
|
|
*
|
|
* Since instances are already triangle meshes, the implementation
|
|
* just returns a pointer to \a this.
|
|
*/
|
|
ref<TriMesh> createTriMesh();
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Access to the stored triangle mesh
|
|
// =============================================================
|
|
|
|
/// Return the number of triangles
|
|
inline size_t getTriangleCount() const { return m_triangleCount; }
|
|
/// Return the number of vertices
|
|
inline size_t getVertexCount() const { return m_vertexCount; }
|
|
|
|
/// Return the triangle list (const version)
|
|
inline const Triangle *getTriangles() const { return m_triangles; };
|
|
/// Return the triangle list
|
|
inline Triangle *getTriangles() { return m_triangles; };
|
|
|
|
/// Return the vertex positions (const version)
|
|
inline const Point *getVertexPositions() const { return m_positions; };
|
|
/// Return the vertex positions
|
|
inline Point *getVertexPositions() { return m_positions; };
|
|
|
|
/// Return the vertex normals (const version)
|
|
inline const Normal *getVertexNormals() const { return m_normals; };
|
|
/// Return the vertex normals
|
|
inline Normal *getVertexNormals() { return m_normals; };
|
|
/// Does the mesh have vertex normals?
|
|
inline bool hasVertexNormals() const { return m_normals != NULL; };
|
|
|
|
/// Return the vertex colors (const version)
|
|
inline const Color3 *getVertexColors() const { return m_colors; };
|
|
/// Return the vertex colors
|
|
inline Color3 *getVertexColors() { return m_colors; };
|
|
/// Does the mesh have vertex colors?
|
|
inline bool hasVertexColors() const { return m_colors != NULL; };
|
|
|
|
/// Return the vertex texture coordinates (const version)
|
|
inline const Point2 *getVertexTexcoords() const { return m_texcoords; };
|
|
/// Return the vertex texture coordinates
|
|
inline Point2 *getVertexTexcoords() { return m_texcoords; };
|
|
/// Does the mesh have vertex texture coordinates?
|
|
inline bool hasVertexTexcoords() const { return m_texcoords != NULL; };
|
|
|
|
/// Return the per-triangle UV tangents (const version)
|
|
inline const TangentSpace *getUVTangents() const { return m_tangents; };
|
|
/// Return the per-triangle UV tangents
|
|
inline TangentSpace *getUVTangents() { return m_tangents; };
|
|
/// Does the mesh have UV tangent information?
|
|
inline bool hasUVTangents() const { return m_tangents != NULL; };
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Sampling routines
|
|
// =============================================================
|
|
|
|
/**
|
|
* \brief Sample a point on the surface of this shape instance
|
|
* (with respect to the area measure)
|
|
*
|
|
* The returned sample density will be uniform over the surface.
|
|
*
|
|
* \param pRec
|
|
* A position record, which will be used to return the sampled
|
|
* position, as well as auxilary information about the sample.
|
|
*
|
|
* \param sample
|
|
* A uniformly distributed 2D vector
|
|
*/
|
|
void samplePosition(PositionSamplingRecord &pRec,
|
|
const Point2 &sample) const;
|
|
|
|
/**
|
|
* \brief Query the probability density of \ref samplePosition() for
|
|
* a particular point on the surface.
|
|
*
|
|
* This method will generally return the inverse of the surface area.
|
|
*
|
|
* \param pRec
|
|
* A position record, which will be used to return the sampled
|
|
* position, as well as auxilary information about the sample.
|
|
*/
|
|
|
|
Float pdfPosition(const PositionSamplingRecord &pRec) const;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Miscellaneous
|
|
// =============================================================
|
|
|
|
/**
|
|
* \brief Generate per-triangle space basis vectors from
|
|
* a user-specified set of UV coordinates
|
|
*
|
|
* Will throw an exception when no UV coordinates are
|
|
* associated with the mesh.
|
|
*/
|
|
void computeUVTangents();
|
|
|
|
/**
|
|
* \brief Generate smooth vertex normals?
|
|
*
|
|
* \param force
|
|
* When this parameter is set to true, the function
|
|
* generates normals <em>even</em> when there are
|
|
* already existing ones.
|
|
*/
|
|
void computeNormals(bool force = false);
|
|
|
|
/**
|
|
* \brief Rebuild the mesh so that adjacent faces
|
|
* with a dihedral angle greater than \c maxAngle degrees
|
|
* are topologically disconnected.
|
|
*
|
|
* On the other hand, if the angle is less than \a maxAngle, the code
|
|
* ensures that the faces reference the same vertices.
|
|
* This step is very useful as a pre-process when generating
|
|
* high-quality smooth shading normals on meshes with creases.
|
|
* Note: this function is fairly memory intensive and will require
|
|
* approximately three 3x the storate used by the input mesh.
|
|
* It will never try to merge vertices with equal positions but
|
|
* different UV coordinates or vertex colors.
|
|
*/
|
|
void rebuildTopology(Float maxAngle);
|
|
|
|
/// Serialize to a file/network stream
|
|
void serialize(Stream *stream, InstanceManager *manager) const;
|
|
|
|
/**
|
|
* \brief Serialize to a file/network stream
|
|
*
|
|
* This is an alternative routine, which \a only loads triangle
|
|
* data (no BSDF, Sub-surface integrator, etc.) in a format that
|
|
* will remain stable as Mitsuba evolves.
|
|
*/
|
|
void serialize(Stream *stream) const;
|
|
|
|
/**
|
|
* \brief Build a discrete probability distribution
|
|
* for sampling.
|
|
*
|
|
* Called once while loading the scene
|
|
*/
|
|
virtual void configure();
|
|
|
|
/**
|
|
* \brief Return the derivative of the normal vector with
|
|
* respect to the UV parameterization
|
|
*
|
|
* This can be used to compute Gaussian and principal curvatures,
|
|
* amongst other things.
|
|
*
|
|
* \param its
|
|
* Intersection record associated with the query
|
|
* \param dndu
|
|
* Parameter used to store the partial derivative of the
|
|
* normal vector with respect to \c u
|
|
* \param dndv
|
|
* Parameter used to store the partial derivative of the
|
|
* normal vector with respect to \c v
|
|
* \param shadingFrame
|
|
* Specifies whether to compute the derivative of the
|
|
* geometric or shading normal of the surface
|
|
*/
|
|
void getNormalDerivative(const Intersection &its,
|
|
Vector &dndu, Vector &dndv, bool shadingFrame) const;
|
|
|
|
/**
|
|
* \brief Return the number of primitives (triangles, hairs, ..)
|
|
* contributed to the scene by this shape
|
|
*
|
|
* Does not include instanced geometry
|
|
*/
|
|
size_t getPrimitiveCount() const;
|
|
|
|
/**
|
|
* \brief Return the number of primitives (triangles, hairs, ..)
|
|
* contributed to the scene by this shape
|
|
*
|
|
* Includes instanced geometry
|
|
*/
|
|
size_t getEffectivePrimitiveCount() const;
|
|
|
|
/// Export an Wavefront OBJ version of this file
|
|
void writeOBJ(const fs::path &path) const;
|
|
|
|
/// Return a string representation
|
|
std::string toString() const;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
MTS_DECLARE_CLASS()
|
|
protected:
|
|
/// Create a new triangle mesh
|
|
TriMesh(const Properties &props);
|
|
|
|
/// Virtual destructor
|
|
virtual ~TriMesh();
|
|
|
|
/// Load a Mitsuba compressed triangle mesh substream
|
|
void loadCompressed(Stream *stream, int idx = 0);
|
|
|
|
/**
|
|
* \brief Reads the header information of a compressed file, returning
|
|
* the version ID. This function assumes the stream is at the beginning
|
|
* of the compressed file and leaves the stream located right after the
|
|
* header.
|
|
*/
|
|
static short readHeader(Stream *stream);
|
|
|
|
/**
|
|
* \brief Read the idx-th entry from the offset diccionary at the end of
|
|
* the stream, which has to be open already, given the file version tag.
|
|
* This function modifies the position of the stream.
|
|
*/
|
|
static size_t readOffset(Stream *stream, short version, int idx);
|
|
|
|
/**
|
|
* \brief Read the entirety of the end-of-file offset dictionary from the
|
|
* already open stream, replacing the contents of the input vector.
|
|
* If the file is not large enough the function returns -1
|
|
* and does not modify the vector.
|
|
* This function modifies the position of the stream.
|
|
*/
|
|
static int readOffsetDictionary(Stream *stream, short version,
|
|
std::vector<size_t>& outOffsets);
|
|
|
|
/// Prepare internal tables for sampling uniformly wrt. area
|
|
void prepareSamplingTable();
|
|
protected:
|
|
std::string m_name;
|
|
AABB m_aabb;
|
|
Triangle *m_triangles;
|
|
Point *m_positions;
|
|
Normal *m_normals;
|
|
Point2 *m_texcoords;
|
|
TangentSpace *m_tangents;
|
|
Color3 *m_colors;
|
|
size_t m_triangleCount;
|
|
size_t m_vertexCount;
|
|
bool m_flipNormals;
|
|
bool m_faceNormals;
|
|
|
|
/* Surface and distribution -- generated on demand */
|
|
DiscreteDistribution m_areaDistr;
|
|
Float m_surfaceArea;
|
|
Float m_invSurfaceArea;
|
|
ref<Mutex> m_mutex;
|
|
};
|
|
|
|
MTS_NAMESPACE_END
|
|
|
|
#endif /* __MITSUBA_RENDER_TRIMESH_H_ */
|