Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2010-11-28 17:36:07 +0000
committerStijn Buys <ingar@osirion.org>2010-11-28 17:36:07 +0000
commit4d1b23606ed58737db9ea4423f1ad0f3d1db2782 (patch)
treefb7aed7ce86df8d934908c1ab7210c11a2a986e2
parentd22085f13895ab5f3cc479c3249ebeea32f53ed7 (diff)
Improved patch mesh surface normals.
-rw-r--r--src/math/functions.h9
-rw-r--r--src/math/vector3f.h4
-rw-r--r--src/model/mapfile.cc114
-rw-r--r--src/model/quad.cc3
-rw-r--r--src/model/quad.h6
5 files changed, 94 insertions, 42 deletions
diff --git a/src/math/functions.h b/src/math/functions.h
index 27a068e..8135392 100644
--- a/src/math/functions.h
+++ b/src/math/functions.h
@@ -107,15 +107,6 @@ inline void swap(float &x, float &y)
y = tmp;
}
-/// float to the n-th power
-inline float pow(const float x, const size_t pow) {
- float r = 1;
- for (size_t i = 1; i <= pow; i++) {
- r *= x;
- }
- return r;
-}
-
} // namespace math
#endif // __INCLUDED_MATH_FUNCTIONS_H__
diff --git a/src/math/vector3f.h b/src/math/vector3f.h
index 7cd533d..6ab77be 100644
--- a/src/math/vector3f.h
+++ b/src/math/vector3f.h
@@ -226,8 +226,8 @@ inline btVector3 to_btVector3(const math::Vector3f & v)
}
/// calculate the normal of a plane defined by three vertices
-inline const Vector3f normal(const Vector3f & first, const Vector3f & second, const Vector3f & third) {
- Vector3f r = crossproduct(second - first, third - first);
+inline const Vector3f normal(const Vector3f & center, const Vector3f & u, const Vector3f & v) {
+ Vector3f r = crossproduct(u - center, v - center);
r.normalize();
return r;
}
diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc
index 76a75a9..bf41cb4 100644
--- a/src/model/mapfile.cc
+++ b/src/model/mapfile.cc
@@ -27,8 +27,8 @@ const float MIN_DELTA = 10e-10;
// from radiant tools/quake3/q3map2/map.c
math::Vector3f texture_baseaxis[18] = {
- // normal texture plane
- math::Vector3f(0, 0, 1), math::Vector3f(1, 0, 0), math::Vector3f(0, -1, 0), // floor
+ // normal texture plane
+ math::Vector3f(0, 0, 1), math::Vector3f(1, 0, 0), math::Vector3f(0, -1, 0), // floor
math::Vector3f(0, 0, -1), math::Vector3f(1, 0, 0), math::Vector3f(0, -1, 0), // ceiling
math::Vector3f(1, 0, 0), math::Vector3f(0, 1, 0), math::Vector3f(0, 0, -1), // west wall
math::Vector3f(-1, 0, 0), math::Vector3f(0, 1, 0), math::Vector3f(0, 0, -1), // east wall
@@ -328,7 +328,6 @@ bool MapFile::read_patchdef()
}
patchvertices[r][c].assign(x, y, z);
- patchvertices[r][c] *= SCALE;
}
if (!(linestream >> word)) {
@@ -388,42 +387,111 @@ bool MapFile::read_patchdef()
}
// load patch data into the model geometry
- // the patch is a set of quadratic B-splines with m = n =2
+ // the patch is a set of quadratic B-splines with m = n = 2
+ // see http://en.wikipedia.org/wiki/Bézier_surface
+ // http://www.cc.gatech.edu/classes/AY2002/cs4451_spring/groups/group3/index.html#bpatches2
+ //
+ // patchvertices[][] are the control points as read from the .map file
+ // mesh[][] is a subdivideXsubdivide quad mesh calculated for each set of 9 control points in the patch
+
// TODO texture coordinates, normals
// TODO variable sibdivision
const size_t subdivide = 4;
- const float binom[3] = {1, 2, 1};
+ const float binom[3] = {1.0f, 2.0f, 1.0f};
for (size_t r = 0; r < rows-2; r +=2 ) {
for (size_t c = 0; c < columns -2; c += 2) {
+
math::Vector3f mesh[subdivide + 1][subdivide +1];
+ math::Vector3f meshnormals[subdivide + 1][subdivide +1];
+ math::Vector3f patchnormals[3][3];
+
+ patchnormals[0][0].assign(math::normal(patchvertices[r+0][c+0], patchvertices[r+1][c+0], patchvertices[r+0][c+1]));
+ patchnormals[0][2].assign(math::normal(patchvertices[r+0][c+2], patchvertices[r+0][c+1], patchvertices[r+1][c+2]));
+ patchnormals[2][2].assign(math::normal(patchvertices[r+2][c+2], patchvertices[r+1][c+2], patchvertices[r+2][c+1]));
+ patchnormals[2][0].assign(math::normal(patchvertices[r+2][c+0], patchvertices[r+2][c+1], patchvertices[r+1][c+0]));
+
+ patchnormals[0][1].assign(patchnormals[0][0] + patchnormals[0][2]);
+ patchnormals[0][1] *= 0.5f;
+ patchnormals[0][1].normalize();
+
+ patchnormals[2][1].assign(patchnormals[2][0] + patchnormals[2][2]);
+ patchnormals[2][1] *= 0.5f;
+ patchnormals[2][1].normalize();
+
+ patchnormals[1][0].assign(patchnormals[0][0] + patchnormals[2][0]);
+ patchnormals[1][0] *= 0.5f;
+ patchnormals[1][0].normalize();
+
+ patchnormals[1][2].assign(patchnormals[0][2] + patchnormals[2][2]);
+ patchnormals[1][2] *= 0.5f;
+ patchnormals[1][2].normalize();
+
+ patchnormals[1][1].assign(patchnormals[0][1] + patchnormals[2][1] + patchnormals[1][0] + patchnormals[1][2]);
+ patchnormals[1][1] *= 0.25f;
+ patchnormals[1][1].normalize();
for (size_t i = 0; i <= subdivide; i++) {
const float u = (float) i / (float) subdivide;
for (size_t j = 0; j <= subdivide; j++) {
const float v = (float) j / (float) subdivide;
+ //math::Vector3f tan_u;
+ //math::Vector3f tan_v;
for (size_t mi = 0; mi < 3; mi++) {
for (size_t mj = 0; mj < 3; mj++) {
mesh[i][j] +=
patchvertices[r+mi][c+mj] *
- binom[mi] * pow (u,mi) * pow(1.0f - u, 2-mi) *
- binom[mj] * pow (v,mj) * pow(1.0f - v, 2-mj);
+ binom[mi] * powf (u, (float) mi) * powf(1.0f - u, 2.0f - (float) mi) *
+ binom[mj] * powf (v, (float) mj) * powf(1.0f - v, 2.0f - (float) mj);
+
+ meshnormals[i][j] +=
+ patchnormals[mi][mj] *
+ binom[mi] * powf (u, (float) mi) * powf(1.0f - u, 2.0f - (float) mi) *
+ binom[mj] * powf (v, (float) mj) * powf(1.0f - v, 2.0f - (float) mj);
+ /*
+ tan_u +=
+ patchvertices[r+mi][c+mj] *
+ binom[mi] * (
+ ((float) mi) * powf(u, (float) mi - 1.0f) * powf(1.0f - u, 2.0f - (float) mi) +
+ ((float) mi - 2.0f) * powf(u, (float) mi) * powf(1.0f - u, 1.0f - (float) mi)
+ ) *
+ binom[mj] * powf (v, (float) mj) * powf(1.0f - v, 2.0f - (float) mj);
+
+ tan_v +=
+ patchvertices[r+mi][c+mj] *
+ binom[mi] * powf (u, (float) mi) * powf(1.0f - u, 2.0f - (float) mi) *
+ binom[mj] * (
+ ((float) mj) * powf(v, (float) mj - 1.0f) * powf(1.0f - v, 2.0f - (float) mj) +
+ ((float) mj - 2.0f) * powf(v, (float) mj) * powf(1.0f - v, 1.0f - (float) mj)
+ );
+ */
}
}
- }
+
+ //meshnormals[i][j].assign(math::crossproduct(tan_u, tan_v));
+ meshnormals[i][j].normalize();
+ class_box.expand(mesh[i][j] * SCALE);
+ }
}
-
+
+ const math::Vector3f zero;
for (size_t i = 0; i < subdivide; i++) {
for (size_t j = 0; j < subdivide; j++) {
Quad *quad = new Quad(
- mesh[i+1][j+1],
- mesh[i][j+1],
- mesh[i][j],
- mesh[i+1][j],
- math::normal(mesh[i][j+1], mesh[i][j], mesh[i+1][j+1])
+ mesh[i+1][j+1] * SCALE,
+ mesh[i][j+1] * SCALE,
+ mesh[i][j] * SCALE,
+ mesh[i+1][j] * SCALE,
+ zero
);
+
+ quad->n0().assign(meshnormals[i+1][j+1]);
+ quad->n1().assign(meshnormals[i][j+1]);
+ quad->n2().assign(meshnormals[i][j]);
+ quad->n3().assign(meshnormals[i+1][j]);
+
primitives->add_quad(quad);
}
}
@@ -811,7 +879,7 @@ void MapFile::make_brushface(Face *face)
primitives = (*mit).second;
}
- // scale vertices and calculate the bounding box
+ // add vertices to the bounding box
for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
class_box.expand(*(*it) * SCALE);
}
@@ -1103,10 +1171,10 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t
Quad *quad = (*quad_it);
if (!quad->detail()) {
size_t count = 0;
- count += fragment->add_vertex(quad->v0() - translation, quad->normal(), quad->t0(), false);
- count += fragment->add_vertex(quad->v1() - translation, quad->normal(), quad->t1(), false);
- count += fragment->add_vertex(quad->v2() - translation, quad->normal(), quad->t2(), false);
- count += fragment->add_vertex(quad->v3() - translation, quad->normal(), quad->t3(), false);
+ count += fragment->add_vertex(quad->v0() - translation, quad->n0(), quad->t0(), false);
+ count += fragment->add_vertex(quad->v1() - translation, quad->n1(), quad->t1(), false);
+ count += fragment->add_vertex(quad->v2() - translation, quad->n2(), quad->t2(), false);
+ count += fragment->add_vertex(quad->v3() - translation, quad->n3(), quad->t3(), false);
if (count == 4) {
model->model_quad_count++;
}
@@ -1118,10 +1186,10 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t
Quad *quad = (*quad_it);
if (quad->detail()) {
size_t count = 0;
- count += fragment->add_vertex(quad->v0() - translation, quad->normal(), quad->t0(), false);
- count += fragment->add_vertex(quad->v1() - translation, quad->normal(), quad->t1(), false);
- count += fragment->add_vertex(quad->v2() - translation, quad->normal(), quad->t2(), false);
- count += fragment->add_vertex(quad->v3() - translation, quad->normal(), quad->t3(), false);
+ count += fragment->add_vertex(quad->v0() - translation, quad->n0(), quad->t0(), true);
+ count += fragment->add_vertex(quad->v1() - translation, quad->n1(), quad->t1(), true);
+ count += fragment->add_vertex(quad->v2() - translation, quad->n2(), quad->t2(), true);
+ count += fragment->add_vertex(quad->v3() - translation, quad->n3(), quad->t3(), true);
if (count == 4) {
model->model_quad_count++;
model->model_quad_detail_count++;
diff --git a/src/model/quad.cc b/src/model/quad.cc
index 0830fe7..29aff34 100644
--- a/src/model/quad.cc
+++ b/src/model/quad.cc
@@ -17,8 +17,7 @@ Quad::Quad(const math::Vector3f &v0, const math::Vector3f &v1, const math::Vect
quad_v2(v2),
quad_n2(normal),
quad_v3(v3),
- quad_n3(normal),
- quad_normal(normal)
+ quad_n3(normal)
{
quad_detail = detail;
}
diff --git a/src/model/quad.h b/src/model/quad.h
index b7dd7af..4609cea 100644
--- a/src/model/quad.h
+++ b/src/model/quad.h
@@ -90,11 +90,6 @@ public:
return quad_detail;
}
- /// face normal
- inline math::Vector3f &normal() {
- return quad_normal;
- }
-
private:
math::Vector3f quad_v0;
@@ -113,7 +108,6 @@ private:
math::Vector3f quad_n3;
math::Vector2f quad_t3;
- math::Vector3f quad_normal;
bool quad_detail;
};