Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve AABB model performance and refactor TopBottomOrientedTexturedBlock. #1570

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package se.llbit.chunky.block;

import se.llbit.chunky.model.FixedTopBottomRotatableTexturedBlockModel;
import se.llbit.chunky.model.TexturedBlockModel;
import se.llbit.chunky.resources.Texture;

/**
Expand All @@ -9,18 +9,19 @@
* If the top and bottom should rotate with the rest of the block, use TopBottomOrientedTexturedBlock.
*/
public class FixedTopBottomRotatableTexturedBlock extends AbstractModelBlock {
public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture side, Texture top) {
this(name, facing, front, side, side, side, top, top);
}
public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture side, Texture top) {
this(name, facing, front, side, side, side, top, top);
}

public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture side, Texture top, Texture bottom) {
this(name, facing, front, side, side, side, top, bottom);
}
public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture side, Texture top, Texture bottom) {
this(name, facing, front, side, side, side, top, bottom);
}

public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture south, Texture east, Texture west, Texture top, Texture bottom) {
super(name, front);
this.model = new FixedTopBottomRotatableTexturedBlockModel(facing, front, south, east, west, top, bottom);
solid = true;
opaque = true;
}
public FixedTopBottomRotatableTexturedBlock(String name, String facing, Texture front, Texture south, Texture east, Texture west, Texture top, Texture bottom) {
super(name, front);
this.model = new TexturedBlockModel(TexturedBlockModel.Orientation.fromFacing(facing, true),
front, east, south, west, top, bottom, null);
solid = true;
opaque = true;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package se.llbit.chunky.block;

import se.llbit.chunky.model.TopBottomOrientedTexturedBlockModel;
import se.llbit.chunky.model.TexturedBlockModel;
import se.llbit.chunky.resources.Texture;

/**
Expand All @@ -19,7 +19,8 @@ public TopBottomOrientedTexturedBlock(String name, String facing, Texture front,

public TopBottomOrientedTexturedBlock(String name, String facing, Texture front, Texture south, Texture east, Texture west, Texture top, Texture bottom) {
super(name, front);
this.model = new TopBottomOrientedTexturedBlockModel(facing, front, south, east, west, top, bottom);
this.model = new TexturedBlockModel(TexturedBlockModel.Orientation.fromFacing(facing, false),
front, east, south, west, top, bottom, null);
solid = true;
opaque = true;
}
Expand Down
29 changes: 14 additions & 15 deletions chunky/src/java/se/llbit/chunky/model/AABBModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import se.llbit.math.Ray;
import se.llbit.math.Vector3;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
Expand Down Expand Up @@ -81,44 +79,45 @@ public boolean intersect(Ray ray, Scene scene) {
for (int i = 0; i < boxes.length; ++i) {
if (boxes[i].intersect(ray)) {
Tint[] tintedFacesBox = tintedFaces != null ? tintedFaces[i] : null;
UVMapping[] mappingBox = mapping != null ? mapping[i] : null;
Vector3 n = ray.getNormal();
if (n.y > 0) { // top
ray.v = 1 - ray.v;
if (intersectFace(ray, scene, textures[i][4],
mapping != null ? mapping[i][4] : null
if (intersectFace(ray, textures[i][4],
mappingBox != null ? mappingBox[4] : null
)) {
tint = tintedFacesBox != null ? tintedFacesBox[4] : Tint.NONE;
hit = true;
}
} else if (n.y < 0) { // bottom
if (intersectFace(ray, scene, textures[i][5],
mapping != null ? mapping[i][5] : null)) {
if (intersectFace(ray, textures[i][5],
mappingBox != null ? mappingBox[5] : null)) {
hit = true;
tint = tintedFacesBox != null ? tintedFacesBox[5] : Tint.NONE;
}
} else if (n.z < 0) { // north
if (intersectFace(ray, scene, textures[i][0],
mapping != null ? mapping[i][0] : null
if (intersectFace(ray, textures[i][0],
mappingBox != null ? mappingBox[0] : null
)) {
hit = true;
tint = tintedFacesBox != null ? tintedFacesBox[0] : Tint.NONE;
}
} else if (n.z > 0) { // south
if (intersectFace(ray, scene, textures[i][2],
mapping != null ? mapping[i][2] : null
if (intersectFace(ray, textures[i][2],
mappingBox != null ? mappingBox[2] : null
)) {
hit = true;
tint = tintedFacesBox != null ? tintedFacesBox[2] : Tint.NONE;
}
} else if (n.x < 0) { // west
if (intersectFace(ray, scene, textures[i][3],
mapping != null ? mapping[i][3] : null)) {
if (intersectFace(ray, textures[i][3],
mappingBox != null ? mappingBox[3] : null)) {
hit = true;
tint = tintedFacesBox != null ? tintedFacesBox[3] : Tint.NONE;
}
} else if (n.x > 0) { // east
if (intersectFace(ray, scene, textures[i][1],
mapping != null ? mapping[i][1] : null)) {
if (intersectFace(ray, textures[i][1],
mappingBox != null ? mappingBox[1] : null)) {
hit = true;
tint = tintedFacesBox != null ? tintedFacesBox[1] : Tint.NONE;
}
Expand All @@ -140,7 +139,7 @@ public boolean intersect(Ray ray, Scene scene) {
return hit;
}

private boolean intersectFace(Ray ray, Scene scene, Texture texture, UVMapping mapping) {
private boolean intersectFace(Ray ray, Texture texture, UVMapping mapping) {
// This is the method that handles intersecting faces of all AABB-based models.
// Do normal mapping, parallax occlusion mapping, specular maps and all the good stuff here!

Expand Down
9 changes: 4 additions & 5 deletions chunky/src/java/se/llbit/chunky/model/DecoratedPotModel.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package se.llbit.chunky.model;

import se.llbit.chunky.entity.SporeBlossom;
import se.llbit.chunky.resources.Texture;
import se.llbit.log.Log;
import se.llbit.math.Quad;
Expand All @@ -18,7 +17,7 @@
import java.util.Collection;
import java.util.LinkedList;

public class DecoratedPotModel extends TopBottomOrientedTexturedBlockModel {
public class DecoratedPotModel extends OrientedQuadModel {

private static final Vector4 BASE_UV_MAP = new Vector4(0 / 32., 14 / 32., 8 / 32., 22 / 32.);
private static final Vector4 SIDE_UV_MAP = new Vector4(1 / 16., 15 / 16., 0., 1.);
Expand Down Expand Up @@ -103,7 +102,7 @@ public Collection<Primitive> primitives(Vector3 offset) {
Collection<Primitive> primitives = new LinkedList<>();
Transform transform = Transform.NONE
.translate(position.x + offset.x, position.y + offset.y, position.z + offset.z);
for (Quad quad : rotateToFacing(facing, QUADS)) {
for (Quad quad : rotateToFacing(TexturedBlockModel.Orientation.fromFacing(facing, false), QUADS)) {
quad.addTriangles(primitives, material, transform);
}
return primitives;
Expand All @@ -127,7 +126,7 @@ public JsonValue toJson() {
}

public DecoratedPotModel(String facing, String[] shards) {
super(facing, DEFAULT_QUADS, new Texture[]{
super(TexturedBlockModel.Orientation.fromFacing(facing, false), DEFAULT_QUADS, new Texture[]{
// shards[0] top crafting slot -> north
getTextureForShard(shards[0]),
// shards[3] bottom crafting slot -> south
Expand All @@ -138,7 +137,7 @@ public DecoratedPotModel(String facing, String[] shards) {
getTextureForShard(shards[2]),
Texture.decoratedPotBase, // top
Texture.decoratedPotBase // bottom
});
}, null);
}

private static Texture getTextureForShard(String shard) {
Expand Down

This file was deleted.

121 changes: 121 additions & 0 deletions chunky/src/java/se/llbit/chunky/model/OrientedQuadModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2023 Chunky contributors
*
* This file is part of Chunky.
*
* Chunky 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.
*
* Chunky 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 Chunky. If not, see <http://www.gnu.org/licenses/>.
*/

package se.llbit.chunky.model;

import se.llbit.chunky.resources.Texture;
import se.llbit.log.Log;
import se.llbit.math.Quad;
import se.llbit.math.Vector3;
import se.llbit.math.Vector4;
import se.llbit.util.annotation.Nullable;

import java.util.Arrays;

public class OrientedQuadModel extends QuadModel {

public static final Quad FULL_BLOCK_NORTH_SIDE = new Quad(
new Vector3(1, 0, 0),
new Vector3(0, 0, 0),
new Vector3(1, 1, 0),
new Vector4(0, 1, 0, 1));
public static final Quad FULL_BLOCK_SOUTH_SIDE = new Quad(
new Vector3(0, 0, 1),
new Vector3(1, 0, 1),
new Vector3(0, 1, 1),
new Vector4(0, 1, 0, 1));
public static final Quad FULL_BLOCK_WEST_SIDE = new Quad(
new Vector3(0, 0, 0),
new Vector3(0, 0, 1),
new Vector3(0, 1, 0),
new Vector4(0, 1, 0, 1));
public static final Quad FULL_BLOCK_EAST_SIDE = new Quad(
new Vector3(1, 0, 1),
new Vector3(1, 0, 0),
new Vector3(1, 1, 1),
new Vector4(0, 1, 0, 1));
public static final Quad FULL_BLOCK_TOP_SIDE = new Quad(
new Vector3(1, 1, 0),
new Vector3(0, 1, 0),
new Vector3(1, 1, 1),
new Vector4(1, 0, 1, 0));
public static final Quad FULL_BLOCK_BOTTOM_SIDE = new Quad(
new Vector3(0, 0, 0),
new Vector3(1, 0, 0),
new Vector3(0, 0, 1),
new Vector4(0, 1, 0, 1));

public static final Quad[] FULL_BLOCK_QUADS = {
FULL_BLOCK_NORTH_SIDE, FULL_BLOCK_SOUTH_SIDE,
FULL_BLOCK_WEST_SIDE, FULL_BLOCK_EAST_SIDE,
FULL_BLOCK_TOP_SIDE, FULL_BLOCK_BOTTOM_SIDE
};

public static Quad[] rotateToFacing(TexturedBlockModel.Orientation orientation, Quad[] quads) {
switch (orientation.reduce()) {
default:
Log.warn("Unknown orientation: " + orientation);
case NORTH:
return quads;
case SOUTH:
return Model.rotateY(Model.rotateY(quads));
case EAST:
return Model.rotateY(quads, -Math.toRadians(90));
case WEST:
return Model.rotateNegY(quads);
}
}

protected final Quad[] quads;
protected final Texture[] textures;
protected final Tint[] tints;

public OrientedQuadModel(TexturedBlockModel.Orientation orientation, Quad[] quads, Texture[] textures,
@Nullable Tint[] tints) {
this.quads = rotateToFacing(orientation, quads);
this.textures = textures;
this.tints = tints;
}

public OrientedQuadModel(TexturedBlockModel.Orientation orientation, Quad[] quads, Quad[] topBottomQuads,
Texture[] textures, @Nullable Tint[] tints) {
quads = rotateToFacing(orientation, quads);
topBottomQuads = orientation.side ? topBottomQuads : rotateToFacing(orientation, topBottomQuads);

this.quads = new Quad[quads.length + topBottomQuads.length];
System.arraycopy(quads, 0, this.quads, 0, quads.length);
System.arraycopy(topBottomQuads, 0, this.quads, quads.length, topBottomQuads.length);
this.textures = textures;
this.tints = tints;
}

@Override
public Quad[] getQuads() {
return quads;
}

@Override
public Texture[] getTextures() {
return new Texture[0];
}

@Override
public Tint[] getTints() {
return tints;
}
}
Loading