Blender  V3.3
btHeightfieldTerrainShape.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
17 
19 
21  int heightStickWidth, int heightStickLength, const void* heightfieldData,
22  btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
23  PHY_ScalarType hdt, bool flipQuadEdges)
24  :m_userIndex2(-1),
25  m_userValue3(0),
27 {
28  initialize(heightStickWidth, heightStickLength, heightfieldData,
29  heightScale, minHeight, maxHeight, upAxis, hdt,
30  flipQuadEdges);
31 }
32 
33 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
34  :m_userIndex2(-1),
35  m_userValue3(0),
37 {
38  // legacy constructor: support only float or unsigned char,
39  // and min height is zero
40  PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
41  btScalar minHeight = 0.0f;
42 
43  // previously, height = uchar * maxHeight / 65535.
44  // So to preserve legacy behavior, heightScale = maxHeight / 65535
45  btScalar heightScale = maxHeight / 65535;
46 
47  initialize(heightStickWidth, heightStickLength, heightfieldData,
48  heightScale, minHeight, maxHeight, upAxis, hdt,
49  flipQuadEdges);
50 }
51 
53  int heightStickWidth, int heightStickLength, const void* heightfieldData,
54  btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
55  PHY_ScalarType hdt, bool flipQuadEdges)
56 {
57  // validation
58  btAssert(heightStickWidth > 1); // && "bad width");
59  btAssert(heightStickLength > 1); // && "bad length");
60  btAssert(heightfieldData); // && "null heightfield data");
61  // btAssert(heightScale) -- do we care? Trust caller here
62  btAssert(minHeight <= maxHeight); // && "bad min/max height");
63  btAssert(upAxis >= 0 && upAxis < 3); // && "bad upAxis--should be in range [0,2]");
64  btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT); // && "Bad height data type enum");
65 
66  // initialize member variables
67  m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
68  m_heightStickWidth = heightStickWidth;
69  m_heightStickLength = heightStickLength;
70  m_minHeight = minHeight;
71  m_maxHeight = maxHeight;
72  m_width = (btScalar)(heightStickWidth - 1);
73  m_length = (btScalar)(heightStickLength - 1);
74  m_heightScale = heightScale;
75  m_heightfieldDataUnknown = heightfieldData;
76  m_heightDataType = hdt;
77  m_flipQuadEdges = flipQuadEdges;
79  m_useZigzagSubdivision = false;
80  m_flipTriangleWinding = false;
81  m_upAxis = upAxis;
82  m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
83 
87 
88  // determine min/max axis-aligned bounding box (aabb) values
89  switch (m_upAxis)
90  {
91  case 0:
92  {
93  m_localAabbMin.setValue(m_minHeight, 0, 0);
95  break;
96  }
97  case 1:
98  {
99  m_localAabbMin.setValue(0, m_minHeight, 0);
101  break;
102  };
103  case 2:
104  {
105  m_localAabbMin.setValue(0, 0, m_minHeight);
107  break;
108  }
109  default:
110  {
111  //need to get valid m_upAxis
112  btAssert(0); // && "Bad m_upAxis");
113  }
114  }
115 
116  // remember origin (defined as exact middle of aabb)
118 }
119 
121 {
123 }
124 
125 void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
126 {
128 
129  btVector3 localOrigin(0, 0, 0);
130  localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
131  localOrigin *= m_localScaling;
132 
133  btMatrix3x3 abs_b = t.getBasis().absolute();
134  btVector3 center = t.getOrigin();
135  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
136  extent += btVector3(getMargin(), getMargin(), getMargin());
137 
138  aabbMin = center - extent;
139  aabbMax = center + extent;
140 }
141 
145 btScalar
147 {
148  btScalar val = 0.f;
149  switch (m_heightDataType)
150  {
151  case PHY_FLOAT:
152  {
154  break;
155  }
156 
157  case PHY_UCHAR:
158  {
159  unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
160  val = heightFieldValue * m_heightScale;
161  break;
162  }
163 
164  case PHY_SHORT:
165  {
166  short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
167  val = hfValue * m_heightScale;
168  break;
169  }
170 
171  default:
172  {
173  btAssert(!"Bad m_heightDataType");
174  }
175  }
176 
177  return val;
178 }
179 
181 void btHeightfieldTerrainShape::getVertex(int x, int y, btVector3& vertex) const
182 {
183  btAssert(x >= 0);
184  btAssert(y >= 0);
187 
189 
190  switch (m_upAxis)
191  {
192  case 0:
193  {
194  vertex.setValue(
195  height - m_localOrigin.getX(),
196  (-m_width / btScalar(2.0)) + x,
197  (-m_length / btScalar(2.0)) + y);
198  break;
199  }
200  case 1:
201  {
202  vertex.setValue(
203  (-m_width / btScalar(2.0)) + x,
204  height - m_localOrigin.getY(),
205  (-m_length / btScalar(2.0)) + y);
206  break;
207  };
208  case 2:
209  {
210  vertex.setValue(
211  (-m_width / btScalar(2.0)) + x,
212  (-m_length / btScalar(2.0)) + y,
213  height - m_localOrigin.getZ());
214  break;
215  }
216  default:
217  {
218  //need to get valid m_upAxis
219  btAssert(0);
220  }
221  }
222 
223  vertex *= m_localScaling;
224 }
225 
226 static inline int
228  btScalar x)
229 {
230  if (x < 0.0)
231  {
232  return (int)(x - 0.5);
233  }
234  return (int)(x + 0.5);
235 }
236 
238 
246 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point, int /*isMax*/) const
247 {
248  btVector3 clampedPoint(point);
249  clampedPoint.setMax(m_localAabbMin);
250  clampedPoint.setMin(m_localAabbMax);
251 
252  out[0] = getQuantized(clampedPoint.getX());
253  out[1] = getQuantized(clampedPoint.getY());
254  out[2] = getQuantized(clampedPoint.getZ());
255 }
256 
258 
265 {
266  // scale down the input aabb's so they are in local (non-scaled) coordinates
267  btVector3 localAabbMin = aabbMin * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
268  btVector3 localAabbMax = aabbMax * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
269 
270  // account for local origin
271  localAabbMin += m_localOrigin;
272  localAabbMax += m_localOrigin;
273 
274  //quantize the aabbMin and aabbMax, and adjust the start/end ranges
275  int quantizedAabbMin[3];
276  int quantizedAabbMax[3];
277  quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
278  quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
279 
280  // expand the min/max quantized values
281  // this is to catch the case where the input aabb falls between grid points!
282  for (int i = 0; i < 3; ++i)
283  {
284  quantizedAabbMin[i]--;
285  quantizedAabbMax[i]++;
286  }
287 
288  int startX = 0;
289  int endX = m_heightStickWidth - 1;
290  int startJ = 0;
291  int endJ = m_heightStickLength - 1;
292 
293  switch (m_upAxis)
294  {
295  case 0:
296  {
297  if (quantizedAabbMin[1] > startX)
298  startX = quantizedAabbMin[1];
299  if (quantizedAabbMax[1] < endX)
300  endX = quantizedAabbMax[1];
301  if (quantizedAabbMin[2] > startJ)
302  startJ = quantizedAabbMin[2];
303  if (quantizedAabbMax[2] < endJ)
304  endJ = quantizedAabbMax[2];
305  break;
306  }
307  case 1:
308  {
309  if (quantizedAabbMin[0] > startX)
310  startX = quantizedAabbMin[0];
311  if (quantizedAabbMax[0] < endX)
312  endX = quantizedAabbMax[0];
313  if (quantizedAabbMin[2] > startJ)
314  startJ = quantizedAabbMin[2];
315  if (quantizedAabbMax[2] < endJ)
316  endJ = quantizedAabbMax[2];
317  break;
318  };
319  case 2:
320  {
321  if (quantizedAabbMin[0] > startX)
322  startX = quantizedAabbMin[0];
323  if (quantizedAabbMax[0] < endX)
324  endX = quantizedAabbMax[0];
325  if (quantizedAabbMin[1] > startJ)
326  startJ = quantizedAabbMin[1];
327  if (quantizedAabbMax[1] < endJ)
328  endJ = quantizedAabbMax[1];
329  break;
330  }
331  default:
332  {
333  //need to get valid m_upAxis
334  btAssert(0);
335  }
336  }
337 
338  // TODO If m_vboundsGrid is available, use it to determine if we really need to process this area
339 
340  for (int j = startJ; j < endJ; j++)
341  {
342  for (int x = startX; x < endX; x++)
343  {
344  btVector3 vertices[3];
345  int indices[3] = { 0, 1, 2 };
347  {
348  indices[0] = 2;
349  indices[2] = 0;
350  }
351 
352  if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
353  {
354  //first triangle
355  getVertex(x, j, vertices[indices[0]]);
356  getVertex(x, j + 1, vertices[indices[1]]);
357  getVertex(x + 1, j + 1, vertices[indices[2]]);
358  callback->processTriangle(vertices, 2 * x, j);
359  //second triangle
360  // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
361  getVertex(x + 1, j + 1, vertices[indices[1]]);
362  getVertex(x + 1, j, vertices[indices[2]]);
363  callback->processTriangle(vertices, 2 * x+1, j);
364  }
365  else
366  {
367  //first triangle
368  getVertex(x, j, vertices[indices[0]]);
369  getVertex(x, j + 1, vertices[indices[1]]);
370  getVertex(x + 1, j, vertices[indices[2]]);
371  callback->processTriangle(vertices, 2 * x, j);
372  //second triangle
373  getVertex(x + 1, j, vertices[indices[0]]);
374  //getVertex(x,j+1,vertices[1]);
375  getVertex(x + 1, j + 1, vertices[indices[2]]);
376  callback->processTriangle(vertices, 2 * x+1, j);
377  }
378  }
379  }
380 }
381 
383 {
384  //moving concave objects not supported
385 
386  inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
387 }
388 
390 {
391  m_localScaling = scaling;
392 }
394 {
395  return m_localScaling;
396 }
397 
398 namespace
399 {
400  struct GridRaycastState
401  {
402  int x; // Next quad coords
403  int z;
404  int prev_x; // Previous quad coords
405  int prev_z;
406  btScalar param; // Exit param for previous quad
407  btScalar prevParam; // Enter param for previous quad
408  btScalar maxDistanceFlat;
409  btScalar maxDistance3d;
410  };
411 }
412 
413 // TODO Does it really need to take 3D vectors?
417 template <typename Action_T>
418 void gridRaycast(Action_T& quadAction, const btVector3& beginPos, const btVector3& endPos, int indices[3])
419 {
420  GridRaycastState rs;
421  rs.maxDistance3d = beginPos.distance(endPos);
422  if (rs.maxDistance3d < 0.0001)
423  {
424  // Consider the ray is too small to hit anything
425  return;
426  }
427 
428 
429  btScalar rayDirectionFlatX = endPos[indices[0]] - beginPos[indices[0]];
430  btScalar rayDirectionFlatZ = endPos[indices[2]] - beginPos[indices[2]];
431  rs.maxDistanceFlat = btSqrt(rayDirectionFlatX * rayDirectionFlatX + rayDirectionFlatZ * rayDirectionFlatZ);
432 
433  if (rs.maxDistanceFlat < 0.0001)
434  {
435  // Consider the ray vertical
436  rayDirectionFlatX = 0;
437  rayDirectionFlatZ = 0;
438  }
439  else
440  {
441  rayDirectionFlatX /= rs.maxDistanceFlat;
442  rayDirectionFlatZ /= rs.maxDistanceFlat;
443  }
444 
445  const int xiStep = rayDirectionFlatX > 0 ? 1 : rayDirectionFlatX < 0 ? -1 : 0;
446  const int ziStep = rayDirectionFlatZ > 0 ? 1 : rayDirectionFlatZ < 0 ? -1 : 0;
447 
448  const float infinite = 9999999;
449  const btScalar paramDeltaX = xiStep != 0 ? 1.f / btFabs(rayDirectionFlatX) : infinite;
450  const btScalar paramDeltaZ = ziStep != 0 ? 1.f / btFabs(rayDirectionFlatZ) : infinite;
451 
452  // pos = param * dir
453  btScalar paramCrossX; // At which value of `param` we will cross a x-axis lane?
454  btScalar paramCrossZ; // At which value of `param` we will cross a z-axis lane?
455 
456  // paramCrossX and paramCrossZ are initialized as being the first cross
457  // X initialization
458  if (xiStep != 0)
459  {
460  if (xiStep == 1)
461  {
462  paramCrossX = (ceil(beginPos[indices[0]]) - beginPos[indices[0]]) * paramDeltaX;
463  }
464  else
465  {
466  paramCrossX = (beginPos[indices[0]] - floor(beginPos[indices[0]])) * paramDeltaX;
467  }
468  }
469  else
470  {
471  paramCrossX = infinite; // Will never cross on X
472  }
473 
474  // Z initialization
475  if (ziStep != 0)
476  {
477  if (ziStep == 1)
478  {
479  paramCrossZ = (ceil(beginPos[indices[2]]) - beginPos[indices[2]]) * paramDeltaZ;
480  }
481  else
482  {
483  paramCrossZ = (beginPos[indices[2]] - floor(beginPos[indices[2]])) * paramDeltaZ;
484  }
485  }
486  else
487  {
488  paramCrossZ = infinite; // Will never cross on Z
489  }
490 
491  rs.x = static_cast<int>(floor(beginPos[indices[0]]));
492  rs.z = static_cast<int>(floor(beginPos[indices[2]]));
493 
494  // Workaround cases where the ray starts at an integer position
495  if (paramCrossX == 0.0)
496  {
497  paramCrossX += paramDeltaX;
498  // If going backwards, we should ignore the position we would get by the above flooring,
499  // because the ray is not heading in that direction
500  if (xiStep == -1)
501  {
502  rs.x -= 1;
503  }
504  }
505 
506  if (paramCrossZ == 0.0)
507  {
508  paramCrossZ += paramDeltaZ;
509  if (ziStep == -1)
510  rs.z -= 1;
511  }
512 
513  rs.prev_x = rs.x;
514  rs.prev_z = rs.z;
515  rs.param = 0;
516 
517  while (true)
518  {
519  rs.prev_x = rs.x;
520  rs.prev_z = rs.z;
521  rs.prevParam = rs.param;
522 
523  if (paramCrossX < paramCrossZ)
524  {
525  // X lane
526  rs.x += xiStep;
527  // Assign before advancing the param,
528  // to be in sync with the initialization step
529  rs.param = paramCrossX;
530  paramCrossX += paramDeltaX;
531  }
532  else
533  {
534  // Z lane
535  rs.z += ziStep;
536  rs.param = paramCrossZ;
537  paramCrossZ += paramDeltaZ;
538  }
539 
540  if (rs.param > rs.maxDistanceFlat)
541  {
542  rs.param = rs.maxDistanceFlat;
543  quadAction(rs);
544  break;
545  }
546  else
547  {
548  quadAction(rs);
549  }
550  }
551 }
552 
554 {
558  int width;
559  int length;
561 
562  void exec(int x, int z) const
563  {
564  if (x < 0 || z < 0 || x >= width || z >= length)
565  {
566  return;
567  }
568 
569  btVector3 vertices[3];
570 
571  // TODO Since this is for raycasts, we could greatly benefit from an early exit on the first hit
572 
573  // Check quad
574  if (flipQuadEdges || (useDiamondSubdivision && (((z + x) & 1) > 0)))
575  {
576  // First triangle
577  shape->getVertex(x, z, vertices[0]);
578  shape->getVertex(x + 1, z, vertices[1]);
579  shape->getVertex(x + 1, z + 1, vertices[2]);
580  callback->processTriangle(vertices, x, z);
581 
582  // Second triangle
583  shape->getVertex(x, z, vertices[0]);
584  shape->getVertex(x + 1, z + 1, vertices[1]);
585  shape->getVertex(x, z + 1, vertices[2]);
586  callback->processTriangle(vertices, x, z);
587  }
588  else
589  {
590  // First triangle
591  shape->getVertex(x, z, vertices[0]);
592  shape->getVertex(x, z + 1, vertices[1]);
593  shape->getVertex(x + 1, z, vertices[2]);
594  callback->processTriangle(vertices, x, z);
595 
596  // Second triangle
597  shape->getVertex(x + 1, z, vertices[0]);
598  shape->getVertex(x, z + 1, vertices[1]);
599  shape->getVertex(x + 1, z + 1, vertices[2]);
600  callback->processTriangle(vertices, x, z);
601  }
602  }
603 
604  void operator()(const GridRaycastState& bs) const
605  {
606  exec(bs.prev_x, bs.prev_z);
607  }
608 };
609 
611 {
613  int width;
614  int length;
616 
620 
621  int* m_indices;
623 
625  : vbounds(bnd),
627  {
628  }
629  void operator()(const GridRaycastState& rs) const
630  {
631  int x = rs.prev_x;
632  int z = rs.prev_z;
633 
634  if (x < 0 || z < 0 || x >= width || z >= length)
635  {
636  return;
637  }
638 
639  const btHeightfieldTerrainShape::Range chunk = vbounds[x + z * width];
640 
641  btVector3 enterPos;
642  btVector3 exitPos;
643 
644  if (rs.maxDistanceFlat > 0.0001)
645  {
646  btScalar flatTo3d = chunkSize * rs.maxDistance3d / rs.maxDistanceFlat;
647  btScalar enterParam3d = rs.prevParam * flatTo3d;
648  btScalar exitParam3d = rs.param * flatTo3d;
649  enterPos = rayBegin + rayDir * enterParam3d;
650  exitPos = rayBegin + rayDir * exitParam3d;
651 
652  // We did enter the flat projection of the AABB,
653  // but we have to check if we intersect it on the vertical axis
654  if (enterPos[1] > chunk.max && exitPos[m_indices[1]] > chunk.max)
655  {
656  return;
657  }
658  if (enterPos[1] < chunk.min && exitPos[m_indices[1]] < chunk.min)
659  {
660  return;
661  }
662  }
663  else
664  {
665  // Consider the ray vertical
666  // (though we shouldn't reach this often because there is an early check up-front)
667  enterPos = rayBegin;
668  exitPos = rayEnd;
669  }
670 
671  gridRaycast(processTriangles, enterPos, exitPos, m_indices);
672  // Note: it could be possible to have more than one grid at different levels,
673  // to do this there would be a branch using a pointer to another ProcessVBoundsAction
674  }
675 };
676 
677 // TODO How do I interrupt the ray when there is a hit? `callback` does not return any result
680 void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const
681 {
682  // Transform to cell-local
683  btVector3 beginPos = raySource / m_localScaling;
684  btVector3 endPos = rayTarget / m_localScaling;
685  beginPos += m_localOrigin;
686  endPos += m_localOrigin;
687 
688  ProcessTrianglesAction processTriangles;
689  processTriangles.shape = this;
690  processTriangles.flipQuadEdges = m_flipQuadEdges;
692  processTriangles.callback = callback;
693  processTriangles.width = m_heightStickWidth - 1;
694  processTriangles.length = m_heightStickLength - 1;
695 
696  // TODO Transform vectors to account for m_upAxis
697  int indices[3] = { 0, 1, 2 };
698  if (m_upAxis == 2)
699  {
700  indices[1] = 2;
701  indices[2] = 1;
702  }
703  int iBeginX = static_cast<int>(floor(beginPos[indices[0]]));
704  int iBeginZ = static_cast<int>(floor(beginPos[indices[2]]));
705  int iEndX = static_cast<int>(floor(endPos[indices[0]]));
706  int iEndZ = static_cast<int>(floor(endPos[indices[2]]));
707 
708  if (iBeginX == iEndX && iBeginZ == iEndZ)
709  {
710  // The ray will never cross quads within the plane,
711  // so directly process triangles within one quad
712  // (typically, vertical rays should end up here)
713  processTriangles.exec(iBeginX, iEndZ);
714  return;
715  }
716 
717 
718 
719  if (m_vboundsGrid.size()==0)
720  {
721  // Process all quads intersecting the flat projection of the ray
722  gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
723  }
724  else
725  {
726  btVector3 rayDiff = endPos - beginPos;
727  btScalar flatDistance2 = rayDiff[indices[0]] * rayDiff[indices[0]] + rayDiff[indices[2]] * rayDiff[indices[2]];
728  if (flatDistance2 < m_vboundsChunkSize * m_vboundsChunkSize)
729  {
730  // Don't use chunks, the ray is too short in the plane
731  gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
732  }
733 
734  ProcessVBoundsAction processVBounds(m_vboundsGrid, &indices[0]);
735  processVBounds.width = m_vboundsGridWidth;
736  processVBounds.length = m_vboundsGridLength;
737  processVBounds.rayBegin = beginPos;
738  processVBounds.rayEnd = endPos;
739  processVBounds.rayDir = rayDiff.normalized();
740  processVBounds.processTriangles = processTriangles;
741  processVBounds.chunkSize = m_vboundsChunkSize;
742  // The ray is long, run raycast on a higher-level grid
743  gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize, indices);
744  }
745 }
746 
751 {
752  if (chunkSize <= 0)
753  {
755  return;
756  }
757 
758  m_vboundsChunkSize = chunkSize;
759  int nChunksX = m_heightStickWidth / chunkSize;
760  int nChunksZ = m_heightStickLength / chunkSize;
761 
762  if (m_heightStickWidth % chunkSize > 0)
763  {
764  ++nChunksX; // In case terrain size isn't dividable by chunk size
765  }
766  if (m_heightStickLength % chunkSize > 0)
767  {
768  ++nChunksZ;
769  }
770 
771  if (m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
772  {
774  m_vboundsGridWidth = nChunksX;
775  m_vboundsGridLength = nChunksZ;
776  }
777 
778  if (nChunksX == 0 || nChunksZ == 0)
779  {
780  return;
781  }
782 
783  // This data structure is only reallocated if the required size changed
784  m_vboundsGrid.resize(nChunksX * nChunksZ);
785 
786  // Compute min and max height for all chunks
787  for (int cz = 0; cz < nChunksZ; ++cz)
788  {
789  int z0 = cz * chunkSize;
790 
791  for (int cx = 0; cx < nChunksX; ++cx)
792  {
793  int x0 = cx * chunkSize;
794 
795  Range r;
796 
797  r.min = getRawHeightFieldValue(x0, z0);
798  r.max = r.min;
799 
800  // Compute min and max height for this chunk.
801  // We have to include one extra cell to account for neighbors.
802  // Here is why:
803  // Say we have a flat terrain, and a plateau that fits a chunk perfectly.
804  //
805  // Left Right
806  // 0---0---0---1---1---1
807  // | | | | | |
808  // 0---0---0---1---1---1
809  // | | | | | |
810  // 0---0---0---1---1---1
811  // x
812  //
813  // If the AABB for the Left chunk did not share vertices with the Right,
814  // then we would fail collision tests at x due to a gap.
815  //
816  for (int z = z0; z < z0 + chunkSize + 1; ++z)
817  {
818  if (z >= m_heightStickLength)
819  {
820  continue;
821  }
822 
823  for (int x = x0; x < x0 + chunkSize + 1; ++x)
824  {
825  if (x >= m_heightStickWidth)
826  {
827  continue;
828  }
829 
831 
832  if (height < r.min)
833  {
834  r.min = height;
835  }
836  else if (height > r.max)
837  {
838  r.max = height;
839  }
840  }
841  }
842 
843  m_vboundsGrid[cx + cz * nChunksX] = r;
844  }
845  }
846 }
847 
849 {
850  m_vboundsGrid.clear();
851 }
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
virtual void setLocalScaling(const btVector3 &scaling)
in case we receive negative scaling
Definition: btBox2dShape.h:120
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
Definition: btConeShape.h:54
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const
getAabb's default implementation is brute force, expected derived classes to implement a fast dedicat...
virtual void getVertex(int i, btVector3 &vtx) const
Definition: btBox2dShape.h:179
@ TERRAIN_SHAPE_PROXYTYPE
void performRaycast(btTriangleCallback *callback, const btVector3 &raySource, const btVector3 &rayTarget)
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
Definition: btEmptyShape.h:57
btTriangleInfoMap * m_triangleInfoMap
int m_userIndex2
virtual const btVector3 & getLocalScaling() const =0
virtual btScalar getMargin() const =0
btVector3 m_localAabbMin
btVector3 m_localAabbMax
btVector3 m_localScaling
PHY_ScalarType
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
static int getQuantized(btScalar x)
void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector3 &endPos, int indices[3])
const void * m_heightfieldDataUnknown
btAlignedObjectArray< Range > m_vboundsGrid
PHY_ScalarType m_heightDataType
int m_heightStickWidth
terrain data
btVector3 m_localOrigin
virtual btScalar getRawHeightFieldValue(int x, int y) const
btScalar m_heightScale
btScalar m_maxHeight
virtual ~btHeightfieldTerrainShape()
int m_vboundsGridWidth
void clearAccelerator()
btScalar m_userValue3
bool m_useDiamondSubdivision
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
preferred constructor
btScalar m_minHeight
int m_vboundsGridLength
const unsigned char * m_heightfieldDataUnsignedChar
const short * m_heightfieldDataShort
bool m_useZigzagSubdivision
int m_heightStickLength
btScalar m_width
btScalar m_length
int m_vboundsChunkSize
bool m_flipTriangleWinding
void buildAccelerator(int chunkSize=16)
const btScalar * m_heightfieldDataFloat
bool m_flipQuadEdges
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:50
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short *out, const btVector3 &point2, int isMax) const
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
SIMD_FORCE_INLINE btScalar btFabs(btScalar x)
Definition: btScalar.h:497
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
Definition: btScalar.h:466
#define btAssert(x)
Definition: btScalar.h:295
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:30
btVector3
btVector3 can be used to represent 3D points and vectors. It has an un-used w component to suit 16-by...
Definition: btVector3.h:82
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
DEGForeachIDComponentCallback callback
ccl_gpu_kernel_postfix int ccl_global int * indices
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
T floor(const T &a)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
void operator()(const GridRaycastState &bs) const
void exec(int x, int z) const
const btHeightfieldTerrainShape * shape
void operator()(const GridRaycastState &rs) const
ProcessVBoundsAction(const btAlignedObjectArray< btHeightfieldTerrainShape::Range > &bnd, int *indices)
ProcessTrianglesAction processTriangles
const btAlignedObjectArray< btHeightfieldTerrainShape::Range > & vbounds
static void initialize(SubdivDisplacement *displacement)