NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ConvexPolyhedron.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2011, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "3d/ConvexPolyhedron.hpp"
29 
30 using namespace FW;
31 
32 //------------------------------------------------------------------------
33 
34 #define EPSILON 1.0e-6f
35 #define ENABLE_ASSERTS 0
36 
37 //------------------------------------------------------------------------
38 
39 void ConvexPolyhedron::setCube(const Vec3f& lo, const Vec3f& hi)
40 {
41  static const Vec2i edges[] =
42  {
43  Vec2i(0, 1), Vec2i(0, 2), Vec2i(0, 4), Vec2i(1, 3),
44  Vec2i(1, 5), Vec2i(2, 3), Vec2i(2, 6), Vec2i(3, 7),
45  Vec2i(4, 5), Vec2i(4, 6), Vec2i(5, 7), Vec2i(6, 7),
46  };
47 
48  static const Vec4i faceEdges[] =
49  {
50  Vec4i(2, 9, ~6, ~1), Vec4i(3, 7, ~10, ~4),
51  Vec4i(0, 4, ~8, ~2), Vec4i(6, 11, ~7, ~5),
52  Vec4i(1, 5, ~3, ~0), Vec4i(8, 10, ~11, ~9),
53  };
54 
55  m_vertices.resize(8);
56  m_vertices[0].pos = Vec3f(lo.x, lo.y, lo.z);
57  m_vertices[1].pos = Vec3f(hi.x, lo.y, lo.z);
58  m_vertices[2].pos = Vec3f(lo.x, hi.y, lo.z);
59  m_vertices[3].pos = Vec3f(hi.x, hi.y, lo.z);
60  m_vertices[4].pos = Vec3f(lo.x, lo.y, hi.z);
61  m_vertices[5].pos = Vec3f(hi.x, lo.y, hi.z);
62  m_vertices[6].pos = Vec3f(lo.x, hi.y, hi.z);
63  m_vertices[7].pos = Vec3f(hi.x, hi.y, hi.z);
64 
65  m_edges.resize(12);
66  for (int i = 0; i < 12; i++)
67  m_edges[i].verts = edges[i];
68 
69  m_faces.resize(6);
70  m_faceEdges.resize(24);
71  FaceEdge* faceEdgePtr = m_faceEdges.getPtr();
72  for (int i = 0; i < 6; i++)
73  {
74  Face& f = m_faces[i];
75  f.planeEq = 0.0f;
76  f.planeEq[i >> 1] = ((i & 1) == 0) ? -1.0f : 1.0f;
77  f.planeEq.w = ((i & 1) == 0) ? -lo[i >> 1] : -hi[i >> 1];
78  f.planeID = -1;
79  f.firstEdge = i * 4;
80  f.numEdges = 4;
81 
82  for (int j = 0; j < 4; j++)
83  (faceEdgePtr++)->edge = faceEdges[i][j];
84  }
85 }
86 
87 //------------------------------------------------------------------------
88 
89 bool ConvexPolyhedron::intersect(const Vec4f& planeEq, int planeID)
90 {
91  // Plane matches a face => not intersected.
92 
93  for (int i = m_faces.getSize() - 1; i >= 0; i--)
94  if (planeEq == m_faces[i].planeEq)
95  return false;
96 
97  // Compute the orientation of vertices.
98 
99  bool culled = false;
100  for (int i = m_vertices.getSize() - 1; i >= 0; i--)
101  {
102  Vertex& v = m_vertices[i];
103  F32 t = planeEq.x * v.pos.x + planeEq.y * v.pos.y + planeEq.z * v.pos.z;
104  F32 eps = (abs(t) + abs(planeEq.w)) * EPSILON;
105  t += planeEq.w;
106  v.aux.orient = t + eps;
107  culled = (culled || t - eps > 0.0f);
108  }
109 
110  // No vertices culled => not intersected.
111 
112  if (!culled)
113  return false;
114 
115  // Intersect edges.
116 
117  int edgeOfs = 0;
118  int firstNewVertex = m_vertices.getSize();
119  for (int i = 0; i < m_edges.getSize(); i++)
120  {
121  // Both vertices are behind the plane => cull.
122 
123  Edge& oldEdge = m_edges[i];
124  const Vertex& vx = m_vertices[oldEdge.verts.x];
125  const Vertex& vy = m_vertices[oldEdge.verts.y];
126  if (vx.aux.orient >= 0.0f && vy.aux.orient >= 0.0f)
127  {
128  oldEdge.remap = -1;
129  continue;
130  }
131 
132  // Remap.
133 
134  oldEdge.remap = edgeOfs;
135  Edge& newEdge = m_edges[edgeOfs++];
136  newEdge.verts = oldEdge.verts;
137 
138  // Vertices are on the different side of the plane => clip.
139 
140  if (vx.aux.orient >= 0.0f || vy.aux.orient >= 0.0f)
141  {
142  F32 t = vx.aux.orient / (vx.aux.orient - vy.aux.orient);
143  Vec3f pos = lerp(vx.pos, vy.pos, fastClamp(t, 0.0f, 1.0f));
144 
145  newEdge.verts[(vx.aux.orient >= 0.0f) ? 0 : 1] = m_vertices.getSize();
146  Vertex& v = m_vertices.add();
147  v.pos = pos;
148  }
149  }
150 
151  // Intersect faces.
152 
153  int firstNewFaceEdge = m_faceEdges.getSize();
154  for (int i = m_faces.getSize() - 1; i >= 0; i--)
155  {
156  Face& face = m_faces[i];
157  FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
158  Vec2i newEdge = -1;
159 
160  for (int j = face.numEdges - 1; j >= 0; j--)
161  {
162  // Edge was culled => remove from the face.
163 
164  int oldIdx = faceEdges[j].edge;
165  int mask = oldIdx >> 31;
166  int newIdx = m_edges[oldIdx ^ mask].remap;
167  if (newIdx == -1)
168  {
169  faceEdges[j].old = faceEdges[--face.numEdges].old;
170  continue;
171  }
172 
173  // Remap and record intersections.
174 
175  faceEdges[j].old = newIdx ^ mask;
176  const Vec2i& verts = m_edges[newIdx].verts;
177  if (verts.x >= firstNewVertex)
178  {
179  FW_ASSERT(!ENABLE_ASSERTS || newEdge[mask & 1] == -1);
180  newEdge[mask & 1] = verts.x;
181  }
182  else if (verts.y >= firstNewVertex)
183  {
184  FW_ASSERT(!ENABLE_ASSERTS || newEdge[~mask & 1] == -1);
185  newEdge[~mask & 1] = verts.y;
186  }
187  }
188 
189  // No edges => remove face.
190  // Intersected => add new edge.
191 
192  if (newEdge.x == -1 || newEdge.y == -1)
193  {
194  FW_ASSERT(!ENABLE_ASSERTS || (newEdge.x == -1 && newEdge.y == -1));
195  face.newEdge = -1;
196  if (face.numEdges < 3)
197  m_faces.removeSwap(i);
198  }
199  else
200  {
201  face.newEdge = edgeOfs;
202  m_faceEdges.add().old = edgeOfs;
203  if (edgeOfs == m_edges.getSize())
204  m_edges.add();
205  m_edges[edgeOfs++].verts = newEdge;
206  }
207  }
208  m_edges.resize(edgeOfs);
209 
210  // Add the new face.
211 
212  Face& newFace = m_faces.add();
213  newFace.planeEq = planeEq;
214  newFace.planeID = planeID;
215  newFace.firstEdge = firstNewFaceEdge;
216  newFace.numEdges = m_faceEdges.getSize() - firstNewFaceEdge;
217  newFace.newEdge = -1;
218 
219  // Rebuild the face edge array.
220 
221  m_faceEdges.add(NULL, newFace.numEdges);
222  int faceEdgeOfs = 0;
223  for (int i = m_faces.getSize() - 1; i >= 0; i--)
224  {
225  Face& face = m_faces[i];
226  const FaceEdge* old = m_faceEdges.getPtr(face.firstEdge);
227  face.firstEdge = faceEdgeOfs;
228  for (int j = face.numEdges - 1; j >= 0; j--)
229  m_faceEdges[faceEdgeOfs++].edge = old[j].old;
230  if (face.newEdge != -1)
231  m_faceEdges[faceEdgeOfs++].edge = ~face.newEdge;
232  face.numEdges = faceEdgeOfs - face.firstEdge;
233  }
234  m_faceEdges.resize(faceEdgeOfs);
235 
236  // Remap vertices.
237 
238  int vertexOfs = 0;
239  for (int i = 0; i < m_vertices.getSize(); i++)
240  {
241  Vertex& v = m_vertices[i];
242  if (i < firstNewVertex && v.aux.orient >= 0.0f)
243  continue;
244 
245  v.aux.remap = vertexOfs;
246  m_vertices[vertexOfs++].pos = v.pos;
247  }
248  for (int i = m_edges.getSize() - 1; i >= 0; i--)
249  {
250  Vec2i& v = m_edges[i].verts;
251  v.x = m_vertices[v.x].aux.remap;
252  v.y = m_vertices[v.y].aux.remap;
253  }
254  m_vertices.resize(vertexOfs);
255  return true;
256 }
257 
258 //------------------------------------------------------------------------
259 
261 {
262  if (&other == this)
263  return false;
264 
265  bool intersected = false;
266  for (int i = 0; i < other.m_faces.getSize(); i++)
267  if (intersect(other.m_faces[i].planeEq, other.m_faces[i].planeID))
268  intersected = true;
269  return intersected;
270 }
271 
272 //------------------------------------------------------------------------
273 
275 {
276  if (!m_faces.getSize())
277  return 0.0f;
278 
279  F32 volume = 0.0f;
280  const Vec3f& base = m_vertices[0].pos;
281 
282  for (int i = 0; i < m_faces.getSize(); i++)
283  {
284  const Face& face = m_faces[i];
285  const FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
286  Vec3f first = getEdgeStartPos(faceEdges[0].edge) - base;
287 
288  for (int j = 1; j < face.numEdges; j++)
289  {
290  Vec2i v = getEdge(faceEdges[j].edge);
291  volume += cross(m_vertices[v.x].pos - base, m_vertices[v.y].pos - base).dot(first);
292  }
293  }
294  return volume * (1.0f / 6.0f);
295 }
296 
297 //------------------------------------------------------------------------
298 
300 {
301  const Face& face = m_faces[faceIdx];
302  const FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
303  const Vec3f& base = getEdgeStartPos(faceEdges[0].edge);
304  F32 area = 0.0f;
305 
306  for (int i = 1; i < face.numEdges; i++)
307  {
308  Vec2i v = getEdge(faceEdges[i].edge);
309  area += cross(m_vertices[v.x].pos - base, m_vertices[v.y].pos - base).length();
310  }
311  return area * 0.5f;
312 }
313 
314 //------------------------------------------------------------------------
315 
317 {
318  const Face& face = m_faces[faceIdx];
319  const FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
320  const Vec3f& base = getEdgeStartPos(faceEdges[0].edge);
321  Vec3f pos = 0.0f;
322  F32 area = 0.0f;
323 
324  for (int i = 1; i < face.numEdges; i++)
325  {
326  Vec2i v = getEdge(faceEdges[i].edge);
327  const Vec3f& px = m_vertices[v.x].pos;
328  const Vec3f& py = m_vertices[v.y].pos;
329  F32 t = cross(px - base, py - base).length();
330  pos += (px + py) * t;
331  area += t;
332  }
333  return pos * (1.0f / 3.0f / area) + base * (1.0f / 3.0f);
334 }
335 
336 //------------------------------------------------------------------------
337 
339 {
340  if (!m_faces.getSize())
341  return 0.0f;
342 
343  Vec3f pos = 0.0f;
344  F32 volume = 0.0f;
345  const Vec3f& base = m_vertices[0].pos;
346 
347  for (int i = 0; i < m_faces.getSize(); i++)
348  {
349  const Face& face = m_faces[i];
350  const FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
351  Vec3f first = getEdgeStartPos(faceEdges[0].edge) - base;
352 
353  for (int j = 1; j < face.numEdges; j++)
354  {
355  Vec2i v = getEdge(faceEdges[j].edge);
356  const Vec3f& px = m_vertices[v.x].pos;
357  const Vec3f& py = m_vertices[v.y].pos;
358  F32 t = cross(px - base, py - base).dot(first);
359  pos += (px + py + first) * t;
360  volume += t;
361  }
362  }
363  return pos * (1.0f / 4.0f / volume) + base * (1.0f / 2.0f);
364 }
365 
366 //------------------------------------------------------------------------
367 
369 {
370  Mesh<VertexPN>* mesh = new Mesh<VertexPN>;
371  Array<Vec3i>& inds = mesh->mutableIndices(mesh->addSubmesh());
372  Array<S32> vmap(NULL, m_vertices.getSize());
373 
374  for (int i = m_faces.getSize() - 1; i >= 0; i--)
375  {
376  const Face& face = m_faces[i];
377  const FaceEdge* faceEdges = m_faceEdges.getPtr(face.firstEdge);
378  int base = -1;
379 
380  for (int j = face.numEdges - 1; j >= 0; j--)
381  {
382  base = getEdgeStartVertex(faceEdges[j].edge);
383  vmap[base] = mesh->numVertices();
384  VertexPN& v = mesh->addVertex();
385  v.p = m_vertices[base].pos;
386  v.n = face.planeEq.getXYZ();
387  }
388 
389  for (int j = face.numEdges - 1; j >= 0; j--)
390  {
391  Vec2i e = getEdge(faceEdges[j].edge);
392  if (e.x != base && e.y != base)
393  inds.add(Vec3i(vmap[base], vmap[e.x], vmap[e.y]));
394  }
395  }
396  return mesh;
397 }
398 
399 //------------------------------------------------------------------------
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid pixels GLint GLsizei const GLfloat value GLint GLfloat GLfloat v1 GLint GLfloat GLfloat GLfloat v2 GLint GLsizei const GLfloat value GLint GLsizei GLboolean const GLfloat value GLuint program GLuint GLfloat GLfloat GLfloat z GLuint GLint GLenum GLboolean GLsizei const GLvoid pointer GLuint GLuint const GLchar name GLenum GLsizei GLenum GLsizei GLsizei height GLenum GLuint renderbuffer GLenum GLenum GLint params GLuint GLsizei range GLuint GLsizei const GLubyte GLsizei GLenum const GLvoid coords GLuint GLsizei GLsizei GLsizei const GLubyte GLsizei GLenum const GLvoid coords GLuint GLenum GLsizei const GLvoid pathString GLuint GLenum const GLvoid GLbitfield GLuint GLsizei GLenum GLuint GLfloat emScale GLuint GLuint srcPath GLuint GLuint GLenum const GLfloat transformValues GLuint GLenum GLint value GLuint GLenum GLfloat value GLenum GLint GLuint mask
Definition: DLLImports.inl:400
#define NULL
Definition: Defs.hpp:39
Mesh< VertexPN > * createMesh(void) const
int getEdgeStartVertex(int idx) const
FW_CUDA_FUNC Vec3f getXYZ(void) const
Definition: Math.hpp:365
bool intersect(const Vec4f &planeEq, int planeID=-1)
V & addVertex(const V &value)
Definition: Mesh.hpp:227
float F32
Definition: Defs.hpp:89
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v
Definition: DLLImports.inl:329
Array< Vec3i > & mutableIndices(int submesh)
Definition: Mesh.hpp:157
#define ENABLE_ASSERTS
Vec3f p
Definition: Mesh.hpp:255
FW_CUDA_FUNC S32 abs(S32 a)
Definition: Math.hpp:41
#define FW_ASSERT(X)
Definition: Defs.hpp:67
FW_CUDA_FUNC F32 fastClamp(F32 v, F32 lo, F32 hi)
Definition: Math.hpp:110
void setCube(const Vec3f &lo, const Vec3f &hi)
int numVertices(void) const
Definition: Mesh.hpp:136
Vec3f n
Definition: Mesh.hpp:256
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction f
Definition: DLLImports.inl:88
FW_CUDA_FUNC F32 cross(const Vec2f &a, const Vec2f &b)
Definition: Math.hpp:481
int addSubmesh(void)
Definition: Mesh.hpp:163
union FW::ConvexPolyhedron::Vertex::@0 aux
F32 computeArea(void) const
Vec3f computeCenterOfMass(void) const
Vec2i getEdge(int idx) const
F32 computeVolume(void) const
FW_CUDA_FUNC A lerp(const A &a, const A &b, const B &t)
Definition: Math.hpp:115
#define EPSILON
const Vec3f & getEdgeStartPos(int idx) const