X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2F3dengfx%2Fsrc%2F3dengfx%2Fscfield.cpp;fp=src%2F3dengfx%2Fsrc%2F3dengfx%2Fscfield.cpp;h=fe67628e197c7a225bbcf0f9792e1b589b7af777;hb=6e23259dbabaeb1711a2a5ca25b9cb421f693759;hp=0000000000000000000000000000000000000000;hpb=fe068fa879814784c45e0cb2e65dac489e8f5594;p=summerhack diff --git a/src/3dengfx/src/3dengfx/scfield.cpp b/src/3dengfx/src/3dengfx/scfield.cpp new file mode 100644 index 0000000..fe67628 --- /dev/null +++ b/src/3dengfx/src/3dengfx/scfield.cpp @@ -0,0 +1,659 @@ +/* +This file is part of the 3dengfx, realtime visualization system. + +Copyright (c) 2004, 2005 John Tsiombikas + +3dengfx is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +3dengfx 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 3dengfx; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Scalar fields and polygonization + * + * Author: Mihalis Georgoulopoulos 2005 + */ + +#define SCFIELD_SOURCE +#include "mcube_tables.h" +#include "scfield.hpp" +#include "3dengfx/3denginefx.hpp" + +// don't change this +#define EDGE_NOT_ASSOCIATED 0xFFFFFFFF + +/* ----------------- + * private functions + * ----------------- + */ + +/* + * AddVertex + * adds a vertex and returns its index + */ +unsigned int ScalarField::add_vertex(const Vertex &vert) +{ + verts.push_back(vert); + return verts.size() - 1; +} + +/* + * Clear + * clears std::vector's that hold mesh data and resets edges table + */ +void ScalarField::clear() +{ + verts.erase(verts.begin(), verts.end()); + tris.erase(tris.begin(), tris.end()); + + unsigned int num_bytes = dimensions * dimensions * dimensions * sizeof(unsigned int); + + memset(edges_x, 0xFF, num_bytes); + memset(edges_y, 0xFF, num_bytes); + memset(edges_z, 0xFF, num_bytes); +} + +/* + * EvaluateAll + * Evaluates all values with the external Evaluate function (if specified) + */ +void ScalarField::evaluate_all(scalar_t t) +{ + if (!evaluate) + { + return; + } + + for (unsigned int z=0; zdimensions = dimensions; + this->from = from; + this->to = to; + this->cell_size = (to - from) / (dimensions - 1); + + values = 0; + edges_x = edges_y = edges_z = 0; + + evaluate = 0; + get_normal = 0; + + set_dimensions(dimensions); +} + +ScalarField::~ScalarField() +{ + if (values) + delete [] values; + if (edges_x) + delete [] edges_x; + if (edges_y) + delete [] edges_y; + if (edges_z) + delete [] edges_z; +} + +void ScalarField::set_dimensions(unsigned int dimensions) +{ + this->dimensions = dimensions; + if (values) + delete [] values; + if (edges_x) + delete [] edges_x; + if (edges_y) + delete [] edges_y; + if (edges_z) + delete [] edges_z; + + values = new scalar_t [dimensions * dimensions * dimensions]; + + unsigned int edges_per_dim = dimensions * dimensions * dimensions; + edges_x = new unsigned int[edges_per_dim]; + edges_y = new unsigned int[edges_per_dim]; + edges_z = new unsigned int[edges_per_dim]; + + clear(); +} + +// Get / Set +void ScalarField::set_value(int x, int y, int z, scalar_t value) +{ + values[get_value_index(x, y, z)] = value; +} + +scalar_t ScalarField::get_value(int x, int y, int z) +{ + return values[get_value_index(x, y, z)]; +} + + +// get / set relative to cell +void ScalarField::set_value(int cx, int cy, int cz, int vert_index, scalar_t value) +{ + if (vert_index == 0) set_value(cx + 0, cy + 0, cz + 1, value); + else if (vert_index == 1) set_value(cx + 1, cy + 0, cz + 1, value); + else if (vert_index == 2) set_value(cx + 1, cy + 0, cz + 0, value); + else if (vert_index == 3) set_value(cx + 0, cy + 0, cz + 0, value); + else if (vert_index == 4) set_value(cx + 0, cy + 1, cz + 1, value); + else if (vert_index == 5) set_value(cx + 1, cy + 1, cz + 1, value); + else if (vert_index == 6) set_value(cx + 1, cy + 1, cz + 0, value); + else if (vert_index == 7) set_value(cx + 0, cy + 1, cz + 0, value); +} + + +scalar_t ScalarField::get_value(int cx, int cy, int cz, int vert_index) +{ + if (vert_index == 0) return get_value(cx + 0, cy + 0, cz + 1); + if (vert_index == 1) return get_value(cx + 1, cy + 0, cz + 1); + if (vert_index == 2) return get_value(cx + 1, cy + 0, cz + 0); + if (vert_index == 3) return get_value(cx + 0, cy + 0, cz + 0); + if (vert_index == 4) return get_value(cx + 0, cy + 1, cz + 1); + if (vert_index == 5) return get_value(cx + 1, cy + 1, cz + 1); + if (vert_index == 6) return get_value(cx + 1, cy + 1, cz + 0); + if (vert_index == 7) return get_value(cx + 0, cy + 1, cz + 0); + + return 0; +} + +// edges are addressed relatively to a cell (cx, cy, cz) +// and the cell's edge number +void ScalarField::set_edge(int cx, int cy, int cz, int edge, unsigned int index) +{ + unsigned int d = dimensions; + unsigned int d2 = dimensions * dimensions; + + if (edge == 0) + edges_x[cx + 0 + (cy + 0) * d + (cz + 1) * d2] = index; + else if (edge == 1) + edges_z[cx + 1 + (cy + 0) * d + (cz + 0) * d2] = index; + else if (edge == 2) + edges_x[cx + 0 + (cy + 0) * d + (cz + 0) * d2] = index; + else if (edge == 3) + edges_z[cx + 0 + (cy + 0) * d + (cz + 0) * d2] = index; + else if (edge == 4) + edges_x[cx + 0 + (cy + 1) * d + (cz + 1) * d2] = index; + else if (edge == 5) + edges_z[cx + 1 + (cy + 1) * d + (cz + 0) * d2] = index; + else if (edge == 6) + edges_x[cx + 0 + (cy + 1) * d + (cz + 0) * d2] = index; + else if (edge == 7) + edges_z[cx + 0 + (cy + 1) * d + (cz + 0) * d2] = index; + else if (edge == 8) + edges_y[cx + 0 + (cy + 0) * d + (cz + 1) * d2] = index; + else if (edge == 9) + edges_y[cx + 1 + (cy + 0) * d + (cz + 1) * d2] = index; + else if (edge == 10) + edges_y[cx + 1 + (cy + 0) * d + (cz + 0) * d2] = index; + else if (edge == 11) + edges_y[cx + 0 + (cy + 0) * d + (cz + 0) * d2] = index; +} + +unsigned int ScalarField::get_edge(int cx, int cy, int cz, int edge) +{ + unsigned int d = dimensions; + unsigned int d2 = dimensions * dimensions; + + if (edge == 0) return edges_x[cx + 0 + (cy + 0) * d + (cz + 1) * d2]; + if (edge == 1) return edges_z[cx + 1 + (cy + 0) * d + (cz + 0) * d2]; + if (edge == 2) return edges_x[cx + 0 + (cy + 0) * d + (cz + 0) * d2]; + if (edge == 3) return edges_z[cx + 0 + (cy + 0) * d + (cz + 0) * d2]; + if (edge == 4) return edges_x[cx + 0 + (cy + 1) * d + (cz + 1) * d2]; + if (edge == 5) return edges_z[cx + 1 + (cy + 1) * d + (cz + 0) * d2]; + if (edge == 6) return edges_x[cx + 0 + (cy + 1) * d + (cz + 0) * d2]; + if (edge == 7) return edges_z[cx + 0 + (cy + 1) * d + (cz + 0) * d2]; + if (edge == 8) return edges_y[cx + 0 + (cy + 0) * d + (cz + 1) * d2]; + if (edge == 9) return edges_y[cx + 1 + (cy + 0) * d + (cz + 1) * d2]; + if (edge == 10) return edges_y[cx + 1 + (cy + 0) * d + (cz + 0) * d2]; + if (edge == 11) return edges_y[cx + 0 + (cy + 0) * d + (cz + 0) * d2]; + + return 0; +} + +// Position in space +Vector3 ScalarField::get_position(int x, int y, int z) +{ + scalar_t vx, vy, vz; + vx = from.x + cell_size.x * x; + vy = from.y + cell_size.y * y; + vz = from.z + cell_size.z * z; + + return Vector3(vx, vy, vz); +} + +Vector3 ScalarField::get_position(int cx, int cy, int cz, int vert_index) +{ + if (vert_index == 0) return get_position(cx + 0, cy + 0, cz + 1); + if (vert_index == 1) return get_position(cx + 1, cy + 0, cz + 1); + if (vert_index == 2) return get_position(cx + 1, cy + 0, cz + 0); + if (vert_index == 3) return get_position(cx + 0, cy + 0, cz + 0); + if (vert_index == 4) return get_position(cx + 0, cy + 1, cz + 1); + if (vert_index == 5) return get_position(cx + 1, cy + 1, cz + 1); + if (vert_index == 6) return get_position(cx + 1, cy + 1, cz + 0); + if (vert_index == 7) return get_position(cx + 0, cy + 1, cz + 0); + + return Vector3(0, 0, 0); +} + +void ScalarField::set_from_to(const Vector3 &from, const Vector3 &to) +{ + this->from = from; + this->to = to; + this->cell_size = (to - from) / (dimensions - 1); +} + +void ScalarField::draw_field(bool full) +{ + set_lighting(false); + + if (full) + { + glBegin(GL_LINES); + { + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + for (unsigned int j=0; jfrom; +} + +Vector3 ScalarField::get_to() +{ + return this->to; +} + +// Evaluators +void ScalarField::set_evaluator(scalar_t (*evaluate) (const Vector3 &vec, scalar_t t)) +{ + this->evaluate = evaluate; +} + +void ScalarField::set_normal_evaluator(Vector3 (*get_normal) (const Vector3 &vec, scalar_t t)) +{ + this->get_normal = get_normal; +} + +// last but not least +void ScalarField::triangulate(TriMesh *mesh, scalar_t isolevel, scalar_t t, bool calc_normals) +{ + // Reset mesh and edges table + clear(); + + // Evaluate + evaluate_all(t); + + // triangulate + for (unsigned int z=0; zset_data(varray, verts.size(), tarray, tris.size()); + + delete [] varray; + delete [] tarray; + + // as a final resort, if we could not calculate normals any other way + // use the regular mesh normal calculation function. + if(need_normals) { + mesh->calculate_normals_by_index(); + } +} + +