From 5c949b7e6eaf0076199f803f83e37290f0c549a8 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Thu, 2 Dec 2010 13:07:57 +0000 Subject: Improved patch mesh subdivision. --- src/model/mapfile.cc | 53 ++++++++++++++++++++++++++++++++++++++-------------- src/model/mapfile.h | 8 ++++++++ 2 files changed, 47 insertions(+), 14 deletions(-) (limited to 'src/model') diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 7775c8d..c016659 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -396,21 +396,46 @@ bool MapFile::read_patchdef() // 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 variable sibdivision - const size_t subdivide = 4; + // binomial coefficient const float binom[3] = {1.0f, 2.0f, 1.0f}; - + size_t subdivide_u = 0; + size_t subdivide_v = 0; + 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::Vector2f meshtexcoords[subdivide + 1][subdivide +1]; - - 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; + // if columns are collinear, do not subdivide in u direction + if ( + collinear(patchvertices[r][c], patchvertices[r+1][c], patchvertices[r+2][c]) && + collinear(patchvertices[r][c+1], patchvertices[r+1][c+1], patchvertices[r+2][c+1]) && + collinear(patchvertices[r][c+2], patchvertices[r+1][c+2], patchvertices[r+2][c+2]) + ) { + subdivide_u = 1; + } else { + subdivide_u = 4; + } + + + // if rows are collinear, do not subdivide in v direction + if ( + collinear(patchvertices[r][c], patchvertices[r][c+1], patchvertices[r][c+2]) && + collinear(patchvertices[r+1][c], patchvertices[r+1][c+1], patchvertices[r+1][c+2]) && + collinear(patchvertices[r+2][c], patchvertices[r+2][c+1], patchvertices[r+2][c+2]) + ) { + subdivide_v = 1; + } else { + subdivide_v = 4; + } + + math::Vector3f mesh[subdivide_u + 1][subdivide_v +1]; + math::Vector3f meshnormals[subdivide_u + 1][subdivide_v +1]; + math::Vector2f meshtexcoords[subdivide_u + 1][subdivide_v +1]; + + for (size_t i = 0; i <= subdivide_u; i++) { + const float u = (float) i / (float) subdivide_u; + + for (size_t j = 0; j <= subdivide_v; j++) { + const float v = (float) j / (float) subdivide_v; math::Vector3f tan_u; math::Vector3f tan_v; @@ -418,7 +443,7 @@ bool MapFile::read_patchdef() // we cheat and pull the edge points towards the middle float un = u; float vn = v; - if ((i ==0) || (j==0) || (i == subdivide) || (j == subdivide)) { + if ((i ==0) || (j==0) || (i == subdivide_u) || (j == subdivide_v)) { un = (u - 0.5f) * 0.95f + 0.5f; vn = (v - 0.5f) * 0.95f + 0.5f; } @@ -480,8 +505,8 @@ bool MapFile::read_patchdef() } const math::Vector3f zero; - for (size_t i = 0; i < subdivide; i++) { - for (size_t j = 0; j < subdivide; j++) { + for (size_t i = 0; i < subdivide_u; i++) { + for (size_t j = 0; j < subdivide_v; j++) { Quad *quad = new Quad( mesh[i+1][j+1] * SCALE, mesh[i][j+1] * SCALE, diff --git a/src/model/mapfile.h b/src/model/mapfile.h index a12e295..c78b56c 100644 --- a/src/model/mapfile.h +++ b/src/model/mapfile.h @@ -128,6 +128,14 @@ private: inline const math::BoundingBox3f & box() const { return map_box; } + + inline bool collinear(const math::Vector3f & a, const math::Vector3f & b, const math::Vector3f & c) + { + if ((distance(a, b) + distance(b, c)) == distance(a, c)) + return true; + else + return false; + } /// close the file void close(); -- cgit v1.2.3