Hastily added pine trees and hazel bushes
- Added ShapePrototype wrapper for ShapePart batch creation - Added pine trees and hazel bushes - Leaves with custom block models - Improved tree generator
This commit is contained in:
		@@ -0,0 +1,248 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Progressia
 | 
				
			||||||
 | 
					 * Copyright (C)  2020-2021  Wind Corporation and contributors
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package ru.windcorp.progressia.client.graphics.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.nio.ShortBuffer;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import glm.mat._3.Mat3;
 | 
				
			||||||
 | 
					import glm.mat._4.Mat4;
 | 
				
			||||||
 | 
					import glm.vec._2.Vec2;
 | 
				
			||||||
 | 
					import glm.vec._3.Vec3;
 | 
				
			||||||
 | 
					import glm.vec._4.Vec4;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.Colors;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram.VertexBuilder;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.texture.Texture;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram.WRPVertexBuilder;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.common.util.StashingStack;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.common.util.VectorUtil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ShapePrototype {
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private final ShapeRenderProgram program;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private Texture texture;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private final Vec3[] positions;
 | 
				
			||||||
 | 
						private final Vec4[] colorMultipliers;
 | 
				
			||||||
 | 
						private final Vec2[] textureCoords;
 | 
				
			||||||
 | 
						private final Vec3[] forcedNormals;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private ShortBuffer indices;
 | 
				
			||||||
 | 
						private ShortBuffer flippedIndices = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected static final int TRANSFORM_STACK_SIZE = 64;
 | 
				
			||||||
 | 
						private final StashingStack<Mat4> transformStack = new StashingStack<>(
 | 
				
			||||||
 | 
							TRANSFORM_STACK_SIZE,
 | 
				
			||||||
 | 
							Mat4::new
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype(
 | 
				
			||||||
 | 
							ShapeRenderProgram program,
 | 
				
			||||||
 | 
							Texture texture,
 | 
				
			||||||
 | 
							Vec3[] positions,
 | 
				
			||||||
 | 
							Vec4[] colorMultipliers,
 | 
				
			||||||
 | 
							Vec2[] textureCoords,
 | 
				
			||||||
 | 
							Vec3[] forcedNormals,
 | 
				
			||||||
 | 
							ShortBuffer indices
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
 | 
							this.program = Objects.requireNonNull(program, "program");
 | 
				
			||||||
 | 
							this.texture = texture;
 | 
				
			||||||
 | 
							this.indices = Objects.requireNonNull(indices, "indices");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Objects.requireNonNull(positions, "positions");
 | 
				
			||||||
 | 
							Objects.requireNonNull(colorMultipliers, "colorMultipliers");
 | 
				
			||||||
 | 
							Objects.requireNonNull(textureCoords, "textureCoords");
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (forcedNormals != null && !(program instanceof WorldRenderProgram)) {
 | 
				
			||||||
 | 
								throw new IllegalArgumentException("Cannot force normals on non-WorldRenderPrograms cuz javahorse stupiddd");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (forcedNormals == null) {
 | 
				
			||||||
 | 
								forcedNormals = new Vec3[positions.length];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							this.positions = positions;
 | 
				
			||||||
 | 
							this.colorMultipliers = colorMultipliers;
 | 
				
			||||||
 | 
							this.textureCoords = textureCoords;
 | 
				
			||||||
 | 
							this.forcedNormals = forcedNormals;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (positions.length != colorMultipliers.length) {
 | 
				
			||||||
 | 
								throw new IllegalArgumentException("positions.length (" + positions.length + ") != colorMultipliers.length (" + colorMultipliers + ")");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (positions.length != textureCoords.length) {
 | 
				
			||||||
 | 
								throw new IllegalArgumentException("positions.length (" + positions.length + ") != textureCoords.length (" + textureCoords + ")");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (positions.length != forcedNormals.length) {
 | 
				
			||||||
 | 
								throw new IllegalArgumentException("positions.length (" + positions.length + ") != forcedNormals.length (" + forcedNormals + ")");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							transformStack.push().identity();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePart build() {
 | 
				
			||||||
 | 
							VertexBuilder builder = program.getVertexBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Vec3 transformedPosition = new Vec3();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (int i = 0; i < positions.length; ++i) {
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								transformedPosition.set(positions[i]);
 | 
				
			||||||
 | 
								if (transformStack.getSize() > 1) {
 | 
				
			||||||
 | 
									VectorUtil.applyMat4(transformedPosition, transformStack.getHead());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								if (forcedNormals[i] != null && builder instanceof WRPVertexBuilder) {
 | 
				
			||||||
 | 
									((WRPVertexBuilder) builder).addVertex(
 | 
				
			||||||
 | 
										transformedPosition, colorMultipliers[i], textureCoords[i], forcedNormals[i]
 | 
				
			||||||
 | 
									);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									builder.addVertex(transformedPosition, colorMultipliers[i], textureCoords[i]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return new ShapePart(texture, builder.assemble(), indices);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype apply(Mat4 transform) {
 | 
				
			||||||
 | 
							for (Vec3 vector : positions) {
 | 
				
			||||||
 | 
								VectorUtil.applyMat4(vector, transform);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype apply(Mat3 transform) {
 | 
				
			||||||
 | 
							for (Vec3 vector : positions) {
 | 
				
			||||||
 | 
								transform.mul(vector);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public Mat4 push() {
 | 
				
			||||||
 | 
							Mat4 previous = transformStack.getHead();
 | 
				
			||||||
 | 
							return transformStack.push().set(previous);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype pop() {
 | 
				
			||||||
 | 
							transformStack.pop();
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype setTexture(Texture texture) {
 | 
				
			||||||
 | 
							this.texture = texture;
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype deleteTexture() {
 | 
				
			||||||
 | 
							this.texture = null;
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype resetColorMultiplier() {
 | 
				
			||||||
 | 
							for (Vec4 color : colorMultipliers) {
 | 
				
			||||||
 | 
								color.set(Colors.WHITE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype addColorMultiplier(Vec4 color) {
 | 
				
			||||||
 | 
							for (Vec4 c : colorMultipliers) {
 | 
				
			||||||
 | 
								c.mul(color);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype flip() {
 | 
				
			||||||
 | 
							ShortBuffer tmp = indices;
 | 
				
			||||||
 | 
							indices = flippedIndices;
 | 
				
			||||||
 | 
							flippedIndices = tmp;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (indices == null) {
 | 
				
			||||||
 | 
								int length = flippedIndices.limit();
 | 
				
			||||||
 | 
								indices = ShortBuffer.allocate(length);
 | 
				
			||||||
 | 
								for (int i = 0; i < length; ++i) {
 | 
				
			||||||
 | 
									indices.put(i, flippedIndices.get(length - i - 1));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public ShapePrototype makeDoubleSided() {
 | 
				
			||||||
 | 
							int length = indices.limit();
 | 
				
			||||||
 | 
							ShortBuffer newIndices = ShortBuffer.allocate(length * 2);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (int i = 0; i < length; ++i) {
 | 
				
			||||||
 | 
								newIndices.put(i, indices.get(i));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for (int i = 0; i < length; ++i) {
 | 
				
			||||||
 | 
								newIndices.put(i + length, indices.get(length - i - 1));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							indices = flippedIndices = newIndices;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static ShapePrototype unitSquare(Texture texture, Vec4 color, ShapeRenderProgram program) {
 | 
				
			||||||
 | 
							return new ShapePrototype(
 | 
				
			||||||
 | 
								program,
 | 
				
			||||||
 | 
								texture,
 | 
				
			||||||
 | 
								new Vec3[] {
 | 
				
			||||||
 | 
									new Vec3(0, 0, 0),
 | 
				
			||||||
 | 
									new Vec3(0, 1, 0),
 | 
				
			||||||
 | 
									new Vec3(1, 0, 0),
 | 
				
			||||||
 | 
									new Vec3(1, 1, 0)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								new Vec4[] {
 | 
				
			||||||
 | 
									new Vec4(color),
 | 
				
			||||||
 | 
									new Vec4(color),
 | 
				
			||||||
 | 
									new Vec4(color),
 | 
				
			||||||
 | 
									new Vec4(color)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								new Vec2[] {
 | 
				
			||||||
 | 
									new Vec2(0, 0),
 | 
				
			||||||
 | 
									new Vec2(0, 1),
 | 
				
			||||||
 | 
									new Vec2(1, 0),
 | 
				
			||||||
 | 
									new Vec2(1, 1)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								null,
 | 
				
			||||||
 | 
								ShortBuffer.wrap(new short[] {3, 1, 0, 2, 3, 0})
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static ShapePrototype unitSquare(Texture texture, Vec4 color) {
 | 
				
			||||||
 | 
							return unitSquare(texture, color, WorldRenderProgram.getDefault());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static ShapePrototype unitSquare(Texture texture) {
 | 
				
			||||||
 | 
							return unitSquare(texture, Colors.WHITE, WorldRenderProgram.getDefault());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static ShapePrototype unitSquare(Vec4 color) {
 | 
				
			||||||
 | 
							return unitSquare(null, color, WorldRenderProgram.getDefault());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static ShapePrototype unitSquare() {
 | 
				
			||||||
 | 
							return unitSquare(null, Colors.WHITE, WorldRenderProgram.getDefault());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -65,6 +65,8 @@ import ru.windcorp.progressia.server.world.tile.*;
 | 
				
			|||||||
import ru.windcorp.progressia.test.Flowers.FlowerVariant;
 | 
					import ru.windcorp.progressia.test.Flowers.FlowerVariant;
 | 
				
			||||||
import ru.windcorp.progressia.test.Rocks.RockType;
 | 
					import ru.windcorp.progressia.test.Rocks.RockType;
 | 
				
			||||||
import ru.windcorp.progressia.test.gen.TestGravityModel;
 | 
					import ru.windcorp.progressia.test.gen.TestGravityModel;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.test.trees.BlockRenderLeavesHazel;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.test.trees.BlockRenderLeavesPine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TestContent {
 | 
					public class TestContent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,7 +133,7 @@ public class TestContent {
 | 
				
			|||||||
		register(new BlockLogic("Test:Log"));
 | 
							register(new BlockLogic("Test:Log"));
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		register(new BlockData("Test:TemporaryLeaves"));
 | 
							register(new BlockData("Test:TemporaryLeaves"));
 | 
				
			||||||
		register(new BlockRenderTransparentCube("Test:TemporaryLeaves", getBlockTexture("TemporaryLeaves")));
 | 
							register(new BlockRenderLeavesHazel("Test:TemporaryLeaves", getBlockTexture("LeavesHazel")));
 | 
				
			||||||
		// Sic, using Glass logic for leaves because  Test
 | 
							// Sic, using Glass logic for leaves because  Test
 | 
				
			||||||
		register(new TestBlockLogicGlass("Test:TemporaryLeaves")); 
 | 
							register(new TestBlockLogicGlass("Test:TemporaryLeaves")); 
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
@@ -143,6 +145,11 @@ public class TestContent {
 | 
				
			|||||||
		register(new TestBlockRenderTux("Test:Tux"));
 | 
							register(new TestBlockRenderTux("Test:Tux"));
 | 
				
			||||||
		register(new BlockLogic("Test:Tux"));
 | 
							register(new BlockLogic("Test:Tux"));
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							register(new BlockData("Test:LeavesPine"));
 | 
				
			||||||
 | 
							register(new BlockRenderLeavesPine("Test:LeavesPine", getBlockTexture("LeavesPine")));
 | 
				
			||||||
 | 
							// Sic, using Glass logic for leaves because  Test
 | 
				
			||||||
 | 
							register(new TestBlockLogicGlass("Test:LeavesPine"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add);
 | 
							BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add);
 | 
				
			||||||
		PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId()));
 | 
							PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId()));
 | 
				
			||||||
		PLACEABLE_BLOCKS.sort(Comparator.comparing(BlockData::getId));
 | 
							PLACEABLE_BLOCKS.sort(Comparator.comparing(BlockData::getId));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,10 +38,12 @@ public class TestBushFeature extends MultiblockVegetationFeature {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		Vec3i center = context.getLocation().add_(0, 0, 1);
 | 
							Vec3i center = context.getLocation().add_(0, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		context.setBlock(center, trunk);
 | 
							if (size > 0.8) {
 | 
				
			||||||
		context.setBlock(center.add_(0, 0, 1), leaves);
 | 
								context.setBlock(center, trunk);
 | 
				
			||||||
 | 
								context.setBlock(center.add_(0, 0, 1), leaves);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		iterateBlob(center, stretch(size, 1.3, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> {
 | 
							iterateBlob(center, stretch(size, 0.5, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> {
 | 
				
			||||||
			setLeaves(context, p, leaves);
 | 
								setLeaves(context, p, leaves);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,10 +26,10 @@ import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlo
 | 
				
			|||||||
public class TestTreeFeature extends MultiblockVegetationFeature {
 | 
					public class TestTreeFeature extends MultiblockVegetationFeature {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log");
 | 
						private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log");
 | 
				
			||||||
	private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
 | 
						private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:LeavesPine");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public TestTreeFeature(String id, SurfaceFloatField selector) {
 | 
						public TestTreeFeature(String id, SurfaceFloatField selector) {
 | 
				
			||||||
		super(id, selector, 10 * 10);
 | 
							super(id, selector, 7 * 7);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
@@ -39,18 +39,29 @@ public class TestTreeFeature extends MultiblockVegetationFeature {
 | 
				
			|||||||
		Vec3i center = start.add_(0);
 | 
							Vec3i center = start.add_(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		double size = selectorValue * randomDouble(context, 0.8, 1.2);
 | 
							double size = selectorValue * randomDouble(context, 0.8, 1.2);
 | 
				
			||||||
 | 
							double volume = stretch(size, 2.5, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int height = (int) stretch(size, 3, 7);
 | 
							int height = (int) stretch(size, 8, 12);
 | 
				
			||||||
		for (; center.z < start.z + height; ++center.z) {
 | 
							for (; center.z < start.z + height; ++center.z) {
 | 
				
			||||||
			context.setBlock(center, trunk);
 | 
								context.setBlock(center, trunk);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							--center.z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		double branchHorDistance = 0;
 | 
							iterateBlob(center, 1.5 * volume, 1.75, 0.5, 3, p -> {
 | 
				
			||||||
 | 
								setLeaves(context, p, leaves);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int branchCount = 1 + context.getRandom().nextInt(2) + (int) (stretch(size, 0, 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (int i = 0; i < branchCount; ++i) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		do {
 | 
					 | 
				
			||||||
			double branchSize = 0.5 + randomDouble(context, 1, 2) * size;
 | 
					 | 
				
			||||||
			double branchHorAngle = randomDouble(context, 0, 2 * Math.PI);
 | 
								double branchHorAngle = randomDouble(context, 0, 2 * Math.PI);
 | 
				
			||||||
			int branchVertOffset = (int) randomDouble(context, -2, 0);
 | 
								double branchHorDistance = randomDouble(context, 0.7, 1.5) * volume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int branchVertOffset = (int) randomDouble(context, -height / 3.0, -height / 1.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								double branchSize = randomDouble(context, 1, 2) * volume;
 | 
				
			||||||
 | 
								double branchHeight = 1.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Vec3i branchCenter = center.add_(
 | 
								Vec3i branchCenter = center.add_(
 | 
				
			||||||
				(int) (Math.sin(branchHorAngle) * branchHorDistance),
 | 
									(int) (Math.sin(branchHorAngle) * branchHorDistance),
 | 
				
			||||||
@@ -58,12 +69,12 @@ public class TestTreeFeature extends MultiblockVegetationFeature {
 | 
				
			|||||||
				branchVertOffset
 | 
									branchVertOffset
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			iterateBlob(branchCenter, 1 * branchSize, 2.3 * branchSize, 0.5, 3, p -> {
 | 
								iterateBlob(branchCenter, branchSize, branchHeight, 0.5, 3, p -> {
 | 
				
			||||||
				setLeaves(context, p, leaves);
 | 
									setLeaves(context, p, leaves);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			branchHorDistance = randomDouble(context, 0.7, 1.5);
 | 
							}
 | 
				
			||||||
		} while (context.getRandom().nextInt(8) > 1);
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Progressia
 | 
				
			||||||
 | 
					 * Copyright (C)  2020-2021  Wind Corporation and contributors
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package ru.windcorp.progressia.test.trees;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.Random;
 | 
				
			||||||
 | 
					import java.util.function.Consumer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import glm.vec._3.i.Vec3i;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.backend.Usage;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.Renderable;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.Shape;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.ShapePart;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.ShapePrototype;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.texture.Texture;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.world.block.BlockRender;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.common.world.DefaultChunkData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BlockRenderLeavesHazel extends BlockRender implements BlockOptimizedSimple {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final Texture texture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public BlockRenderLeavesHazel(String id, Texture texture) {
 | 
				
			||||||
 | 
							super(id);
 | 
				
			||||||
 | 
							this.texture = texture;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer<ShapePart> output) {
 | 
				
			||||||
 | 
							ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided();
 | 
				
			||||||
 | 
							sp.push().translate(bic.x, bic.y, bic.z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Random random = new Random(chunk.getX() ^ bic.x);
 | 
				
			||||||
 | 
							random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y);
 | 
				
			||||||
 | 
							random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							final float angle = (float) (Math.PI / 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.push().translate(0, 0, random.nextFloat() * 0.5f)
 | 
				
			||||||
 | 
								.rotateZ(random.nextFloat() * Math.PI)
 | 
				
			||||||
 | 
								.rotateX(-0.3f + random.nextFloat() * 0.6)
 | 
				
			||||||
 | 
								.scale(1.3f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.push().translate(0, 0, -0.5f).rotateX(angle).translate(-0.5f, -0.5f, 0);
 | 
				
			||||||
 | 
							output.accept(sp.build());
 | 
				
			||||||
 | 
							sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.push().translate(0, 0, -0.5f).rotateX(-angle).translate(-0.5f, -0.5f, 0);
 | 
				
			||||||
 | 
							output.accept(sp.build());
 | 
				
			||||||
 | 
							sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.push().translate(0, 0, -0.5f).rotateY(angle).translate(-0.5f, -0.5f, 0);
 | 
				
			||||||
 | 
							output.accept(sp.build());
 | 
				
			||||||
 | 
							sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.push().translate(0, 0, -0.5f).rotateY(-angle).translate(-0.5f, -0.5f, 0);
 | 
				
			||||||
 | 
							output.accept(sp.build());
 | 
				
			||||||
 | 
							sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sp.pop();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
 | 
				
			||||||
 | 
							Collection<ShapePart> parts = new ArrayList<>(6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							getShapeParts(chunk, blockInChunk, parts::add);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new Shape(
 | 
				
			||||||
 | 
								Usage.STATIC,
 | 
				
			||||||
 | 
								WorldRenderProgram.getDefault(),
 | 
				
			||||||
 | 
								parts.toArray(new ShapePart[parts.size()])
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public boolean needsOwnRenderable() {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Progressia
 | 
				
			||||||
 | 
					 * Copyright (C)  2020-2021  Wind Corporation and contributors
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package ru.windcorp.progressia.test.trees;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.Random;
 | 
				
			||||||
 | 
					import java.util.function.Consumer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import glm.vec._3.i.Vec3i;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.Colors;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.backend.Usage;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.Renderable;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.Shape;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.ShapePart;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.model.ShapePrototype;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.texture.Texture;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.world.block.BlockRender;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple;
 | 
				
			||||||
 | 
					import ru.windcorp.progressia.common.world.DefaultChunkData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BlockRenderLeavesPine extends BlockRender implements BlockOptimizedSimple {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final Texture texture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public BlockRenderLeavesPine(String id, Texture texture) {
 | 
				
			||||||
 | 
							super(id);
 | 
				
			||||||
 | 
							this.texture = texture;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer<ShapePart> output) {
 | 
				
			||||||
 | 
							Random random = new Random(chunk.getX() ^ bic.x);
 | 
				
			||||||
 | 
							random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y);
 | 
				
			||||||
 | 
							random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided();
 | 
				
			||||||
 | 
							sp.push().translate(
 | 
				
			||||||
 | 
								bic.x + random.nextFloat() * 0.3f - 0.15f,
 | 
				
			||||||
 | 
								bic.y + random.nextFloat() * 0.3f - 0.15f,
 | 
				
			||||||
 | 
								bic.z
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							final float angle = 0.5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (float offset : new float[] { -0.25f, -0.75f }) {
 | 
				
			||||||
 | 
								sp.push().translate(0, 0, offset + random.nextFloat() * 0.5f)
 | 
				
			||||||
 | 
									.rotateZ(-0.3f + random.nextFloat() * 0.6)
 | 
				
			||||||
 | 
									.rotateX(-0.3f + random.nextFloat() * 0.6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sp.push().translate(0, 0, -0.3f).rotateX(angle).translate(-0.5f, -0.5f, 0.5f);
 | 
				
			||||||
 | 
								output.accept(sp.build());
 | 
				
			||||||
 | 
								sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sp.push().translate(0, 0, -0.3f).rotateX(-angle).translate(-0.5f, -0.5f, 0.5f);
 | 
				
			||||||
 | 
								output.accept(sp.build());
 | 
				
			||||||
 | 
								sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sp.push().translate(0, 0, -0.3f).rotateY(angle).translate(-0.5f, -0.5f, 0.5f);
 | 
				
			||||||
 | 
								output.accept(sp.build());
 | 
				
			||||||
 | 
								sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sp.push().translate(0, 0, -0.3f).rotateY(-angle).translate(-0.5f, -0.5f, 0.5f);
 | 
				
			||||||
 | 
								output.accept(sp.build());
 | 
				
			||||||
 | 
								sp.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sp.pop();
 | 
				
			||||||
 | 
								sp.addColorMultiplier(Colors.GRAY_A);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
 | 
				
			||||||
 | 
							Collection<ShapePart> parts = new ArrayList<>(6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							getShapeParts(chunk, blockInChunk, parts::add);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new Shape(
 | 
				
			||||||
 | 
								Usage.STATIC,
 | 
				
			||||||
 | 
								WorldRenderProgram.getDefault(),
 | 
				
			||||||
 | 
								parts.toArray(new ShapePart[parts.size()])
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public boolean needsOwnRenderable() {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/assets/textures/blocks/LeavesHazel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/assets/textures/blocks/LeavesHazel.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 408 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/assets/textures/blocks/LeavesPine.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/assets/textures/blocks/LeavesPine.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 6.4 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 6.8 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 6.5 KiB  | 
		Reference in New Issue
	
	Block a user