dust3d/thirdparty/carve-1.4.0/common/geometry.cpp

245 lines
8.1 KiB
C++

// Begin License:
// Copyright (C) 2006-2008 Tobias Sargeant (tobias.sargeant@gmail.com).
// All rights reserved.
//
// This file is part of the Carve CSG Library (http://carve-csg.com/)
//
// This file may be used under the terms of the GNU General Public
// License version 2.0 as published by the Free Software Foundation
// and appearing in the file LICENSE.GPL2 included in the packaging of
// this file.
//
// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE.
// End:
#if defined(HAVE_CONFIG_H)
# include <carve_config.h>
#endif
#include "geometry.hpp"
#include <carve/input.hpp>
carve::poly::Polyhedron *makeCube(const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
data.addVertex(transform * carve::geom::VECTOR(+1.0, +1.0, +1.0));
data.addVertex(transform * carve::geom::VECTOR(-1.0, +1.0, +1.0));
data.addVertex(transform * carve::geom::VECTOR(-1.0, -1.0, +1.0));
data.addVertex(transform * carve::geom::VECTOR(+1.0, -1.0, +1.0));
data.addVertex(transform * carve::geom::VECTOR(+1.0, +1.0, -1.0));
data.addVertex(transform * carve::geom::VECTOR(-1.0, +1.0, -1.0));
data.addVertex(transform * carve::geom::VECTOR(-1.0, -1.0, -1.0));
data.addVertex(transform * carve::geom::VECTOR(+1.0, -1.0, -1.0));
data.addFace(0, 1, 2, 3);
data.addFace(7, 6, 5, 4);
data.addFace(0, 4, 5, 1);
data.addFace(1, 5, 6, 2);
data.addFace(2, 6, 7, 3);
data.addFace(3, 7, 4, 0);
return new carve::poly::Polyhedron(data.points, data.getFaceCount(), data.faceIndices);
}
static bool _all(int x, int y, int z) {
return true;
}
carve::poly::Polyhedron *makeSubdividedCube(int sub_x, int sub_y, int sub_z,
bool (*inc)(int, int, int), const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
if (inc == NULL) inc = _all;
data.reserveVertices((sub_x + 1) * (sub_y + 1) * (sub_z + 1));
for (int _z = 0; _z < sub_z + 1; ++_z) {
double z = 1.0 - 2.0 * _z / sub_z;
for (int _y = 0; _y < sub_y + 1; ++_y) {
double y = 1.0 - 2.0 * _y / sub_y;
for (int _x = 0; _x < sub_x + 1; ++_x) {
double x = 1.0 - 2.0 * _x / sub_x;
data.addVertex(transform * carve::geom::VECTOR(x, y, z));
}
}
}
#define OK(x, y, z) ((x) >= 0 && (x) < sub_x && (y) >= 0 && (y) < sub_y && (z) >= 0 && (z) < sub_z)
#define I(x, y, z) ((x) + (y) * (sub_x + 1) + (z) * ((sub_x + 1) * (sub_y + 1)))
#define FACE(a, b, c, d) data.addFace(idx[a], idx[b], idx[c], idx[d])
for (int _z = 0; _z < sub_z; ++_z) {
for (int _y = 0; _y < sub_y; ++_y) {
for (int _x = 0; _x < sub_x; ++_x) {
int idx[8] = {
I(_x, _y, _z),
I(_x+1, _y, _z),
I(_x+1, _y+1, _z),
I(_x, _y+1, _z),
I(_x, _y, _z+1),
I(_x+1, _y, _z+1),
I(_x+1, _y+1, _z+1),
I(_x, _y+1, _z+1)
};
if (!inc(_x, _y, _z)) continue;
if (!OK(_x - 1, _y, _z) || !inc(_x - 1, _y, _z)) FACE(3, 7, 4, 0);
if (!OK(_x + 1, _y, _z) || !inc(_x + 1, _y, _z)) FACE(1, 5, 6, 2);
if (!OK(_x, _y - 1, _z) || !inc(_x, _y - 1, _z)) FACE(0, 4, 5, 1);
if (!OK(_x, _y + 1, _z) || !inc(_x, _y + 1, _z)) FACE(2, 6, 7, 3);
if (!OK(_x, _y, _z - 1) || !inc(_x, _y, _z - 1)) FACE(0, 1, 2, 3);
if (!OK(_x, _y, _z + 1) || !inc(_x, _y, _z + 1)) FACE(7, 6, 5, 4);
}
}
}
return data.create();
}
carve::poly::Polyhedron *makeDoubleCube(const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
data.addVertex(transform * carve::geom::VECTOR(-1.0, -1.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(-1.0, -1.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, -1.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, -1.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(-1.0, +0.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(-1.0, +0.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, +0.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, +0.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, +1.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(+0.0, +1.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(+1.0, +0.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(+1.0, +0.0, +0.5));
data.addVertex(transform * carve::geom::VECTOR(+1.0, +1.0, -0.5));
data.addVertex(transform * carve::geom::VECTOR(+1.0, +1.0, +0.5));
data.addFace(0, 4, 6, 2);
data.addFace(6, 8, 12, 10);
data.addFace(1, 3, 7, 5);
data.addFace(7, 11, 13, 9);
data.addFace(1, 5, 4, 0);
data.addFace(3, 1, 0, 2);
data.addFace(7, 3, 2, 6);
data.addFace(5, 7, 6, 4);
data.addFace(11, 7, 6, 10);
data.addFace(13, 11, 10, 12);
data.addFace(9, 13, 12, 8);
data.addFace(7, 9, 8, 6);
return data.create();
}
carve::poly::Polyhedron *makeTorus(int slices,
int rings,
double rad1,
double rad2,
const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
data.reserveVertices(slices * rings);
for (int i = 0; i < slices; i++) {
double a1 = i * M_PI * 2.0 / slices;
double dy = cos(a1);
double dx = sin(a1);
for (int j = 0; j < rings; j++) {
double a2 = j * M_PI * 2.0 / rings;
double x = dx * (rad1 + cos(a2) * rad2);
double y = dy * (rad1 + cos(a2) * rad2);
double z = sin(a2) * rad2;
data.addVertex(transform * carve::geom::VECTOR(x, y, z));
}
}
#define V(i, j) ((i) * rings + (j))
data.reserveFaces(slices * rings, 4);
for (int i = 0; i < slices; i++) {
int i2 = (i + 1) % slices;
for (int j = 0; j < rings; j++) {
int j2 = (j + 1) % rings;
data.addFace(V(i, j), V(i, j2), V(i2, j2), V(i2, j));
}
}
#undef V
return data.create();
}
carve::poly::Polyhedron *makeCylinder(int slices,
double rad,
double height,
const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
data.reserveVertices(slices * 2 + 2);
data.addVertex(transform * carve::geom::VECTOR(0, 0, +height/2));
data.addVertex(transform * carve::geom::VECTOR(0, 0, -height/2));
for (int i = 0; i < slices; i++) {
double a1 = i * M_PI * 2.0 / slices;
double y = cos(a1) * rad;
double x = sin(a1) * rad;
data.addVertex(transform * carve::geom::VECTOR(x, y, +height/2));
data.addVertex(transform * carve::geom::VECTOR(x, y, -height/2));
}
data.reserveFaces(slices * 3, 4);
for (int i = 0; i < slices; i++) {
data.addFace(0,
2 + ((i+1) % slices) * 2,
2 + i * 2);
}
for (int i = 0; i < slices; i++) {
data.addFace(2 + i * 2,
2 + ((i+1) % slices) * 2,
3 + ((i+1) % slices) * 2,
3 + i * 2);
}
for (int i = 0; i < slices; i++) {
data.addFace(1,
3 + i * 2,
3 + ((i+1) % slices) * 2);
}
return data.create();
}
carve::poly::Polyhedron *makeCone(int slices,
double rad,
double height,
const carve::math::Matrix &transform) {
carve::input::PolyhedronData data;
data.reserveVertices(slices + 2);
data.addVertex(transform * carve::geom::VECTOR(0, 0, +height/2));
data.addVertex(transform * carve::geom::VECTOR(0, 0, -height/2));
for (int i = 0; i < slices; i++) {
double a1 = i * M_PI * 2.0 / slices;
double y = cos(a1) * rad;
double x = sin(a1) * rad;
data.addVertex(transform * carve::geom::VECTOR(x, y, -height/2));
}
data.reserveFaces(slices * 2, 3);
for (int i = 0; i < slices; i++) {
data.addFace(0,
2 + ((i+1) % slices),
2 + i);
}
for (int i = 0; i < slices; i++) {
data.addFace(1,
2 + i,
2 + ((i+1) % slices));
}
return data.create();
}