work on sutherland-hodgman, allow to set log level to errors only
parent
6185149b86
commit
46dcdc4100
|
@ -29,14 +29,14 @@ MTS_NAMESPACE_BEGIN
|
|||
* vertex normals, UV coordinates and a tangent frame.
|
||||
*/
|
||||
struct Vertex {
|
||||
Point v; ///< %Vertex position
|
||||
Normal n; ///< %Vertex normal
|
||||
Point p; ///< %Position
|
||||
Normal n; ///< %Normal
|
||||
Point2 uv; ///< %Texture coordinates
|
||||
Vector dpdu; ///< Partial derivative of the position with respect to \a u.
|
||||
Vector dpdv; ///< Partial derivative of the position with respect to \a v.
|
||||
|
||||
inline bool operator==(const Vertex &vert) const {
|
||||
return (v == vert.v && n == vert.n && uv == vert.uv
|
||||
return (p == vert.p && n == vert.n && uv == vert.uv
|
||||
&& dpdu == vert.dpdu && dpdv == vert.dpdv);
|
||||
}
|
||||
|
||||
|
|
|
@ -208,12 +208,12 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
struct vertex_key_order : public
|
||||
std::binary_function<Vertex, Vertex, bool> {
|
||||
static int compare(const Vertex &v1, const Vertex &v2) {
|
||||
if (v1.v.x < v2.v.x) return -1;
|
||||
else if (v1.v.x > v2.v.x) return 1;
|
||||
if (v1.v.y < v2.v.y) return -1;
|
||||
else if (v1.v.y > v2.v.y) return 1;
|
||||
if (v1.v.z < v2.v.z) return -1;
|
||||
else if (v1.v.z > v2.v.z) return 1;
|
||||
if (v1.p.x < v2.p.x) return -1;
|
||||
else if (v1.p.x > v2.p.x) return 1;
|
||||
if (v1.p.y < v2.p.y) return -1;
|
||||
else if (v1.p.y > v2.p.y) return 1;
|
||||
if (v1.p.z < v2.p.z) return -1;
|
||||
else if (v1.p.z > v2.p.z) return 1;
|
||||
if (v1.n.x < v2.n.x) return -1;
|
||||
else if (v1.n.x > v2.n.x) return 1;
|
||||
if (v1.n.y < v2.n.y) return -1;
|
||||
|
@ -282,7 +282,7 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
for (size_t i=0; i<tess_data.size(); i+=tess_nSources) {
|
||||
Vertex vertex;
|
||||
domUint posRef = tess_data[i+vData->typeToOffsetInStream[EPosition]];
|
||||
vertex.v = vData->data[vData->typeToOffset[EPosition]][posRef].toPoint();
|
||||
vertex.p = vData->data[vData->typeToOffset[EPosition]][posRef].toPoint();
|
||||
|
||||
if (vData->typeToOffset[ENormal] != -1) {
|
||||
domUint normalRef = tess_data[i+vData->typeToOffsetInStream[ENormal]];
|
||||
|
@ -306,9 +306,9 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
|
||||
triangle.idx[triangleIdx++] = key;
|
||||
if (triangleIdx == 3) {
|
||||
Point p0 = vertexBuffer[triangle.idx[0]].v,
|
||||
p1 = vertexBuffer[triangle.idx[1]].v,
|
||||
p2 = vertexBuffer[triangle.idx[2]].v;
|
||||
Point p0 = vertexBuffer[triangle.idx[0]].p,
|
||||
p1 = vertexBuffer[triangle.idx[1]].p,
|
||||
p2 = vertexBuffer[triangle.idx[2]].p;
|
||||
if (triMap.find(SimpleTriangle(p0, p1, p2)) != triMap.end() ||
|
||||
triMap.find(SimpleTriangle(p2, p0, p1)) != triMap.end() ||
|
||||
triMap.find(SimpleTriangle(p1, p2, p0)) != triMap.end() ||
|
||||
|
|
|
@ -22,9 +22,9 @@ MTS_NAMESPACE_BEGIN
|
|||
|
||||
bool Triangle::rayIntersect(const Vertex *buffer, const Ray &ray,
|
||||
Float &u, Float &v, Float &t) const {
|
||||
const Point &v0 = buffer[idx[0]].v;
|
||||
const Point &v1 = buffer[idx[1]].v;
|
||||
const Point &v2 = buffer[idx[2]].v;
|
||||
const Point &v0 = buffer[idx[0]].p;
|
||||
const Point &v1 = buffer[idx[1]].p;
|
||||
const Point &v2 = buffer[idx[2]].p;
|
||||
|
||||
/* find vectors for two edges sharing v[0] */
|
||||
Vector edge1 = v1 - v0, edge2 = v2 - v0;
|
||||
|
@ -63,9 +63,9 @@ bool Triangle::rayIntersect(const Vertex *buffer, const Ray &ray,
|
|||
|
||||
Point Triangle::sample(const Vertex *buffer, Normal &normal,
|
||||
const Point2 &sample) const {
|
||||
const Point &v0 = buffer[idx[0]].v;
|
||||
const Point &v1 = buffer[idx[1]].v;
|
||||
const Point &v2 = buffer[idx[2]].v;
|
||||
const Point &v0 = buffer[idx[0]].p;
|
||||
const Point &v1 = buffer[idx[1]].p;
|
||||
const Point &v2 = buffer[idx[2]].p;
|
||||
const Normal &n0 = buffer[idx[0]].n;
|
||||
const Normal &n1 = buffer[idx[1]].n;
|
||||
const Normal &n2 = buffer[idx[2]].n;
|
||||
|
@ -82,9 +82,9 @@ Point Triangle::sample(const Vertex *buffer, Normal &normal,
|
|||
}
|
||||
|
||||
Float Triangle::surfaceArea(const Vertex *buffer) const {
|
||||
const Point &v0 = buffer[idx[0]].v;
|
||||
const Point &v1 = buffer[idx[1]].v;
|
||||
const Point &v2 = buffer[idx[2]].v;
|
||||
const Point &v0 = buffer[idx[0]].p;
|
||||
const Point &v1 = buffer[idx[1]].p;
|
||||
const Point &v2 = buffer[idx[2]].p;
|
||||
Vector sideA = v1 - v0, sideB = v2 - v0;
|
||||
return 0.5f * cross(sideA, sideB).length();
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ Float Triangle::surfaceArea(const Vertex *buffer) const {
|
|||
AABB Triangle::getAABB(const Vertex *buffer) const {
|
||||
AABB aabb;
|
||||
for (int k=0; k<3; k++)
|
||||
aabb.expandBy(buffer[idx[k]].v);
|
||||
aabb.expandBy(buffer[idx[k]].p);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ AABB Triangle::getClippedAABB(const Vertex *buffer, const AABB &aabb) const {
|
|||
int nVertices = 3;
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
vertices1[i] = buffer[idx[i]].v;
|
||||
vertices1[i] = buffer[idx[i]].p;
|
||||
|
||||
for (int axis=0; axis<3; ++axis) {
|
||||
nVertices = sutherlandHodgman(vertices1, nVertices, vertices2, axis, aabb.min[axis], true);
|
||||
|
@ -155,11 +155,10 @@ AABB Triangle::getClippedAABB(const Vertex *buffer, const AABB &aabb) const {
|
|||
for (int i=0; i<nVertices; ++i)
|
||||
result.expandBy(vertices1[i]);
|
||||
|
||||
/* Cover up some numerical imprecisions */
|
||||
for (int i=0; i<3; ++i) {
|
||||
result.min[i] -= Epsilon * std::abs(result.min[i]);
|
||||
result.max[i] += Epsilon * std::abs(result.max[i]);
|
||||
}
|
||||
// Cover up some floating point imprecisions
|
||||
Vector error = aabb.getExtents() * Epsilon;
|
||||
result.min -= error;
|
||||
result.max += error;
|
||||
|
||||
result.clip(aabb);
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ void GLGeometry::refresh() {
|
|||
int pos = 0;
|
||||
for (size_t i=0; i<m_mesh->getVertexCount(); ++i) {
|
||||
const Vertex &vtx = source[i];
|
||||
vertices[pos++] = (float) vtx.v.x;
|
||||
vertices[pos++] = (float) vtx.v.y;
|
||||
vertices[pos++] = (float) vtx.v.z;
|
||||
vertices[pos++] = (float) vtx.p.x;
|
||||
vertices[pos++] = (float) vtx.p.y;
|
||||
vertices[pos++] = (float) vtx.p.z;
|
||||
vertices[pos++] = (float) vtx.n.x;
|
||||
vertices[pos++] = (float) vtx.n.y;
|
||||
vertices[pos++] = (float) vtx.n.z;
|
||||
|
|
|
@ -164,12 +164,12 @@ void KDTree::rayIntersectPacket(const Ray *rays, Intersection *its) const {
|
|||
const Vector &rayD = rays[i].d;
|
||||
it.p = rays[i].o + it.t * rayD;
|
||||
|
||||
Normal faceNormal(normalize(cross(v1.v-v0.v, v2.v-v0.v)));
|
||||
Normal faceNormal(normalize(cross(v1.p-v0.p, v2.p-v0.p)));
|
||||
it.geoFrame.n = faceNormal;
|
||||
coordinateSystem(it.geoFrame.n, it.geoFrame.s, it.geoFrame.t);
|
||||
|
||||
/* Intersection refinement step */
|
||||
Vector rel = it.p - v0.v;
|
||||
Vector rel = it.p - v0.p;
|
||||
Float correction = -dot(rel, faceNormal)/dot(rayD, faceNormal);
|
||||
it.t += correction;
|
||||
it.p += rayD * correction;
|
||||
|
|
|
@ -183,7 +183,7 @@ void KDTree::build() {
|
|||
const Vertex *vb = mesh->getVertexBuffer();
|
||||
const Triangle &tri = mesh->getTriangles()[ta.index];
|
||||
for (int j=0; j<3; j++)
|
||||
m_bsphere.expandBy(vb[tri.idx[j]].v);
|
||||
m_bsphere.expandBy(vb[tri.idx[j]].p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,9 +215,9 @@ void KDTree::build() {
|
|||
const TriMesh *mesh = static_cast<const TriMesh *>(m_shapes[ta.shapeIndex]);
|
||||
const Vertex *vertices = mesh->getVertexBuffer();
|
||||
const Triangle &tri = mesh->getTriangles()[ta.index];
|
||||
Point A = vertices[tri.idx[0]].v,
|
||||
B = vertices[tri.idx[1]].v,
|
||||
C = vertices[tri.idx[2]].v;
|
||||
Point A = vertices[tri.idx[0]].p,
|
||||
B = vertices[tri.idx[1]].p,
|
||||
C = vertices[tri.idx[2]].p;
|
||||
m_failures += ta.load(A, B, C);
|
||||
}
|
||||
#endif
|
||||
|
@ -670,9 +670,9 @@ void KDTree::createLeaf(int nodeIndex, int depth, int numPrims, EdgeEventVec3 &a
|
|||
const TriMesh *mesh = static_cast<const TriMesh *>(m_shapes[t.shapeIndex]);
|
||||
const Vertex *vertices = mesh->getVertexBuffer();
|
||||
const Triangle &tri = mesh->getTriangles()[t.index];
|
||||
A[packIndex] = vertices[tri.idx[0]].v;
|
||||
B[packIndex] = vertices[tri.idx[1]].v;
|
||||
C[packIndex] = vertices[tri.idx[2]].v;
|
||||
A[packIndex] = vertices[tri.idx[0]].p;
|
||||
B[packIndex] = vertices[tri.idx[1]].p;
|
||||
C[packIndex] = vertices[tri.idx[2]].p;
|
||||
} else {
|
||||
nonTriFlag = true;
|
||||
}
|
||||
|
|
|
@ -258,11 +258,11 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const {
|
|||
const Vertex &v1 = triMesh->getVertexBuffer()[t.idx[1]];
|
||||
const Vertex &v2 = triMesh->getVertexBuffer()[t.idx[2]];
|
||||
its.p = ray(its.t);
|
||||
Normal faceNormal(normalize(cross(v1.v-v0.v, v2.v-v0.v)));
|
||||
Normal faceNormal(normalize(cross(v1.p-v0.p, v2.p-v0.p)));
|
||||
|
||||
#if defined(SINGLE_PRECISION)
|
||||
/* Intersection refinement step */
|
||||
Float correction = -dot(its.p - v0.v, faceNormal)/dot(ray.d, faceNormal);
|
||||
Float correction = -dot(its.p - v0.p, faceNormal)/dot(ray.d, faceNormal);
|
||||
its.t += correction;
|
||||
its.p += ray.d * correction;
|
||||
|
||||
|
|
|
@ -151,10 +151,10 @@ void TriMesh::configure() {
|
|||
/* Generate a bounding sphere */
|
||||
m_aabb.reset();
|
||||
for (size_t i=0; i<m_vertexCount; i++)
|
||||
m_aabb.expandBy(m_vertexBuffer[i].v);
|
||||
m_aabb.expandBy(m_vertexBuffer[i].p);
|
||||
m_bsphere.center = m_aabb.getCenter();
|
||||
for (size_t i=0; i<m_vertexCount; i++)
|
||||
m_bsphere.expandBy(m_vertexBuffer[i].v);
|
||||
m_bsphere.expandBy(m_vertexBuffer[i].p);
|
||||
}
|
||||
|
||||
Float TriMesh::sampleArea(ShapeSamplingRecord &sRec, const Point2 &sample) const {
|
||||
|
@ -172,9 +172,9 @@ void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, boo
|
|||
for (unsigned int i=0; i<m_vertexCount; i++)
|
||||
m_vertexBuffer[i].n = Normal(0.0, 0.0f, 0.0f);
|
||||
for (unsigned int i=0; i<m_triangleCount; i++) {
|
||||
const Point &v0 = m_vertexBuffer[m_triangles[i].idx[0]].v;
|
||||
const Point &v1 = m_vertexBuffer[m_triangles[i].idx[1]].v;
|
||||
const Point &v2 = m_vertexBuffer[m_triangles[i].idx[2]].v;
|
||||
const Point &v0 = m_vertexBuffer[m_triangles[i].idx[0]].p;
|
||||
const Point &v1 = m_vertexBuffer[m_triangles[i].idx[1]].p;
|
||||
const Point &v2 = m_vertexBuffer[m_triangles[i].idx[2]].p;
|
||||
Normal n = Normal(cross(v1 - v0, v2 - v0));
|
||||
Float length = n.length();
|
||||
if (length != 0) {
|
||||
|
@ -232,9 +232,9 @@ void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, boo
|
|||
unsigned int idx0 = m_triangles[i].idx[0],
|
||||
idx1 = m_triangles[i].idx[1],
|
||||
idx2 = m_triangles[i].idx[2];
|
||||
const Point &v0 = m_vertexBuffer[idx0].v;
|
||||
const Point &v1 = m_vertexBuffer[idx1].v;
|
||||
const Point &v2 = m_vertexBuffer[idx2].v;
|
||||
const Point &v0 = m_vertexBuffer[idx0].p;
|
||||
const Point &v1 = m_vertexBuffer[idx1].p;
|
||||
const Point &v2 = m_vertexBuffer[idx2].p;
|
||||
const Point2 &uv0 = m_vertexBuffer[idx0].uv;
|
||||
const Point2 &uv1 = m_vertexBuffer[idx1].uv;
|
||||
const Point2 &uv2 = m_vertexBuffer[idx2].uv;
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
case EDebug: ui->logVerbosityBox->setCurrentIndex(1); break;
|
||||
case EInfo: ui->logVerbosityBox->setCurrentIndex(2); break;
|
||||
case EWarn: ui->logVerbosityBox->setCurrentIndex(3); break;
|
||||
case EError: ui->logVerbosityBox->setCurrentIndex(4); break;
|
||||
default:
|
||||
SLog(EError, "Unknown verbosity level!");
|
||||
}
|
||||
|
@ -102,6 +103,7 @@ public:
|
|||
case 1: return EDebug;
|
||||
case 2: return EInfo;
|
||||
case 3: return EWarn;
|
||||
case 4: return EError;
|
||||
default:
|
||||
SLog(EError, "Unknown verbosity level!");
|
||||
return EDebug;
|
||||
|
|
|
@ -522,6 +522,11 @@ above and including "Info" is written to the console.</string>
|
|||
<string>Warn</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Error</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
|
|
|
@ -31,7 +31,7 @@ MTS_NAMESPACE_BEGIN
|
|||
class WavefrontOBJ : public Shape {
|
||||
public:
|
||||
struct OBJTriangle {
|
||||
unsigned int v[3];
|
||||
unsigned int p[3];
|
||||
unsigned int n[3];
|
||||
unsigned int uv[3];
|
||||
};
|
||||
|
@ -128,7 +128,7 @@ public:
|
|||
triangles.push_back(t);
|
||||
if (iss >> tmp) {
|
||||
parse(t, 1, tmp);
|
||||
std::swap(t.v[0], t.v[1]);
|
||||
std::swap(t.p[0], t.p[1]);
|
||||
std::swap(t.uv[0], t.uv[1]);
|
||||
std::swap(t.n[0], t.n[1]);
|
||||
triangles.push_back(t);
|
||||
|
@ -165,17 +165,17 @@ public:
|
|||
void parse(OBJTriangle &t, int i, const std::string &str) {
|
||||
std::vector<std::string> tokens = tokenize(str, "/");
|
||||
if (tokens.size() == 1) {
|
||||
t.v[i] = atoi(tokens[0].c_str())-1;
|
||||
t.p[i] = atoi(tokens[0].c_str())-1;
|
||||
} else if (tokens.size() == 2) {
|
||||
if (str.find("//") == std::string::npos) {
|
||||
t.v[i] = atoi(tokens[0].c_str())-1;
|
||||
t.p[i] = atoi(tokens[0].c_str())-1;
|
||||
t.uv[i] = atoi(tokens[1].c_str())-1;
|
||||
} else {
|
||||
t.v[i] = atoi(tokens[0].c_str())-1;
|
||||
t.p[i] = atoi(tokens[0].c_str())-1;
|
||||
t.n[i] = atoi(tokens[1].c_str())-1;
|
||||
}
|
||||
} else if (tokens.size() == 3) {
|
||||
t.v[i] = atoi(tokens[0].c_str())-1;
|
||||
t.p[i] = atoi(tokens[0].c_str())-1;
|
||||
t.uv[i] = atoi(tokens[1].c_str())-1;
|
||||
t.n[i] = atoi(tokens[2].c_str())-1;
|
||||
} else {
|
||||
|
@ -229,12 +229,12 @@ public:
|
|||
std::binary_function<Vertex, Vertex, bool> {
|
||||
public:
|
||||
bool operator()(const Vertex &v1, const Vertex &v2) const {
|
||||
if (v1.v.x < v2.v.x) return true;
|
||||
else if (v1.v.x > v2.v.x) return false;
|
||||
if (v1.v.y < v2.v.y) return true;
|
||||
else if (v1.v.y > v2.v.y) return false;
|
||||
if (v1.v.z < v2.v.z) return true;
|
||||
else if (v1.v.z > v2.v.z) return false;
|
||||
if (v1.p.x < v2.p.x) return true;
|
||||
else if (v1.p.x > v2.p.x) return false;
|
||||
if (v1.p.y < v2.p.y) return true;
|
||||
else if (v1.p.y > v2.p.y) return false;
|
||||
if (v1.p.z < v2.p.z) return true;
|
||||
else if (v1.p.z > v2.p.z) return false;
|
||||
if (v1.n.x < v2.n.x) return true;
|
||||
else if (v1.n.x > v2.n.x) return false;
|
||||
if (v1.n.y < v2.n.y) return true;
|
||||
|
@ -268,13 +268,13 @@ public:
|
|||
for (unsigned int i=0; i<triangles.size(); i++) {
|
||||
Triangle tri;
|
||||
for (unsigned int j=0; j<3; j++) {
|
||||
unsigned int vertexId = triangles[i].v[j];
|
||||
unsigned int vertexId = triangles[i].p[j];
|
||||
unsigned int normalId = triangles[i].n[j];
|
||||
unsigned int uvId = triangles[i].uv[j];
|
||||
int key;
|
||||
|
||||
Vertex vertex;
|
||||
vertex.v = vertices.at(vertexId);
|
||||
vertex.p = vertices.at(vertexId);
|
||||
if (hasNormals)
|
||||
vertex.n = normals.at(normalId);
|
||||
else
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
if (!m_objectToWorld.isIdentity()) {
|
||||
for (size_t i=0; i<m_vertexCount; ++i) {
|
||||
Vertex &vertex = m_vertexBuffer[i];
|
||||
vertex.v = m_objectToWorld(vertex.v);
|
||||
vertex.p = m_objectToWorld(vertex.p);
|
||||
vertex.n = m_objectToWorld(vertex.n);
|
||||
vertex.dpdu = m_objectToWorld(vertex.dpdu);
|
||||
vertex.dpdv = m_objectToWorld(vertex.dpdv);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 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/>.
|
||||
*/
|
||||
|
||||
#include <mitsuba/render/testcase.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class TestTriangle : public TestCase {
|
||||
public:
|
||||
MTS_BEGIN_TESTCASE()
|
||||
MTS_DECLARE_TEST(test01_sutherlandHodgman)
|
||||
MTS_END_TESTCASE()
|
||||
|
||||
void test01_sutherlandHodgman() {
|
||||
/* Test the triangle clipping algorithm */
|
||||
Vertex vertices[3];
|
||||
vertices[0].p = Point(0, 0, 0);
|
||||
vertices[1].p = Point(1, 0, 0);
|
||||
vertices[2].p = Point(1, 1, 0);
|
||||
|
||||
AABB clipAABB(
|
||||
Point(0, .5, -1),
|
||||
Point(1, 1, 1)
|
||||
);
|
||||
|
||||
AABB expectedResult(
|
||||
Point(.5, .5, 0),
|
||||
Point(1, 1, 0)
|
||||
);
|
||||
|
||||
Triangle t;
|
||||
t.idx[0] = 0; t.idx[1] = 1; t.idx[2] = 2;
|
||||
|
||||
AABB clippedAABB = t.getClippedAABB(vertices, clipAABB);
|
||||
|
||||
assertEquals(clippedAABB.min, expectedResult.min);
|
||||
assertEquals(clippedAABB.max, expectedResult.max);
|
||||
}
|
||||
};
|
||||
|
||||
MTS_EXPORT_TESTCASE(TestTriangle, "Testcase for Triangle-related code")
|
||||
MTS_NAMESPACE_END
|
Loading…
Reference in New Issue