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:
parent
4b10dc82ed
commit
efc6a8ecd0
@ -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);
|
||||||
|
|
||||||
|
if (size > 0.8) {
|
||||||
context.setBlock(center, trunk);
|
context.setBlock(center, trunk);
|
||||||
context.setBlock(center.add_(0, 0, 1), leaves);
|
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