|
9 | 9 | package hellfirepvp.modularmachinery.client.util; |
10 | 10 |
|
11 | 11 | import hellfirepvp.modularmachinery.client.ClientScheduler; |
| 12 | +import hellfirepvp.modularmachinery.common.data.Config; |
12 | 13 | import hellfirepvp.modularmachinery.common.util.BlockArray; |
13 | 14 | import hellfirepvp.modularmachinery.common.util.BlockCompatHelper; |
14 | 15 | import hellfirepvp.modularmachinery.common.util.IBlockStateDescriptor; |
15 | 16 | import net.minecraft.block.state.IBlockState; |
16 | 17 | import net.minecraft.client.Minecraft; |
17 | 18 | import net.minecraft.client.gui.GuiScreen; |
18 | 19 | import net.minecraft.client.gui.ScaledResolution; |
19 | | -import net.minecraft.client.renderer.BlockRendererDispatcher; |
20 | | -import net.minecraft.client.renderer.BufferBuilder; |
21 | | -import net.minecraft.client.renderer.Tessellator; |
| 20 | +import net.minecraft.client.renderer.*; |
22 | 21 | import net.minecraft.client.renderer.texture.TextureMap; |
23 | 22 | import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; |
24 | 23 | import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; |
|
52 | 51 | * Date: 09.07.2017 / 20:16 |
53 | 52 | */ |
54 | 53 | public class BlockArrayRenderHelper { |
| 54 | + private static int hash = -1; |
| 55 | + private static int batchDList = -1; |
55 | 56 |
|
56 | 57 | private final BlockArray blocks; |
57 | 58 | private final WorldBlockArrayRenderAccess renderAccess; |
@@ -158,72 +159,141 @@ public void render3DGUI(double x, double y, float scaleMultiplier, float pTicks, |
158 | 159 |
|
159 | 160 | GL11.glScaled(-size * mul, -size * mul, -size * mul); |
160 | 161 |
|
161 | | - BlockRendererDispatcher brd = Minecraft.getMinecraft().getBlockRendererDispatcher(); |
162 | | - VertexFormat blockFormat = DefaultVertexFormats.BLOCK; |
163 | | - |
164 | 162 | renderAccess.respectRenderSlice = slice.isPresent(); |
165 | 163 | renderAccess.currentRenderSlice = slice.orElse(0); |
166 | 164 |
|
| 165 | + if (Config.enableStructurePreviewDisplayList) { |
| 166 | + if (batchDList == -1) { |
| 167 | + batchBlocks(slice, pTicks); |
| 168 | + hash = hashBlocks(); |
| 169 | + } else { |
| 170 | + int currentHash = hashBlocks(); |
| 171 | + if (hash != currentHash) { |
| 172 | + GLAllocation.deleteDisplayLists(batchDList); |
| 173 | + batchBlocks(slice, pTicks); |
| 174 | + hash = currentHash; |
| 175 | + } |
| 176 | + } |
| 177 | + GlStateManager.disableDepth(); |
| 178 | + GlStateManager.callList(batchDList); |
| 179 | + GlStateManager.enableDepth(); |
| 180 | + } else { |
| 181 | + batchBlocks(slice, pTicks); |
| 182 | + } |
| 183 | + |
| 184 | + renderAccess.respectRenderSlice = false; |
| 185 | + renderAccess.currentRenderSlice = 0; |
| 186 | + |
| 187 | + GL11.glPopMatrix(); |
| 188 | + GL11.glPopAttrib(); |
| 189 | + } |
| 190 | + |
| 191 | + private void batchBlocks(final Optional<Integer> slice, final float pTicks) { |
| 192 | + if (batchDList != -1) { |
| 193 | + GlStateManager.glDeleteLists(batchDList, 1); |
| 194 | + } |
| 195 | + if (Config.enableStructurePreviewDisplayList) { |
| 196 | + batchDList = GLAllocation.generateDisplayLists(1); |
| 197 | + GlStateManager.glNewList(batchDList, GL11.GL_COMPILE); |
| 198 | + } |
| 199 | + |
| 200 | + BlockRendererDispatcher brd = Minecraft.getMinecraft().getBlockRendererDispatcher(); |
| 201 | + VertexFormat blockFormat = DefaultVertexFormats.BLOCK; |
167 | 202 | Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); |
168 | 203 | Tessellator tes = Tessellator.getInstance(); |
169 | 204 | BufferBuilder vb = tes.getBuffer(); |
170 | 205 |
|
171 | 206 | vb.begin(GL11.GL_QUADS, blockFormat); |
172 | | - for (Map.Entry<BlockPos, BakedBlockData> data : renderAccess.blockRenderData.entrySet()) { |
173 | | - BlockPos offset = data.getKey(); |
174 | | - if (slice.isPresent()) { |
175 | | - if (slice.get() != offset.getY()) { |
176 | | - continue; |
177 | | - } |
178 | | - } |
179 | | - BakedBlockData renderData = data.getValue(); |
180 | | - SampleRenderState state = renderData.getSampleState(); |
181 | | - if (state.state.getBlock() != Blocks.AIR) { |
182 | | - TileEntityRenderData terd = state.renderData; |
183 | | - if (terd != null && terd.tileEntity != null) { |
184 | | - terd.tileEntity.setWorld(Minecraft.getMinecraft().world); |
185 | | - terd.tileEntity.setPos(offset); |
186 | | - } |
187 | | - try { |
188 | | - IBlockState actRenderState = state.state; |
189 | | - actRenderState = actRenderState.getBlock().getActualState(actRenderState, renderAccess, offset); |
190 | | - brd.renderBlock(actRenderState, offset, renderAccess, vb); |
191 | | - } catch (Exception exc) { |
192 | | - brd.getBlockModelRenderer().renderModel( |
193 | | - renderAccess, |
194 | | - brd.getBlockModelShapes().getModelManager().getMissingModel(), |
195 | | - state.state, |
196 | | - offset, |
197 | | - vb, true); |
198 | | - } |
199 | | - } |
200 | | - } |
| 207 | + //noinspection SimplifyOptionalCallChains |
| 208 | + renderAccess.blockRenderData.entrySet().stream() |
| 209 | + .filter(data -> !slice.isPresent() || slice.get() == data.getKey().getY()) |
| 210 | + .sorted(this::comparePos).forEach((data) -> { |
| 211 | + BlockPos offset = data.getKey(); |
| 212 | + BakedBlockData renderData = data.getValue(); |
| 213 | + SampleRenderState state = renderData.getSampleState(); |
| 214 | + if (state.state.getBlock() != Blocks.AIR) { |
| 215 | + TileEntityRenderData terd = state.renderData; |
| 216 | + if (terd != null && terd.tileEntity != null) { |
| 217 | + terd.tileEntity.setWorld(Minecraft.getMinecraft().world); |
| 218 | + terd.tileEntity.setPos(offset); |
| 219 | + } |
| 220 | + try { |
| 221 | + IBlockState actRenderState = state.state; |
| 222 | + actRenderState = actRenderState.getBlock().getActualState(actRenderState, renderAccess, offset); |
| 223 | + brd.renderBlock(actRenderState, offset, renderAccess, vb); |
| 224 | + } catch (Exception exc) { |
| 225 | + brd.getBlockModelRenderer().renderModel( |
| 226 | + renderAccess, |
| 227 | + brd.getBlockModelShapes().getModelManager().getMissingModel(), |
| 228 | + state.state, |
| 229 | + offset, |
| 230 | + vb, true); |
| 231 | + } |
| 232 | + } |
| 233 | + }); |
| 234 | + |
201 | 235 | tes.draw(); |
| 236 | + //noinspection SimplifyOptionalCallChains |
| 237 | + renderAccess.blockRenderData.entrySet().stream() |
| 238 | + .filter(data -> !slice.isPresent() || slice.get() == data.getKey().getY()) |
| 239 | + .sorted(this::comparePos) |
| 240 | + .forEach(data -> { |
| 241 | + BlockPos offset = data.getKey(); |
| 242 | + SampleRenderState state = data.getValue().getSampleState(); |
| 243 | + TileEntityRenderData terd = state.renderData; |
| 244 | + if (terd != null && terd.tileEntity != null && terd.renderer != null) { |
| 245 | + terd.tileEntity.setWorld(Minecraft.getMinecraft().world); |
| 246 | + terd.tileEntity.setPos(offset); |
| 247 | + try { |
| 248 | + terd.renderer.render(terd.tileEntity, offset.getX(), offset.getY(), offset.getZ(), pTicks, 0, 1F); |
| 249 | + } catch (Exception ignored) { |
| 250 | + } |
| 251 | + } |
| 252 | + }); |
| 253 | + |
| 254 | + if (Config.enableStructurePreviewDisplayList) { |
| 255 | + GlStateManager.glEndList(); |
| 256 | + } |
| 257 | + } |
202 | 258 |
|
203 | | - for (Map.Entry<BlockPos, BakedBlockData> data : renderAccess.blockRenderData.entrySet()) { |
204 | | - BlockPos offset = data.getKey(); |
205 | | - if (slice.isPresent()) { |
206 | | - if (slice.get() != offset.getY()) { |
207 | | - continue; |
208 | | - } |
| 259 | + private int hashBlocks() { |
| 260 | + int hash = 80238287; |
| 261 | + for (Map.Entry<BlockPos, BlockArray.BlockInformation> entry : blocks.getPattern().entrySet()) { |
| 262 | + if (Minecraft.getMinecraft().world != null && entry.getValue().matches(Minecraft.getMinecraft().world, entry.getKey(), false)) { |
| 263 | + continue; |
209 | 264 | } |
210 | | - SampleRenderState state = data.getValue().getSampleState(); |
211 | | - TileEntityRenderData terd = state.renderData; |
212 | | - if (terd != null && terd.tileEntity != null && terd.renderer != null) { |
213 | | - terd.tileEntity.setWorld(Minecraft.getMinecraft().world); |
214 | | - terd.tileEntity.setPos(offset); |
215 | | - try { |
216 | | - terd.renderer.render(terd.tileEntity, offset.getX(), offset.getY(), offset.getZ(), pTicks, 0, 1F); |
217 | | - } catch (Exception ignored) { |
218 | | - } |
| 265 | + int layer = entry.getKey().getY(); |
| 266 | + if (renderAccess.currentRenderSlice != layer) { |
| 267 | + continue; |
219 | 268 | } |
| 269 | + hash = (hash << 4) ^ (hash >> 28) ^ (entry.getKey().getX() * 5449 % 130651); |
| 270 | + hash = (hash << 4) ^ (hash >> 28) ^ (entry.getKey().getY() * 5449 % 130651); |
| 271 | + hash = (hash << 4) ^ (hash >> 28) ^ (entry.getKey().getZ() * 5449 % 130651); |
| 272 | + hash = (hash << 4) ^ (hash >> 28) ^ (entry.getValue().getSampleState(sampleSnap).hashCode() * 5449 % 130651); |
220 | 273 | } |
| 274 | + return hash % 75327403; |
| 275 | + } |
221 | 276 |
|
222 | | - renderAccess.respectRenderSlice = false; |
223 | | - renderAccess.currentRenderSlice = 0; |
224 | | - |
225 | | - GL11.glPopMatrix(); |
226 | | - GL11.glPopAttrib(); |
| 277 | + private int comparePos(Map.Entry<BlockPos, BakedBlockData> o1, Map.Entry<BlockPos, BakedBlockData> o2) { |
| 278 | + int yCompare; |
| 279 | + if (rotY < 0 && rotX >= 0 && rotX <= 90) { |
| 280 | + yCompare = Integer.compare(o2.getKey().getY(), o1.getKey().getY()); |
| 281 | + } else { |
| 282 | + yCompare = Integer.compare(o1.getKey().getY(), o2.getKey().getY()); |
| 283 | + } |
| 284 | + if (yCompare != 0) { |
| 285 | + return yCompare; |
| 286 | + } |
| 287 | + int xCompare; |
| 288 | + if (rotX < 0 && rotY < 0) { |
| 289 | + xCompare = Integer.compare(o1.getKey().getX(), o2.getKey().getX()); |
| 290 | + } else { |
| 291 | + xCompare = Integer.compare(o2.getKey().getX(), o1.getKey().getX()); |
| 292 | + } |
| 293 | + if (xCompare != 0) { |
| 294 | + return xCompare; |
| 295 | + } |
| 296 | + return Integer.compare(o1.getKey().getZ(), o2.getKey().getZ()); |
227 | 297 | } |
228 | 298 |
|
229 | 299 | static class BakedBlockData { |
|
0 commit comments