|
@@ -16,7 +16,9 @@
|
|
|
TypeHandle BulletHeightfieldShape::_type_handle;
|
|
TypeHandle BulletHeightfieldShape::_type_handle;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- *
|
|
|
|
|
|
|
+ * @brief Creates a collision shape suited for terrains from a rectangular image.
|
|
|
|
|
+ * @details Stores the image's brightness values in a vector Bullet can use,
|
|
|
|
|
+ * while rotating it 90 degrees to the right.
|
|
|
*/
|
|
*/
|
|
|
BulletHeightfieldShape::
|
|
BulletHeightfieldShape::
|
|
|
BulletHeightfieldShape(const PNMImage &image, PN_stdfloat max_height, BulletUpAxis up) {
|
|
BulletHeightfieldShape(const PNMImage &image, PN_stdfloat max_height, BulletUpAxis up) {
|
|
@@ -28,8 +30,10 @@ BulletHeightfieldShape(const PNMImage &image, PN_stdfloat max_height, BulletUpAx
|
|
|
|
|
|
|
|
for (int row=0; row < _num_rows; row++) {
|
|
for (int row=0; row < _num_rows; row++) {
|
|
|
for (int column=0; column < _num_cols; column++) {
|
|
for (int column=0; column < _num_cols; column++) {
|
|
|
- _data[_num_cols * row + column] =
|
|
|
|
|
- max_height * image.get_bright(column, _num_cols - row - 1);
|
|
|
|
|
|
|
+ // Transpose
|
|
|
|
|
+ _data[_num_rows * column + row] =
|
|
|
|
|
+ // Flip y
|
|
|
|
|
+ max_height * image.get_bright(row, _num_cols - column - 1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -59,3 +63,41 @@ set_use_diamond_subdivision(bool flag) {
|
|
|
|
|
|
|
|
return _shape->setUseDiamondSubdivision(flag);
|
|
return _shape->setUseDiamondSubdivision(flag);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @brief Creates a collision shape suited for terrains from a rectangular texture.
|
|
|
|
|
+ * @details Alternative constructor intended for use with ShaderTerrainMesh. This will
|
|
|
|
|
+ * do bilinear sampling at the corners of all texels. Also works with textures
|
|
|
|
|
+ * that are non-power-of-two and/or rectangular.
|
|
|
|
|
+ */
|
|
|
|
|
+BulletHeightfieldShape::
|
|
|
|
|
+BulletHeightfieldShape(Texture *tex, PN_stdfloat max_height, BulletUpAxis up) {
|
|
|
|
|
+
|
|
|
|
|
+ _num_rows = tex->get_x_size() + 1;
|
|
|
|
|
+ _num_cols = tex->get_y_size() + 1;
|
|
|
|
|
+ _data = new float[_num_rows * _num_cols];
|
|
|
|
|
+
|
|
|
|
|
+ PN_stdfloat step_x = 1.0 / (PN_stdfloat)tex->get_x_size();
|
|
|
|
|
+ PN_stdfloat step_y = 1.0 / (PN_stdfloat)tex->get_y_size();
|
|
|
|
|
+
|
|
|
|
|
+ PT(TexturePeeker) peeker = tex->peek();
|
|
|
|
|
+ LColor sample;
|
|
|
|
|
+
|
|
|
|
|
+ for (int row=0; row < _num_rows; row++) {
|
|
|
|
|
+ for (int column=0; column < _num_cols; column++) {
|
|
|
|
|
+ if (!peeker->lookup_bilinear(sample, row * step_x, column * step_y)) {
|
|
|
|
|
+ bullet_cat.error() << "Could not sample texture." << endl;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Transpose
|
|
|
|
|
+ _data[_num_rows * column + row] = max_height * sample.get_x();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _shape = new btHeightfieldTerrainShape(_num_rows,
|
|
|
|
|
+ _num_cols,
|
|
|
|
|
+ _data,
|
|
|
|
|
+ max_height,
|
|
|
|
|
+ up,
|
|
|
|
|
+ true, false);
|
|
|
|
|
+ _shape->setUserPointer(this);
|
|
|
|
|
+}
|