From cc51e4c9083f5ecd581c1802e2d57ac24ac06263 Mon Sep 17 00:00:00 2001 From: austin Date: Thu, 21 Nov 2024 18:30:17 -0500 Subject: [PATCH] foliage work --- docs/src/progress/renderertodo.md | 1 + .../client/terrain/foliage/FoliageCell.java | 55 +--- .../client/terrain/foliage/FoliageModel.java | 282 ++++++++++-------- 3 files changed, 168 insertions(+), 170 deletions(-) diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 75bc2cd7..62202e5c 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1113,6 +1113,7 @@ Change grass texture Fix allocations on FoliageChunk child iterations Reduce near clip to remove flickering on far chunks Complete overhaul of foliage management +Fix foliage inconsistently placing on varied terrain # TODO diff --git a/src/main/java/electrosphere/client/terrain/foliage/FoliageCell.java b/src/main/java/electrosphere/client/terrain/foliage/FoliageCell.java index aeb73960..b945bbdb 100644 --- a/src/main/java/electrosphere/client/terrain/foliage/FoliageCell.java +++ b/src/main/java/electrosphere/client/terrain/foliage/FoliageCell.java @@ -276,7 +276,7 @@ public class FoliageCell { */ protected void generate(){ boolean shouldGenerate = false; - if(voxelPos.y + 1 >= ServerTerrainChunk.CHUNK_DIMENSION){ + if(!Globals.clientDrawCellManager.hasGeneratedPhysics(worldPos.x, worldPos.y, worldPos.z)){ return; } ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos,ChunkData.NO_STRIDE); @@ -285,61 +285,38 @@ public class FoliageCell { } //get foliage types supported List foliageTypesSupported = new LinkedList(); - boolean airAbove = data.getType(voxelPos.x,voxelPos.y+1,voxelPos.z) == 0; + boolean airAbove = true; int scale = (int)Math.pow(2,lod); for(int x = 0; x < scale; x++){ for(int y = 0; y < scale; y++){ for(int z = 0; z < scale; z++){ - List currentList = Globals.gameConfigCurrent.getVoxelData().getTypeFromId(data.getType(voxelPos)).getAmbientFoliage(); + if(voxelPos.y + y >= ServerTerrainChunk.CHUNK_DIMENSION){ + continue; + } + List currentList = Globals.gameConfigCurrent.getVoxelData().getTypeFromId(data.getType(new Vector3i(voxelPos).add(x,y,z))).getAmbientFoliage(); if(currentList == null){ continue; } foliageTypesSupported.addAll(currentList); - airAbove = data.getType(voxelPos.x,voxelPos.y+1,voxelPos.z) == 0; + airAbove = data.getType(voxelPos.x + x,voxelPos.y + y + 1,voxelPos.z + z) == 0; if(foliageTypesSupported != null && foliageTypesSupported.size() > 0 && airAbove){ shouldGenerate = true; + break; } } + if(shouldGenerate){ + break; + } + } + if(shouldGenerate){ + break; } } if(shouldGenerate){ + Entity oldEntity = this.modelEntity; //create entity this.modelEntity = EntityCreationUtils.createClientSpatialEntity(); - FoliageModel.clientCreateFoliageChunkEntity(foliageTypesSupported,scale,this.modelEntity,this.getRealPos(),worldPos,voxelPos,null,null); - //get type - // String foliageTypeName = foliageTypesSupported.get(placementRandomizer.nextInt() % foliageTypesSupported.size()); - // FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(foliageTypeName); - - // //create cell and buffer - // ByteBuffer buffer = BufferUtils.createByteBuffer(TARGET_FOLIAGE_PER_CELL * SINGLE_FOLIAGE_DATA_SIZE_BYTES); - // if(buffer.capacity() < TARGET_FOLIAGE_PER_CELL * SINGLE_FOLIAGE_DATA_SIZE_BYTES){ - // LoggerInterface.loggerEngine.WARNING("Failed to allocate data for foliage cell! " + buffer.limit()); - // } - // FloatBuffer floatBufferView = buffer.asFloatBuffer(); - // int drawCount = 0; - // for(int x = 0; x < scale; x++){ - // for(int y = 0; y < scale; y++){ - // for(int z = 0; z < scale; z++){ - // drawCount = drawCount + this.insertBlades(x, y, z, floatBufferView, data); - // } - // } - // } - // // drawCount = drawCount + this.insertBlades(0, 0, 0, floatBufferView, data); - // if(drawCount > 0){ - // buffer.position(0); - // buffer.limit(TARGET_FOLIAGE_PER_CELL * SINGLE_FOLIAGE_DATA_SIZE_BYTES); - // //construct data texture - // Texture dataTexture = new Texture(Globals.renderingEngine.getOpenGLState(),buffer,SINGLE_FOLIAGE_DATA_SIZE_BYTES / 4,TARGET_FOLIAGE_PER_CELL); - - // //create entity - // this.modelEntity = EntityCreationUtils.createClientSpatialEntity(); - - // TextureInstancedActor.attachTextureInstancedActor(this.modelEntity, foliageType.getGraphicsTemplate().getModel().getPath(), vertexPath, fragmentPath, dataTexture, drawCount); - // ClientEntityUtils.initiallyPositionEntity(this.modelEntity, this.getRealPos(), new Quaterniond()); - // EntityUtils.getScale(this.modelEntity).set(1,1,1); - // //add ambient foliage behavior tree - // AmbientFoliage.attachAmbientFoliageTree(this.modelEntity, 1.0f, foliageType.getGrowthModel().getGrowthRate()); - // } + FoliageModel.clientCreateFoliageChunkEntity(foliageTypesSupported,scale,this.modelEntity,this.getRealPos(),worldPos,voxelPos,notifyTarget,oldEntity); } else { this.homogenous = true; } diff --git a/src/main/java/electrosphere/client/terrain/foliage/FoliageModel.java b/src/main/java/electrosphere/client/terrain/foliage/FoliageModel.java index ae92c21e..2a819a99 100644 --- a/src/main/java/electrosphere/client/terrain/foliage/FoliageModel.java +++ b/src/main/java/electrosphere/client/terrain/foliage/FoliageModel.java @@ -48,7 +48,7 @@ public class FoliageModel { /** * The interval to space along */ - static final int TARGET_FOLIAGE_SPACING = 50; + static final int TARGET_FOLIAGE_SPACING = 25; /** * The target number of foliage to place per cell @@ -58,12 +58,12 @@ public class FoliageModel { /** * The length of the ray to ground test with */ - static final float RAY_LENGTH = 1.0f; + static final float RAY_LENGTH = 2.5f; /** * The height above the chunk to start from when sampling downwards */ - static final float SAMPLE_START_HEIGHT = 0.5f; + static final float SAMPLE_START_HEIGHT = 1.0f; /** * The ID of the air voxel @@ -86,6 +86,11 @@ public class FoliageModel { */ static final int SINGLE_FOLIAGE_DATA_SIZE_BYTES = 3 * 4 + 2 * 4; + /** + * Offset to sample by + */ + static final float SAMPLE_OFFSET = 0.499f; + /** * Vertex shader path */ @@ -137,19 +142,41 @@ public class FoliageModel { } FloatBuffer floatBufferView = buffer.asFloatBuffer(); int drawCount = 0; + Vector3i currWorldPos = new Vector3i(); + Vector3i currVoxelPos = new Vector3i(voxelPos); + Vector3d currRealPos = new Vector3d(); for(int x = 0; x < scale; x++){ - for(int y = 0; y < scale; y++){ - for(int z = 0; z < scale; z++){ - ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos,ChunkData.NO_STRIDE); - if(data == null){ + for(int z = 0; z < scale; z++){ + for(int y = 0; y < scale; y++){ + currVoxelPos.set(voxelPos).add(x,y,z); + currWorldPos.set(worldPos).add( + x / ServerTerrainChunk.CHUNK_DIMENSION, + y / ServerTerrainChunk.CHUNK_DIMENSION, + z / ServerTerrainChunk.CHUNK_DIMENSION + ); + currRealPos.set( + currVoxelPos.x + currWorldPos.x * ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET, + currVoxelPos.y + currWorldPos.y * ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET, + currVoxelPos.z + currWorldPos.z * ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET + ); + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(currWorldPos,ChunkData.NO_STRIDE); + List currentList = Globals.gameConfigCurrent.getVoxelData().getTypeFromId(data.getType(currVoxelPos)).getAmbientFoliage(); + if(currentList == null){ continue; } - drawCount = drawCount + FoliageModel.insertBlades( - realPos, voxelPos, + if(data.getType(currVoxelPos.x,currVoxelPos.y+1,currVoxelPos.z) != AIR_VOXEL_ID){ + continue; + } + int numGenerated = FoliageModel.insertBlades( + currWorldPos, currRealPos, currVoxelPos, scale, placementRandomizer, x, y, z, floatBufferView, data ); + drawCount = drawCount + numGenerated; + // if(numGenerated > 0){ + // break; + // } } } } @@ -187,144 +214,137 @@ public class FoliageModel { * @return the number of blades of grass added */ protected static int insertBlades( - Vector3d realPos, Vector3i voxelPos, + Vector3i worldPos, Vector3d realPos, Vector3i voxelPos, int scale, Random placementRandomizer, int vX, int vY, int vZ, FloatBuffer floatBufferView, ChunkData chunkData ){ int rVal = 0; - //get positions offset - Vector3d voxelRealPos = new Vector3d(realPos).add(vX,vY,vZ); - Vector3i currVoxelPos = new Vector3i(voxelPos).add(vX,vY,vZ); - - //check that the current voxel even supports foliage - boolean shouldGenerate = false; - List foliageTypesSupported = null; - if(chunkData != null && currVoxelPos.y + 1 < ServerTerrainChunk.CHUNK_DIMENSION){ - foliageTypesSupported = Globals.gameConfigCurrent.getVoxelData().getTypeFromId(chunkData.getType(currVoxelPos)).getAmbientFoliage(); - boolean airAbove = chunkData.getType(currVoxelPos.x,currVoxelPos.y+1,currVoxelPos.z) == AIR_VOXEL_ID; - if(foliageTypesSupported != null && airAbove){ - shouldGenerate = true; - } - } - if(shouldGenerate){ - //construct simple grid to place foliage on - Vector3d sample_00 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add(-0.5,SAMPLE_START_HEIGHT,-0.5), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_01 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add(-0.5,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_02 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add(-0.5,SAMPLE_START_HEIGHT, 0.5), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_10 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0,SAMPLE_START_HEIGHT,-0.5), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_11 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_12 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0,SAMPLE_START_HEIGHT, 0.5), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_20 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0.5,SAMPLE_START_HEIGHT,-0.5), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_21 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0.5,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); - Vector3d sample_22 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(voxelRealPos).add( 0.5,SAMPLE_START_HEIGHT, 0.5), new Vector3d(0,-1,0), RAY_LENGTH); - //get the heights of each sample - float height_11 = (float)(sample_11 != null ? sample_11.y : 0); - float height_00 = (float)(sample_00 != null ? sample_00.y : height_11); - float height_01 = (float)(sample_01 != null ? sample_01.y : height_11); - float height_02 = (float)(sample_02 != null ? sample_02.y : height_11); - float height_10 = (float)(sample_10 != null ? sample_10.y : height_11); - float height_12 = (float)(sample_12 != null ? sample_12.y : height_11); - float height_20 = (float)(sample_20 != null ? sample_20.y : height_11); - float height_21 = (float)(sample_21 != null ? sample_21.y : height_11); - float height_22 = (float)(sample_22 != null ? sample_22.y : height_11); - //each height is in real world coordinates that are absolute - //when rendering, there's already a y offset for the center of the field of grass (based on the model matrix) - //so when offseting the position of the blade of grass RELATIVE to the overall instance being drawn, need to subtract the real world coordinates of the overall instance - //in other words realPos SPECIFICALLY for the y dimension, for x and z you don't need to worry about it - - //if we don't find data for the center sample, can't place grass so don't create entity - if(sample_11 != null){ - //generate positions to place - for(int x = 0; x < TARGET_FOLIAGE_SPACING; x=x+scale){ - for(int z = 0; z < TARGET_FOLIAGE_SPACING; z=z+scale){ - //get position to place - double rand1 = placementRandomizer.nextDouble(); - double rand2 = placementRandomizer.nextDouble(); - double relativePositionOnGridX = x / (1.0 * TARGET_FOLIAGE_SPACING) + rand1 / TARGET_FOLIAGE_SPACING; - double relativePositionOnGridZ = z / (1.0 * TARGET_FOLIAGE_SPACING) + rand2 / TARGET_FOLIAGE_SPACING; - double offsetX = relativePositionOnGridX - 0.5; - double offsetZ = relativePositionOnGridZ - 0.5; - //determine quadrant we're placing in - double offsetY = 0; - boolean addBlade = false; - if(relativePositionOnGridX >=0.5){ - if(relativePositionOnGridZ >= 0.5){ - relativePositionOnGridX = relativePositionOnGridX - 0.5; - relativePositionOnGridZ = relativePositionOnGridZ - 0.5; - relativePositionOnGridX /= 0.5; - relativePositionOnGridZ /= 0.5; - // System.out.println(relativePositionOnGridX + " " + relativePositionOnGridZ); - //if we have heights for all four surrounding spots, interpolate for y value - if(sample_11 != null && sample_12 != null && sample_21 != null && sample_22 != null){ - offsetY = - height_11 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_12 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + - height_21 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_22 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); - addBlade = true; - } - } else { - relativePositionOnGridX = relativePositionOnGridX - 0.5; - relativePositionOnGridX /= 0.5; - relativePositionOnGridZ /= 0.5; - //if we have heights for all four surrounding spots, interpolate for y value - if(sample_10 != null && sample_11 != null && sample_20 != null && sample_21 != null){ - offsetY = - height_10 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_11 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + - height_20 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_21 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); - addBlade = true; - } + //construct simple grid to place foliage on + Vector3d sample_00 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add(-SAMPLE_OFFSET,SAMPLE_START_HEIGHT,-SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_01 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add(-SAMPLE_OFFSET,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_02 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add(-SAMPLE_OFFSET,SAMPLE_START_HEIGHT, SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_10 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( 0,SAMPLE_START_HEIGHT,-SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_11 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( 0,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_12 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( 0,SAMPLE_START_HEIGHT, SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_20 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( SAMPLE_OFFSET,SAMPLE_START_HEIGHT,-SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_21 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( SAMPLE_OFFSET,SAMPLE_START_HEIGHT, 0), new Vector3d(0,-1,0), RAY_LENGTH); + Vector3d sample_22 = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(realPos).add( SAMPLE_OFFSET,SAMPLE_START_HEIGHT, SAMPLE_OFFSET), new Vector3d(0,-1,0), RAY_LENGTH); + //get the heights of each sample + float height_11 = (float)(sample_11 != null ? sample_11.y : 0); + float height_00 = (float)(sample_00 != null ? sample_00.y : height_11); + float height_01 = (float)(sample_01 != null ? sample_01.y : height_11); + float height_02 = (float)(sample_02 != null ? sample_02.y : height_11); + float height_10 = (float)(sample_10 != null ? sample_10.y : height_11); + float height_12 = (float)(sample_12 != null ? sample_12.y : height_11); + float height_20 = (float)(sample_20 != null ? sample_20.y : height_11); + float height_21 = (float)(sample_21 != null ? sample_21.y : height_11); + float height_22 = (float)(sample_22 != null ? sample_22.y : height_11); + //each height is in real world coordinates that are absolute + //when rendering, there's already a y offset for the center of the field of grass (based on the model matrix) + //so when offseting the position of the blade of grass RELATIVE to the overall instance being drawn, need to subtract the real world coordinates of the overall instance + //in other words realPos SPECIFICALLY for the y dimension, for x and z you don't need to worry about it + + //if we don't find data for the center sample, can't place grass so don't create entity + if(sample_11 != null){ + //generate positions to place + for(int x = 0; x < TARGET_FOLIAGE_SPACING; x=x+scale){ + for(int z = 0; z < TARGET_FOLIAGE_SPACING; z=z+scale){ + //get position to place + double rand1 = placementRandomizer.nextDouble(); + double rand2 = placementRandomizer.nextDouble(); + double relativePositionOnGridX = x / (1.0 * TARGET_FOLIAGE_SPACING) + rand1 / TARGET_FOLIAGE_SPACING; + double relativePositionOnGridZ = z / (1.0 * TARGET_FOLIAGE_SPACING) + rand2 / TARGET_FOLIAGE_SPACING; + double offsetX = relativePositionOnGridX - 0.5; + double offsetZ = relativePositionOnGridZ - 0.5; + //determine quadrant we're placing in + double offsetY = 0; + boolean addBlade = false; + if(relativePositionOnGridX >=0.5){ + if(relativePositionOnGridZ >= 0.5){ + relativePositionOnGridX = relativePositionOnGridX - 0.5; + relativePositionOnGridZ = relativePositionOnGridZ - 0.5; + relativePositionOnGridX /= 0.5; + relativePositionOnGridZ /= 0.5; + // System.out.println(relativePositionOnGridX + " " + relativePositionOnGridZ); + //if we have heights for all four surrounding spots, interpolate for y value + if(sample_11 != null && sample_12 != null && sample_21 != null && sample_22 != null){ + offsetY = + height_11 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_12 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + + height_21 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_22 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); + addBlade = true; } } else { - if(relativePositionOnGridZ >= 0.5){ - relativePositionOnGridZ = relativePositionOnGridZ - 0.5; - relativePositionOnGridX /= 0.5; - relativePositionOnGridZ /= 0.5; - //if we have heights for all four surrounding spots, interpolate for y value - if(sample_01 != null && sample_02 != null && sample_11 != null && sample_12 != null){ - offsetY = - height_01 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_02 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + - height_11 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_12 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); - addBlade = true; - } - } else { - relativePositionOnGridX /= 0.5; - relativePositionOnGridZ /= 0.5; - //if we have heights for all four surrounding spots, interpolate for y value - if(sample_00 != null && sample_01 != null && sample_10 != null && sample_11 != null){ - offsetY = - height_00 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_01 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + - height_10 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + - height_11 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); - addBlade = true; - } + relativePositionOnGridX = relativePositionOnGridX - 0.5; + relativePositionOnGridX /= 0.5; + relativePositionOnGridZ /= 0.5; + //if we have heights for all four surrounding spots, interpolate for y value + if(sample_10 != null && sample_11 != null && sample_20 != null && sample_21 != null){ + offsetY = + height_10 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_11 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + + height_20 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_21 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); + addBlade = true; } } - if(addBlade){ - //convert y to relative to chunk - offsetY = offsetY - realPos.y; - double rotVar = placementRandomizer.nextDouble() * Math.PI * 2; - double rotVar2 = placementRandomizer.nextDouble(); - if(floatBufferView.limit() >= floatBufferView.position() + SINGLE_FOLIAGE_DATA_SIZE_BYTES / 4){ - floatBufferView.put((float)offsetX + vX); - floatBufferView.put((float)offsetY + vY); - floatBufferView.put((float)offsetZ + vZ); - floatBufferView.put((float)rotVar); - floatBufferView.put((float)rotVar2); - rVal++; + } else { + if(relativePositionOnGridZ >= 0.5){ + relativePositionOnGridZ = relativePositionOnGridZ - 0.5; + relativePositionOnGridX /= 0.5; + relativePositionOnGridZ /= 0.5; + //if we have heights for all four surrounding spots, interpolate for y value + if(sample_01 != null && sample_02 != null && sample_11 != null && sample_12 != null){ + offsetY = + height_01 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_02 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + + height_11 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_12 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); + addBlade = true; } + } else { + relativePositionOnGridX /= 0.5; + relativePositionOnGridZ /= 0.5; + //if we have heights for all four surrounding spots, interpolate for y value + if(sample_00 != null && sample_01 != null && sample_10 != null && sample_11 != null){ + offsetY = + height_00 * (1-relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_01 * (1-relativePositionOnGridX) * ( relativePositionOnGridZ) + + height_10 * ( relativePositionOnGridX) * (1-relativePositionOnGridZ) + + height_11 * ( relativePositionOnGridX) * ( relativePositionOnGridZ); + addBlade = true; + } + } + } + if(addBlade){ + // if(realPos.y == 20 && sample_11 != null){ + // System.out.println("asdf"); + // } + //convert y to relative to chunk + offsetY = offsetY - realPos.y; + double rotVar = placementRandomizer.nextDouble() * Math.PI * 2; + double rotVar2 = placementRandomizer.nextDouble(); + if(floatBufferView.limit() >= floatBufferView.position() + SINGLE_FOLIAGE_DATA_SIZE_BYTES / 4){ + floatBufferView.put((float)offsetX + vX); + floatBufferView.put((float)offsetY + vY); + floatBufferView.put((float)offsetZ + vZ); + floatBufferView.put((float)rotVar); + floatBufferView.put((float)rotVar2); + rVal++; } } } } } + // else { + // String message = "Failed to collide with a chunk that definitely should already exist!\n"; + // message = message + "sample pos: " + new Vector3d(realPos).add(0,SAMPLE_START_HEIGHT,0) + "\n"; + // message = message + "generated physics: " + Globals.clientDrawCellManager.hasGeneratedPhysics(worldPos.x, worldPos.y, worldPos.z) + "\n"; + // throw new Error(message); + // } return rVal; }