Line data Source code
1 0 : /*
2 :
3 : OOVoxel.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #import "OOMaths.h"
27 :
28 :
29 : // routines concerning octree voxels
30 :
31 0 : int checkFace(Vector p, GLfloat rd)
32 : {
33 : int faces = 0;
34 : if (p.x > rd) faces |= CUBE_FACE_RIGHT; // right
35 : if (p.x < -rd) faces |= CUBE_FACE_LEFT; // left
36 : if (p.y > rd) faces |= CUBE_FACE_TOP; // above
37 : if (p.y < -rd) faces |= CUBE_FACE_BOTTOM; // below
38 : if (p.z > rd) faces |= CUBE_FACE_FRONT; // ahead
39 : if (p.z < -rd) faces |= CUBE_FACE_BACK; // behind
40 : return faces ;
41 : }
42 :
43 0 : int checkBevel(Vector p, GLfloat rd)
44 : {
45 : GLfloat r2 = rd * 2;
46 : int bevels = 0;
47 : if ( p.x + p.y > r2) bevels |= 0x001;
48 : if ( p.x - p.y > r2) bevels |= 0x002;
49 : if (-p.x + p.y > r2) bevels |= 0x004;
50 : if (-p.x - p.y > r2) bevels |= 0x008;
51 : if ( p.x + p.z > r2) bevels |= 0x010;
52 : if ( p.x - p.z > r2) bevels |= 0x020;
53 : if (-p.x + p.z > r2) bevels |= 0x040;
54 : if (-p.x - p.z > r2) bevels |= 0x080;
55 : if ( p.y + p.z > r2) bevels |= 0x100;
56 : if ( p.y - p.z > r2) bevels |= 0x200;
57 : if (-p.y + p.z > r2) bevels |= 0x400;
58 : if (-p.y - p.z > r2) bevels |= 0x800;
59 : return bevels;
60 : }
61 :
62 0 : int checkCorner(Vector p, GLfloat rd)
63 : {
64 : GLfloat r3 = rd * 3;
65 : int corners = 0;
66 : if (( p.x + p.y + p.z) > r3) corners |= 0x01;
67 : if (( p.x + p.y - p.z) > r3) corners |= 0x02;
68 : if (( p.x - p.y + p.z) > r3) corners |= 0x04;
69 : if (( p.x - p.y - p.z) > r3) corners |= 0x08;
70 : if ((-p.x + p.y + p.z) > r3) corners |= 0x10;
71 : if ((-p.x + p.y - p.z) > r3) corners |= 0x20;
72 : if ((-p.x - p.y + p.z) > r3) corners |= 0x40;
73 : if ((-p.x - p.y - p.z) > r3) corners |= 0x80;
74 : return corners;
75 : }
76 :
77 0 : Vector lineIntersectionWithFace(Vector p1, Vector p2, long mask, GLfloat rd)
78 : {
79 : if (CUBE_FACE_RIGHT & mask)
80 : return make_vector( rd,
81 : p1.y + (p2.y - p1.y) * (rd - p1.x) / (p2.x - p1.x),
82 : p1.z + (p2.z - p1.z) * (rd - p1.x) / (p2.x - p1.x));
83 :
84 : if (CUBE_FACE_LEFT & mask)
85 : return make_vector( -rd,
86 : p1.y + (p2.y - p1.y) * (-rd - p1.x) / (p2.x - p1.x),
87 : p1.z + (p2.z - p1.z) * (-rd - p1.x) / (p2.x - p1.x));
88 :
89 : if (CUBE_FACE_TOP & mask)
90 : return make_vector( p1.x + (p2.x - p1.x) * (rd - p1.y) / (p2.y - p1.y),
91 : rd,
92 : p1.z + (p2.z - p1.z) * (rd - p1.y) / (p2.y - p1.y));
93 :
94 : if (CUBE_FACE_BOTTOM & mask)
95 : return make_vector( p1.x + (p2.x - p1.x) * (-rd - p1.y) / (p2.y - p1.y),
96 : -rd,
97 : p1.z + (p2.z - p1.z) * (-rd - p1.y) / (p2.y - p1.y));
98 :
99 : if (CUBE_FACE_FRONT & mask)
100 : return make_vector( p1.x + (p2.x - p1.x) * (rd - p1.z) / (p2.z - p1.z),
101 : p1.y + (p2.y - p1.y) * (rd - p1.z) / (p2.z - p1.z),
102 : rd);
103 :
104 : if (CUBE_FACE_BACK & mask)
105 : return make_vector( p1.x + (p2.x - p1.x) * (-rd - p1.z) / (p2.z - p1.z),
106 : p1.y + (p2.y - p1.y) * (-rd - p1.z) / (p2.z - p1.z),
107 : -rd);
108 : return p1;
109 : }
110 :
111 0 : int checkPoint(Vector p1, Vector p2, GLfloat alpha, long mask, GLfloat rd)
112 : {
113 : Vector pp;
114 : pp.x = p1.x + alpha * (p2.x - p1.x);
115 : pp.y = p1.y + alpha * (p2.y - p1.y);
116 : pp.z = p1.z + alpha * (p2.z - p1.z);
117 : return (checkFace( pp, rd) & mask);
118 : }
119 :
120 0 : int checkLine(Vector p1, Vector p2, int mask, GLfloat rd)
121 : {
122 : int result = 0;
123 : if ((CUBE_FACE_RIGHT & mask) && (p1.x > p2.x) && (checkPoint( p1, p2, (rd-p1.x)/(p2.x-p1.x), 0x3f - CUBE_FACE_RIGHT, rd) == 0)) // right
124 : result |= CUBE_FACE_RIGHT;
125 : if ((CUBE_FACE_LEFT & mask) && (p1.x < p2.x) && (checkPoint( p1, p2, (-rd-p1.x)/(p2.x-p1.x), 0x3f - CUBE_FACE_LEFT, rd) == 0)) // left
126 : result |= CUBE_FACE_LEFT;
127 : if ((CUBE_FACE_TOP & mask) && (p1.y > p2.y) && (checkPoint( p1, p2, (rd-p1.y)/(p2.y-p1.y), 0x3f - CUBE_FACE_TOP, rd) == 0)) // above
128 : result |= CUBE_FACE_TOP;
129 : if ((CUBE_FACE_BOTTOM & mask) && (p1.y < p2.y) && (checkPoint( p1, p2, (-rd-p1.y)/(p2.y-p1.y), 0x3f - CUBE_FACE_BOTTOM, rd) == 0)) // below
130 : result |= CUBE_FACE_BOTTOM;
131 : if ((CUBE_FACE_FRONT & mask) && (p1.z > p2.z) && (checkPoint( p1, p2, (rd-p1.z)/(p2.z-p1.z), 0x3f - CUBE_FACE_FRONT, rd) == 0)) // ahead
132 : result |= CUBE_FACE_FRONT;
133 : if ((CUBE_FACE_BACK & mask) && (p1.z < p2.z) && (checkPoint( p1, p2, (-rd-p1.z)/(p2.z-p1.z), 0x3f - CUBE_FACE_BACK, rd) == 0)) // behind
134 : result |= CUBE_FACE_BACK;
135 : return result;
136 : }
137 :
138 : // line v0 to v1 is compared with a cube centered on the origin (corners at -rd,-rd,-rd to rd,rd,rd).
139 : // returns -1 if the line intersects the cube.
140 0 : int lineCubeIntersection(Vector v0, Vector v1, GLfloat rd)
141 : {
142 : int v0_test, v1_test;
143 :
144 : // compare both vertexes with all six face-planes
145 : //
146 : if ((v0_test = checkFace( v0, rd)) == 0)
147 : return -1; // v0 is inside the cube
148 : if ((v1_test = checkFace( v1, rd)) == 0)
149 : return -1; // v1 is inside the cube
150 :
151 : // check they're not both outside one face-plane
152 : //
153 : if ((v0_test & v1_test) != 0)
154 : return 0; // both v0 and v1 are outside the same face of the cube
155 :
156 : // Now do the same test for the 12 edge planes
157 : //
158 : v0_test |= checkBevel( v0, rd) << 8;
159 : v1_test |= checkBevel( v1, rd) << 8;
160 : if ((v0_test & v1_test) != 0)
161 : return 0; // v0 and v1 outside of the same bevel
162 :
163 : // Now do the same test for the 8 corner planes
164 : //
165 : v0_test |= checkCorner( v0, rd) << 24;
166 : v1_test |= checkCorner( v1, rd) << 24;
167 : if ((v0_test & v1_test) != 0)
168 : return 0; // v0 and v1 outside of same corner
169 :
170 : // see if the v0-->v1 line intersects the cube.
171 : //
172 : return checkLine( v0, v1, v0_test | v1_test, rd);
173 : }
|