📄 terrainpage.java
字号:
/**
* <code>getSurfaceNormal</code> returns the normal of an arbitrary point
* on the terrain. The normal is linearly interpreted from the normals of
* the 4 nearest defined points. If the point provided is not within the
* bounds of the height map, null is returned.
*
* @param x
* the x coordinate to check.
* @param z
* the z coordinate to check.
* @param store
* the Vector3f object to store the result in. If null, a new one
* is created.
* @return the normal vector at the provided location.
*/
public Vector3f getSurfaceNormal(float x, float z, Vector3f store) {
// determine which quadrant this is in.
Spatial child = null;
int split = (size - 1) >> 1;
float halfmapx = split * stepScale.x, halfmapz = split * stepScale.z;
float newX = 0, newZ = 0;
if (x == 0)
x += .001f;
if (z == 0)
z += .001f;
if (x > 0) {
if (z > 0) {
// upper right
child = getChild(3);
newX = x;
newZ = z;
} else {
// lower right
child = getChild(2);
newX = x;
newZ = z + halfmapz;
}
} else {
if (z > 0) {
// upper left
child = getChild(1);
newX = x + halfmapx;
newZ = z;
} else {
// lower left...
child = getChild(0);
if (x == 0)
x -= .1f;
if (z == 0)
z -= .1f;
newX = x + halfmapx;
newZ = z + halfmapz;
}
}
if (child instanceof TerrainBlock)
return ((TerrainBlock) child).getSurfaceNormal(newX, newZ, store);
else if (child instanceof TerrainPage)
return ((TerrainPage) child).getSurfaceNormal(x
- ((TerrainPage) child).getLocalTranslation().x, z
- ((TerrainPage) child).getLocalTranslation().z, store);
return null;
}
/**
* <code>split</code> divides the heightmap data for four children. The
* children are either pages or blocks. This is dependent on the size of the
* children. If the child's size is less than or equal to the set block
* size, then blocks are created, otherwise, pages are created.
*
* @param blockSize
* the blocks size to test against.
* @param heightMap
* the height data.
*/
private void split(int blockSize, float[] heightMap) {
if ((size >> 1) + 1 <= blockSize) {
createQuadBlock(heightMap);
} else {
createQuadPage(blockSize, heightMap);
}
}
/**
* <code>createQuadPage</code> generates four new pages from this page.
*/
private void createQuadPage(int blockSize, float[] heightMap) {
// create 4 terrain pages
int quarterSize = size >> 2;
int split = (size + 1) >> 1;
Vector2f tempOffset = new Vector2f();
offsetAmount += quarterSize;
// 1 upper left
float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);
Vector3f origin1 = new Vector3f(-quarterSize * stepScale.x, 0,
-quarterSize * stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin1.x;
tempOffset.y += origin1.z;
TerrainPage page1 = new TerrainPage(getName() + "Page1", blockSize,
split, stepScale, heightBlock1, totalSize, tempOffset,
offsetAmount);
page1.setLocalTranslation(origin1);
page1.quadrant = 1;
this.attachChild(page1);
// 2 lower left
float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,
split);
Vector3f origin2 = new Vector3f(-quarterSize * stepScale.x, 0,
quarterSize * stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin2.x;
tempOffset.y += origin2.z;
TerrainPage page2 = new TerrainPage(getName() + "Page2", blockSize,
split, stepScale, heightBlock2, totalSize, tempOffset,
offsetAmount);
page2.setLocalTranslation(origin2);
page2.quadrant = 2;
this.attachChild(page2);
// 3 upper right
float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,
split);
Vector3f origin3 = new Vector3f(quarterSize * stepScale.x, 0,
-quarterSize * stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin3.x;
tempOffset.y += origin3.z;
TerrainPage page3 = new TerrainPage(getName() + "Page3", blockSize,
split, stepScale, heightBlock3, totalSize, tempOffset,
offsetAmount);
page3.setLocalTranslation(origin3);
page3.quadrant = 3;
this.attachChild(page3);
// //
// 4 lower right
float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,
split - 1, split);
Vector3f origin4 = new Vector3f(quarterSize * stepScale.x, 0,
quarterSize * stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin4.x;
tempOffset.y += origin4.z;
TerrainPage page4 = new TerrainPage(getName() + "Page4", blockSize,
split, stepScale, heightBlock4, totalSize, tempOffset,
offsetAmount);
page4.setLocalTranslation(origin4);
page4.quadrant = 4;
this.attachChild(page4);
}
/**
* <code>createQuadBlock</code> creates four child blocks from this page.
*/
private void createQuadBlock(float[] heightMap) {
// create 4 terrain blocks
int quarterSize = size >> 2;
int halfSize = size >> 1;
int split = (size + 1) >> 1;
Vector2f tempOffset = new Vector2f();
offsetAmount += quarterSize;
// 1 upper left
float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);
Vector3f origin1 = new Vector3f(-halfSize * stepScale.x, 0, -halfSize
* stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin1.x / 2;
tempOffset.y += origin1.z / 2;
TerrainBlock block1 = new TerrainBlock(getName() + "Block1", split,
stepScale, heightBlock1, origin1, totalSize, tempOffset,
offsetAmount);
block1.setQuadrant((short) 1);
this.attachChild(block1);
block1.setModelBound(new BoundingBox());
block1.updateModelBound();
// 2 lower left
float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,
split);
Vector3f origin2 = new Vector3f(-halfSize * stepScale.x, 0, 0);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += origin1.x / 2;
tempOffset.y += quarterSize * stepScale.z;
TerrainBlock block2 = new TerrainBlock(getName() + "Block2", split,
stepScale, heightBlock2, origin2, totalSize, tempOffset,
offsetAmount);
block2.setQuadrant((short) 2);
this.attachChild(block2);
block2.setModelBound(new BoundingBox());
block2.updateModelBound();
// 3 upper right
float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,
split);
Vector3f origin3 = new Vector3f(0, 0, -halfSize * stepScale.z);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += quarterSize * stepScale.x;
tempOffset.y += origin3.z / 2;
TerrainBlock block3 = new TerrainBlock(getName() + "Block3", split,
stepScale, heightBlock3, origin3, totalSize, tempOffset,
offsetAmount);
block3.setQuadrant((short) 3);
this.attachChild(block3);
block3.setModelBound(new BoundingBox());
block3.updateModelBound();
// 4 lower right
float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,
split - 1, split);
Vector3f origin4 = new Vector3f(0, 0, 0);
tempOffset.x = offset.x;
tempOffset.y = offset.y;
tempOffset.x += quarterSize * stepScale.x;
tempOffset.y += quarterSize * stepScale.z;
TerrainBlock block4 = new TerrainBlock(getName() + "Block4", split,
stepScale, heightBlock4, origin4, totalSize, tempOffset,
offsetAmount);
block4.setQuadrant((short) 4);
this.attachChild(block4);
block4.setModelBound(new BoundingBox());
block4.updateModelBound();
}
/**
* Returns the current offset amount. This is used when building texture
* coordinates.
*
* @return The current offset amount.
*/
public Vector2f getOffset() {
return offset;
}
/**
* Returns the total size of the terrain.
*
* @return The terrain's total size.
*/
public int getTotalSize() {
return totalSize;
}
/**
* Returns the size of this terrain page.
*
* @return The current block size.
*/
public int getSize() {
return size;
}
/**
* Returns the step scale that stretches the height map.
*
* @return The current step scale.
*/
public Vector3f getStepScale() {
return stepScale;
}
/**
* Returns the offset amount this terrain block uses for textures.
*
* @return The current offset amount.
*/
public float getOffsetAmount() {
return offsetAmount;
}
/**
* Sets the value for the current offset amount to use when building texture
* coordinates. Note that this does <b>NOT</b> rebuild the terrain at all.
* This is mostly used for outside constructors of terrain blocks.
*
* @param offset
* The new texture offset.
*/
public void setOffset(Vector2f offset) {
this.offset = offset;
}
/**
* Sets the total size of the terrain . Note that this does <b>NOT</b>
* rebuild the terrain at all. This is mostly used for outside constructors
* of terrain blocks.
*
* @param totalSize
* The new total size.
*/
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
/**
* Sets the size of this terrain page. Note that this does <b>NOT</b>
* rebuild the terrain at all. This is mostly used for outside constructors
* of terrain blocks.
*
* @param size
* The new size.
*/
public void setSize(int size) {
this.size = size;
}
/**
* Sets the step scale of this terrain page's height map. Note that this
* does <b>NOT</b> rebuild the terrain at all. This is mostly used for
* outside constructors of terrain blocks.
*
* @param stepScale
* The new step scale.
*/
public void setStepScale(Vector3f stepScale) {
this.stepScale = stepScale;
}
/**
* Sets the offset of this terrain texture map. Note that this does <b>NOT</b>
* rebuild the terrain at all. This is mostly used for outside constructors
* of terrain blocks.
*
* @param offsetAmount
* The new texture offset.
*/
public void setOffsetAmount(float offsetAmount) {
this.offsetAmount = offsetAmount;
}
/*
* Deletes the VBO for this normal buffer, if any is present.
*/
private void deleteNormalVBO(TerrainBlock block) {
if (block.getVBOInfo() != null
&& block.getVBOInfo().getVBOIndexID() > 0) {
DisplaySystem.getDisplaySystem().getRenderer().deleteVBO(
block.getNormalBuffer());
block.getVBOInfo().setVBONormalID(-1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -