work on sutherland-hodgman, allow to set log level to errors only

metadata
Wenzel Jakob 2010-09-16 02:30:47 +02:00
parent 6185149b86
commit 46dcdc4100
13 changed files with 129 additions and 66 deletions

View File

@ -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);
}

View File

@ -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() ||

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -522,6 +522,11 @@ above and including &quot;Info&quot; 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">

View File

@ -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

View File

@ -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);

57
src/tests/test_tri.cpp Normal file
View File

@ -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