unindent RenberableBoxGroup
This commit is contained in:
+369
-369
@@ -35,375 +35,375 @@ import java.util.stream.Stream;
|
||||
public class RenderableBoxGroup
|
||||
extends AbstractList<DhApiRenderableBox>
|
||||
implements IDhApiRenderableBoxGroup, Closeable
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
|
||||
|
||||
|
||||
|
||||
public final long id;
|
||||
|
||||
public final String resourceLocationNamespace;
|
||||
public final String resourceLocationPath;
|
||||
|
||||
/** If false the boxes will be positioned relative to the level's origin */
|
||||
public final boolean positionBoxesRelativeToGroupOrigin;
|
||||
|
||||
private final List<DhApiRenderableBox> boxList;
|
||||
/** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */
|
||||
private final List<DhApiRenderableBox> uploadBoxList;
|
||||
private final DhApiVec3d originBlockPos;
|
||||
|
||||
|
||||
public boolean active = true;
|
||||
public boolean ssaoEnabled = true;
|
||||
private boolean vertexDataDirty = true;
|
||||
|
||||
public byte skyLight = LodUtil.MAX_MC_LIGHT;
|
||||
public byte blockLight = LodUtil.MIN_MC_LIGHT;
|
||||
public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded();
|
||||
|
||||
@Nullable
|
||||
public Consumer<DhApiRenderParam> beforeRenderFunc;
|
||||
public Consumer<DhApiRenderParam> afterRenderFunc;
|
||||
|
||||
// instance data
|
||||
public int instanceColorVbo = 0;
|
||||
public int instanceMaterialVbo = 0;
|
||||
public int instanceScaleVbo = 0;
|
||||
public int instanceChunkPosVbo = 0;
|
||||
public int instanceSubChunkPosVbo = 0;
|
||||
|
||||
public int uploadedBoxCount = -1;
|
||||
|
||||
|
||||
//=================//
|
||||
// getters/setters //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public long getId() { return this.id; }
|
||||
|
||||
@Override
|
||||
public String getResourceLocationNamespace() { return this.resourceLocationNamespace; }
|
||||
@Override
|
||||
public String getResourceLocationPath() { return this.resourceLocationPath; }
|
||||
|
||||
@Override
|
||||
public void setOriginBlockPos(DhApiVec3d pos)
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
|
||||
|
||||
|
||||
|
||||
public final long id;
|
||||
|
||||
public final String resourceLocationNamespace;
|
||||
public final String resourceLocationPath;
|
||||
|
||||
/** If false the boxes will be positioned relative to the level's origin */
|
||||
public final boolean positionBoxesRelativeToGroupOrigin;
|
||||
|
||||
private final List<DhApiRenderableBox> boxList;
|
||||
/** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */
|
||||
private final List<DhApiRenderableBox> uploadBoxList;
|
||||
private final DhApiVec3d originBlockPos;
|
||||
|
||||
|
||||
public boolean active = true;
|
||||
public boolean ssaoEnabled = true;
|
||||
private boolean vertexDataDirty = true;
|
||||
|
||||
public byte skyLight = LodUtil.MAX_MC_LIGHT;
|
||||
public byte blockLight = LodUtil.MIN_MC_LIGHT;
|
||||
public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded();
|
||||
|
||||
@Nullable
|
||||
public Consumer<DhApiRenderParam> beforeRenderFunc;
|
||||
public Consumer<DhApiRenderParam> afterRenderFunc;
|
||||
|
||||
// instance data
|
||||
public int instanceColorVbo = 0;
|
||||
public int instanceMaterialVbo = 0;
|
||||
public int instanceScaleVbo = 0;
|
||||
public int instanceChunkPosVbo = 0;
|
||||
public int instanceSubChunkPosVbo = 0;
|
||||
|
||||
public int uploadedBoxCount = -1;
|
||||
|
||||
|
||||
//=================//
|
||||
// getters/setters //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public long getId() { return this.id; }
|
||||
|
||||
@Override
|
||||
public String getResourceLocationNamespace() { return this.resourceLocationNamespace; }
|
||||
@Override
|
||||
public String getResourceLocationPath() { return this.resourceLocationPath; }
|
||||
|
||||
@Override
|
||||
public void setOriginBlockPos(DhApiVec3d pos)
|
||||
{
|
||||
this.originBlockPos.x = pos.x;
|
||||
this.originBlockPos.y = pos.y;
|
||||
this.originBlockPos.z = pos.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
|
||||
|
||||
|
||||
@Override
|
||||
public void setSkyLight(int skyLight)
|
||||
{
|
||||
if (skyLight < LodUtil.MIN_MC_LIGHT
|
||||
|| skyLight > LodUtil.MAX_MC_LIGHT)
|
||||
{
|
||||
throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
|
||||
}
|
||||
this.skyLight = (byte)skyLight;
|
||||
}
|
||||
@Override
|
||||
public int getSkyLight() { return this.skyLight; }
|
||||
|
||||
@Override
|
||||
public void setBlockLight(int blockLight)
|
||||
{
|
||||
if (blockLight < LodUtil.MIN_MC_LIGHT
|
||||
|| blockLight > LodUtil.MAX_MC_LIGHT)
|
||||
{
|
||||
throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
|
||||
}
|
||||
this.blockLight = (byte)blockLight;
|
||||
}
|
||||
@Override
|
||||
public int getBlockLight() { return this.blockLight; }
|
||||
|
||||
@Override
|
||||
public void setPreRenderFunc(Consumer<DhApiRenderParam> func) { this.beforeRenderFunc = func; }
|
||||
|
||||
@Override
|
||||
public void setPostRenderFunc(Consumer<DhApiRenderParam> func) { this.afterRenderFunc = func; }
|
||||
|
||||
@Override
|
||||
public void setActive(boolean active) { this.active = active; }
|
||||
@Override
|
||||
public boolean isActive() { return this.active; }
|
||||
|
||||
@Override
|
||||
public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; }
|
||||
@Override
|
||||
public boolean isSsaoEnabled() { return this.ssaoEnabled; }
|
||||
|
||||
@Override
|
||||
public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; }
|
||||
@Override
|
||||
public DhApiRenderableBoxGroupShading getShading() { return this.shading; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public RenderableBoxGroup(
|
||||
String resourceLocation,
|
||||
DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList,
|
||||
boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException
|
||||
{
|
||||
String[] splitResourceLocation = resourceLocation.split(":");
|
||||
if (splitResourceLocation.length != 2)
|
||||
{
|
||||
throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons.");
|
||||
}
|
||||
|
||||
this.resourceLocationNamespace = splitResourceLocation[0];
|
||||
this.resourceLocationPath = splitResourceLocation[1];
|
||||
|
||||
this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
|
||||
this.boxList = Collections.synchronizedList(new ArrayList<>(boxList));
|
||||
this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList));
|
||||
|
||||
this.originBlockPos = originBlockPos;
|
||||
this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// render building //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void triggerBoxChange() { this.vertexDataDirty = true; }
|
||||
|
||||
/** Does nothing if the vertex data is already up-to-date */
|
||||
public void updateVertexAttributeData()
|
||||
{
|
||||
if (!this.vertexDataDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.vertexDataDirty = false;
|
||||
|
||||
if (this.instanceChunkPosVbo == 0)
|
||||
{
|
||||
this.instanceChunkPosVbo = GLMC.glGenBuffers();
|
||||
this.instanceSubChunkPosVbo = GLMC.glGenBuffers();
|
||||
this.instanceScaleVbo = GLMC.glGenBuffers();
|
||||
this.instanceColorVbo = GLMC.glGenBuffers();
|
||||
this.instanceMaterialVbo = GLMC.glGenBuffers();
|
||||
}
|
||||
|
||||
// copy over the box list so we can upload without concurrent modification issues
|
||||
this.uploadBoxList.clear();
|
||||
synchronized (this.uploadBoxList)
|
||||
{
|
||||
this.uploadBoxList.addAll(this.boxList);
|
||||
}
|
||||
|
||||
|
||||
int boxCount = this.uploadBoxList.size();
|
||||
this.uploadedBoxCount = boxCount;
|
||||
|
||||
|
||||
|
||||
// transformation / scaling //
|
||||
int[] chunkPosData = RenderBoxArrayCache.getCachedIntArray(boxCount * 3, 0);
|
||||
float[] subChunkPosData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 1);
|
||||
float[] scalingData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 2);
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = this.uploadBoxList.get(i);
|
||||
|
||||
int dataIndex = i * 3;
|
||||
|
||||
chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x);
|
||||
chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y);
|
||||
chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x);
|
||||
subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y);
|
||||
subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x);
|
||||
scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y);
|
||||
scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// colors/materials //
|
||||
float[] colorData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 4, 3);
|
||||
int[] materialData = RenderBoxArrayCache.getCachedIntArray(boxCount, 4);
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = this.uploadBoxList.get(i);
|
||||
Color color = box.color;
|
||||
int colorIndex = i * 4;
|
||||
colorData[colorIndex] = color.getRed() / 255.0f;
|
||||
colorData[colorIndex + 1] = color.getGreen() / 255.0f;
|
||||
colorData[colorIndex + 2] = color.getBlue() / 255.0f;
|
||||
colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
|
||||
|
||||
materialData[i] = box.material;
|
||||
}
|
||||
|
||||
|
||||
// Upload transformation matrices
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload colors
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload materials
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceMaterialVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, materialData, GL32.GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// render events //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
/**
|
||||
* This is called before every frame, even if {@link this#isActive()} returns false. <br>
|
||||
* {@link this#isActive()} can be changed at this point before the object is rendered to the frame.
|
||||
*/
|
||||
public void preRender(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
if (this.beforeRenderFunc != null)
|
||||
{
|
||||
this.beforeRenderFunc.accept(renderEventParam);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called after rendering is completed. <br>
|
||||
* Can be used to handle any necessary cleanup.
|
||||
*/
|
||||
public void postRender(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
if (this.afterRenderFunc != null)
|
||||
{
|
||||
this.afterRenderFunc.accept(renderEventParam);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// List Overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
|
||||
@Override
|
||||
public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
|
||||
@Override
|
||||
public int size() { return this.boxList.size(); }
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
|
||||
@Override
|
||||
public boolean remove(Object obj) { return this.boxList.remove(obj); }
|
||||
@Override
|
||||
public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); }
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<DhApiRenderableBox> operator) { this.boxList.replaceAll(operator); }
|
||||
@Override
|
||||
public void sort(Comparator<? super DhApiRenderableBox> comparator) { this.boxList.sort(comparator); }
|
||||
@Override
|
||||
public void forEach(Consumer<? super DhApiRenderableBox> action) { this.boxList.forEach(action); }
|
||||
@Override
|
||||
public Spliterator<DhApiRenderableBox> spliterator() { return this.boxList.spliterator(); }
|
||||
@Override
|
||||
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
|
||||
@Override
|
||||
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
|
||||
@Override
|
||||
public void clear() { this.boxList.clear(); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; }
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
if (this.instanceChunkPosVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceChunkPosVbo);
|
||||
this.instanceChunkPosVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceSubChunkPosVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceSubChunkPosVbo);
|
||||
this.instanceSubChunkPosVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceScaleVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceScaleVbo);
|
||||
this.instanceScaleVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceColorVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceColorVbo);
|
||||
this.instanceColorVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceMaterialVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceMaterialVbo);
|
||||
this.instanceMaterialVbo = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
this.originBlockPos.x = pos.x;
|
||||
this.originBlockPos.y = pos.y;
|
||||
this.originBlockPos.z = pos.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
|
||||
|
||||
|
||||
@Override
|
||||
public void setSkyLight(int skyLight)
|
||||
{
|
||||
if (skyLight < LodUtil.MIN_MC_LIGHT
|
||||
|| skyLight > LodUtil.MAX_MC_LIGHT)
|
||||
{
|
||||
throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
|
||||
}
|
||||
this.skyLight = (byte)skyLight;
|
||||
}
|
||||
@Override
|
||||
public int getSkyLight() { return this.skyLight; }
|
||||
|
||||
@Override
|
||||
public void setBlockLight(int blockLight)
|
||||
{
|
||||
if (blockLight < LodUtil.MIN_MC_LIGHT
|
||||
|| blockLight > LodUtil.MAX_MC_LIGHT)
|
||||
{
|
||||
throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
|
||||
}
|
||||
this.blockLight = (byte)blockLight;
|
||||
}
|
||||
@Override
|
||||
public int getBlockLight() { return this.blockLight; }
|
||||
|
||||
@Override
|
||||
public void setPreRenderFunc(Consumer<DhApiRenderParam> func) { this.beforeRenderFunc = func; }
|
||||
|
||||
@Override
|
||||
public void setPostRenderFunc(Consumer<DhApiRenderParam> func) { this.afterRenderFunc = func; }
|
||||
|
||||
@Override
|
||||
public void setActive(boolean active) { this.active = active; }
|
||||
@Override
|
||||
public boolean isActive() { return this.active; }
|
||||
|
||||
@Override
|
||||
public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; }
|
||||
@Override
|
||||
public boolean isSsaoEnabled() { return this.ssaoEnabled; }
|
||||
|
||||
@Override
|
||||
public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; }
|
||||
@Override
|
||||
public DhApiRenderableBoxGroupShading getShading() { return this.shading; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public RenderableBoxGroup(
|
||||
String resourceLocation,
|
||||
DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList,
|
||||
boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException
|
||||
{
|
||||
String[] splitResourceLocation = resourceLocation.split(":");
|
||||
if (splitResourceLocation.length != 2)
|
||||
{
|
||||
throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons.");
|
||||
}
|
||||
|
||||
this.resourceLocationNamespace = splitResourceLocation[0];
|
||||
this.resourceLocationPath = splitResourceLocation[1];
|
||||
|
||||
this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
|
||||
this.boxList = Collections.synchronizedList(new ArrayList<>(boxList));
|
||||
this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList));
|
||||
|
||||
this.originBlockPos = originBlockPos;
|
||||
this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// render building //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void triggerBoxChange() { this.vertexDataDirty = true; }
|
||||
|
||||
/** Does nothing if the vertex data is already up-to-date */
|
||||
public void updateVertexAttributeData()
|
||||
{
|
||||
if (!this.vertexDataDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.vertexDataDirty = false;
|
||||
|
||||
if (this.instanceChunkPosVbo == 0)
|
||||
{
|
||||
this.instanceChunkPosVbo = GLMC.glGenBuffers();
|
||||
this.instanceSubChunkPosVbo = GLMC.glGenBuffers();
|
||||
this.instanceScaleVbo = GLMC.glGenBuffers();
|
||||
this.instanceColorVbo = GLMC.glGenBuffers();
|
||||
this.instanceMaterialVbo = GLMC.glGenBuffers();
|
||||
}
|
||||
|
||||
// copy over the box list so we can upload without concurrent modification issues
|
||||
this.uploadBoxList.clear();
|
||||
synchronized (this.uploadBoxList)
|
||||
{
|
||||
this.uploadBoxList.addAll(this.boxList);
|
||||
}
|
||||
|
||||
|
||||
int boxCount = this.uploadBoxList.size();
|
||||
this.uploadedBoxCount = boxCount;
|
||||
|
||||
|
||||
|
||||
// transformation / scaling //
|
||||
int[] chunkPosData = RenderBoxArrayCache.getCachedIntArray(boxCount * 3, 0);
|
||||
float[] subChunkPosData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 1);
|
||||
float[] scalingData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 2);
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = this.uploadBoxList.get(i);
|
||||
|
||||
int dataIndex = i * 3;
|
||||
|
||||
chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x);
|
||||
chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y);
|
||||
chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x);
|
||||
subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y);
|
||||
subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x);
|
||||
scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y);
|
||||
scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// colors/materials //
|
||||
float[] colorData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 4, 3);
|
||||
int[] materialData = RenderBoxArrayCache.getCachedIntArray(boxCount, 4);
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = this.uploadBoxList.get(i);
|
||||
Color color = box.color;
|
||||
int colorIndex = i * 4;
|
||||
colorData[colorIndex] = color.getRed() / 255.0f;
|
||||
colorData[colorIndex + 1] = color.getGreen() / 255.0f;
|
||||
colorData[colorIndex + 2] = color.getBlue() / 255.0f;
|
||||
colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
|
||||
|
||||
materialData[i] = box.material;
|
||||
}
|
||||
|
||||
|
||||
// Upload transformation matrices
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload colors
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload materials
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceMaterialVbo);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, materialData, GL32.GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// render events //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
/**
|
||||
* This is called before every frame, even if {@link this#isActive()} returns false. <br>
|
||||
* {@link this#isActive()} can be changed at this point before the object is rendered to the frame.
|
||||
*/
|
||||
public void preRender(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
if (this.beforeRenderFunc != null)
|
||||
{
|
||||
this.beforeRenderFunc.accept(renderEventParam);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called after rendering is completed. <br>
|
||||
* Can be used to handle any necessary cleanup.
|
||||
*/
|
||||
public void postRender(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
if (this.afterRenderFunc != null)
|
||||
{
|
||||
this.afterRenderFunc.accept(renderEventParam);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// List Overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
|
||||
@Override
|
||||
public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
|
||||
@Override
|
||||
public int size() { return this.boxList.size(); }
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
|
||||
@Override
|
||||
public boolean remove(Object obj) { return this.boxList.remove(obj); }
|
||||
@Override
|
||||
public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); }
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<DhApiRenderableBox> operator) { this.boxList.replaceAll(operator); }
|
||||
@Override
|
||||
public void sort(Comparator<? super DhApiRenderableBox> comparator) { this.boxList.sort(comparator); }
|
||||
@Override
|
||||
public void forEach(Consumer<? super DhApiRenderableBox> action) { this.boxList.forEach(action); }
|
||||
@Override
|
||||
public Spliterator<DhApiRenderableBox> spliterator() { return this.boxList.spliterator(); }
|
||||
@Override
|
||||
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
|
||||
@Override
|
||||
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
|
||||
@Override
|
||||
public void clear() { this.boxList.clear(); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; }
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
if (this.instanceChunkPosVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceChunkPosVbo);
|
||||
this.instanceChunkPosVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceSubChunkPosVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceSubChunkPosVbo);
|
||||
this.instanceSubChunkPosVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceScaleVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceScaleVbo);
|
||||
this.instanceScaleVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceColorVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceColorVbo);
|
||||
this.instanceColorVbo = 0;
|
||||
}
|
||||
|
||||
if (this.instanceMaterialVbo != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(this.instanceMaterialVbo);
|
||||
this.instanceMaterialVbo = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user