Compare commits

..
8 Commits
Author SHA1 Message Date
Martin Robertz 39ed6607a6 update 2024-10-06 13:35:38 +02:00
Alexdoru 99b815c12e Reduce RAM allocations during rendering (#22)
* edit doc for fluid rendering method + clamp fillRate of the tank between 0 and 1

* init all static fields in the static block

* remove object instantiation that is never used in the following method and assign local variables

* reduce object allocation spam in CCModelLibrary.getRenderMatrix

* fix error in local V value

* remove all object instantiation during rendering to minimize RAM allocation in RenderUtils
2024-10-06 13:33:56 +02:00
Martin Robertz 0f37937ada update 2024-09-01 22:46:57 +02:00
Alexdoru c9d29a5c8e fix logic of the ClassConstantPoolParser (#20) 2024-09-01 22:19:33 +02:00
tth05 ea4f68d163 Add map to provide fast access to all config tags in sub-tree (#18) 2024-07-18 21:37:30 +07:00
Dream Master 549f769747 update 2024-07-17 16:47:04 +07:00
Caedis cba2e0f642 Fix casing 2024-07-04 00:30:22 -07:00
Jason Mitchell 3740253590 Maybe more backwards compatible (#16)
* Maybe more backwards compatible
2024-07-03 11:21:27 -07:00
24 changed files with 467 additions and 307 deletions

No files matched your search

+15 -1
View File
@@ -55,6 +55,9 @@ generateGradleTokenClass = codechicken.core.asm.Tags
# Name of the token containing the project's current version to generate/replace.
gradleTokenVersion = VERSION
# [DEPRECATED] Mod Group replacement token.
gradleTokenGroupName =
# [DEPRECATED]
# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java
# public static final String VERSION = "GRADLETOKEN_VERSION";
@@ -76,6 +79,11 @@ accessTransformersFile =
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
usesMixins = false
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
# Mixin classes will have access to "main" classes, but not the other way around.
separateMixinSourceSet =
# Adds some debug arguments like verbose output and class export.
usesMixinDebug = false
@@ -108,9 +116,15 @@ minimizeShadowedDependencies = true
# If disabled, won't rename the shadowed classes.
relocateShadowedDependencies = true
# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
includeWellKnownRepositories = true
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
# list of strings, with the acceptable keys being(case does not matter):
# cursemaven
# modrinth
excludeWellKnownRepositories =
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+5 -2
View File
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Vendored
+2
View File
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27'
}
@@ -83,7 +83,7 @@ public class ClassConstantPoolParser {
if (strLen == bytes.length) {
for (int j = index + 3; j < index + 3 + strLen; j++) {
if (basicClass[j] != bytes[j - (index + 3)]) {
break label;
continue label;
}
}
return true;
@@ -119,11 +119,9 @@ public class RedirectorTransformer implements IClassTransformer {
changed = true;
}
} else if (node.getOpcode() == Opcodes.INVOKESTATIC && node instanceof MethodInsnNode mNode) {
if (redirectedMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) {
mNode.name = mNode.name + "Static";
changed = true;
} else if (redirectedSimpleMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) {
} else if (node instanceof MethodInsnNode mNode) {
if (node.getOpcode() == Opcodes.INVOKESTATIC && redirectedSimpleMethods.contains(mNode.name)
&& mNode.owner.equals(RenderStateClass)) {
mn.instructions.insertBefore(
mNode,
new MethodInsnNode(
@@ -132,8 +130,15 @@ public class RedirectorTransformer implements IClassTransformer {
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
mNode.setOpcode(Opcodes.INVOKEVIRTUAL);
mNode.name = mNode.name + "Instance";
changed = true;
}
} else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && mNode.owner.equals(RenderStateClass)
&& (redirectedSimpleMethods.contains(mNode.name)
|| redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
}
}
}
@@ -6,8 +6,10 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
public abstract class ConfigTagParent {
@@ -21,25 +23,30 @@ public abstract class ConfigTagParent {
}
public int compare(ConfigTag o1, ConfigTag o2) {
if (o1.position != o2.position) return compareInt(o1.position, o2.position);
if (o1.position != o2.position) return Integer.compare(o1.position, o2.position);
if (o1.brace != o2.brace) return o1.brace ? 1 : -1; // braced one goes after
switch (sortMode) {
case 1:
if (o1.value == o2.value) return 0;
if (o1.value == null) return 1;
if (o2.value == null) return -1;
return o1.value.compareTo(o2.value);
default:
return o1.name.compareTo(o2.name);
if (sortMode == 1) {
if (Objects.equals(o1.value, o2.value)) return 0;
if (o1.value == null) return 1;
if (o2.value == null) return -1;
return o1.value.compareTo(o2.value);
} else {
return o1.name.compareTo(o2.name);
}
}
private int compareInt(int a, int b) {
return a == b ? 0 : a < b ? -1 : 1;
}
}
private TreeMap<String, ConfigTag> childtags = new TreeMap<String, ConfigTag>();
/**
* The immediate child tags of this tag
*/
private final TreeMap<String, ConfigTag> childtags = new TreeMap<>();
/**
* A map of all tags in the tree, meaning all tags in this tag and all tags in child tags (recursively). Allows for
* quick access to any tag in the tree, without the need to traverse the tree part by part.
*/
private final Map<String, ConfigTag> allTagsInTree = new HashMap<>();
public String comment;
/**
* 0 = name, 1 = value
@@ -88,7 +95,7 @@ public abstract class ConfigTagParent {
}
public boolean containsTag(String tagname) {
return getTag(tagname, false) != null;
return allTagsInTree.get(tagname) != null;
}
public ConfigTag getNewTag(String tagname) {
@@ -96,6 +103,12 @@ public abstract class ConfigTagParent {
}
public ConfigTag getTag(String tagname, boolean create) {
ConfigTag tag = allTagsInTree.get(tagname);
if (tag == null && create) return getTagRecursive(tagname, create);
return tag;
}
public ConfigTag getTagRecursive(String tagname, boolean create) {
int dotpos = tagname.indexOf(".");
String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos);
ConfigTag basetag = childtags.get(basetagname);
@@ -115,6 +128,8 @@ public abstract class ConfigTagParent {
}
public boolean removeTag(String tagname) {
removeChildFromFlatMap(tagname);
ConfigTag tag = getTag(tagname, false);
if (tag == null) return false;
@@ -131,6 +146,22 @@ public abstract class ConfigTagParent {
public void addChild(ConfigTag tag) {
childtags.put(tag.name, tag);
addChildToFlatMap(tag.name, tag);
}
private void addChildToFlatMap(String path, ConfigTag tag) {
allTagsInTree.put(path, tag);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.addChildToFlatMap(t.name + "." + path, tag);
}
private void removeChildFromFlatMap(String path) {
allTagsInTree.remove(path);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.removeChildFromFlatMap(t.name + "." + path);
}
public <T extends ConfigTag> ArrayList<T> getSortedTagList() {
@@ -64,15 +64,15 @@ public class Canvas9Seg {
public void draw(CCRenderState state, int x, int y, int w, int h) {
CCRenderState.changeTexture(tex);
state.reset();
state.startDrawing();
state.resetInstance();
state.startDrawingInstance();
int[] sw = new int[] { x, x + seg_w[0], x + w - seg_w[2], x + w };
int[] sh = new int[] { y, y + seg_h[0], y + h - seg_h[2], y + h };
for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg);
state.draw();
state.drawInstance();
}
public void draw(int x, int y, int w, int h) {
@@ -128,8 +128,8 @@ public class LightMatrix implements CCRenderState.IVertexOperation {
float[] a = ao(lc.side);
float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd);
int[] b = brightness(lc.side);
state.setColour(ColourRGBA.multiplyC(state.colour, f));
state.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF);
state.setColourInstance(ColourRGBA.multiplyC(state.colour, f));
state.setBrightnessInstance((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF);
}
@Override
@@ -88,7 +88,7 @@ public class LightModel implements CCRenderState.IVertexOperation {
@Override
public void operate(CCRenderState state) {
state.setColour(apply(state.colour, state.normal));
state.setColourInstance(apply(state.colour, state.normal));
}
@Override
@@ -47,7 +47,7 @@ public class PlanarLightMatrix extends PlanarLightModel {
@Override
public void operate(CCRenderState state) {
super.operate(state);
state.setBrightness(brightness(state.side));
state.setBrightnessInstance(brightness(state.side));
}
@Override
@@ -27,7 +27,7 @@ public class PlanarLightModel implements CCRenderState.IVertexOperation {
@Override
public void operate(CCRenderState state) {
state.setColour(ColourRGBA.multiply(state.colour, colours[state.side]));
state.setColourInstance(ColourRGBA.multiply(state.colour, colours[state.side]));
}
@Override
@@ -46,7 +46,7 @@ public class SimpleBrightnessModel implements CCRenderState.IVertexOperation {
@Override
public void operate(CCRenderState state) {
state.setBrightness(sample(state.side));
state.setBrightnessInstance(sample(state.side));
}
@Override
@@ -154,7 +154,7 @@ public class BlockRenderer {
// public static void renderFullBlock(int sideMask) {
public static void renderFullBlock(CCRenderState state, int sideMask) {
state.setModel(fullBlock);
state.setModelInstance(fullBlock);
renderFaces(state, sideMask);
}
@@ -171,8 +171,8 @@ public class BlockRenderer {
public static void renderFaces(CCRenderState state, int sideMask) {
if (sideMask == 0x3F) return;
for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) {
state.setVertexRange(s * 4, (s + 1) * 4);
state.render();
state.setVertexRangeInstance(s * 4, (s + 1) * 4);
state.renderInstance();
}
}
@@ -191,10 +191,10 @@ public class BlockRenderer {
public static void renderCuboid(CCRenderState state, Cuboid6 bounds, int sideMask) {
if (sideMask == 0x3F) return;
state.setModel(face);
state.setModelInstance(face);
for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) {
face.loadCuboidFace(bounds, s);
state.render();
state.renderInstance();
}
}
@@ -467,8 +467,8 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable<CCModel> {
* @param ops Operations to apply
*/
public void render(CCRenderState state, int start, int end, CCRenderState.IVertexOperation... ops) {
state.setPipeline(this, start, end, ops);
state.render();
state.setPipelineInstance(this, start, end, ops);
state.renderInstance();
}
public void render(int start, int end, CCRenderState.IVertexOperation... ops) {
@@ -5,7 +5,6 @@ import static codechicken.lib.math.MathHelper.phi;
import codechicken.lib.vec.Matrix4;
import codechicken.lib.vec.Quat;
import codechicken.lib.vec.Rotation;
import codechicken.lib.vec.Scale;
import codechicken.lib.vec.Vector3;
public class CCModelLibrary {
@@ -82,7 +81,12 @@ public class CCModelLibrary {
i++;
}
@Deprecated
public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) {
return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation);
return new Matrix4().translate(position).scale(scale).apply(rotation);
}
public static Matrix4 getRenderMatrix(double posX, double posY, double posZ, Rotation rotation, double scale) {
return new Matrix4().translate(posX, posY, posZ).scale(scale).apply(rotation);
}
}
@@ -49,7 +49,7 @@ public class CCRenderPipeline {
public void render() {
rebuild();
renderState.render();
renderState.renderInstance();
}
}
@@ -101,7 +101,7 @@ public class CCRenderState {
/**
* Management class for a vertex attrute such as colour, normal etc This class should handle the loading of the
* attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others
*
*
* @param <T> The array type for this attrute eg. int[], Vector3[]
*/
public abstract static class VertexAttribute<T> implements IVertexOperation {
@@ -146,7 +146,7 @@ public class CCRenderState {
/**
* Gets an array of vertex attrutes
*
*
* @param attr The vertex attrute to get
* @param <T> The attrute array type
* @return An array, or null if not computed
@@ -193,8 +193,8 @@ public class CCRenderState {
@Override
public void operate(CCRenderState state) {
if (normalRef != null) state.setNormal(normalRef[state.vertexIndex]);
else state.setNormal(Rotation.axes[state.side]);
if (normalRef != null) state.setNormalInstance(normalRef[state.vertexIndex]);
else state.setNormalInstance(Rotation.axes[state.side]);
}
};
public static VertexAttribute<int[]> colourAttrib = new VertexAttribute<>() {
@@ -214,8 +214,9 @@ public class CCRenderState {
@Override
public void operate(CCRenderState state) {
if (colourRef != null) state.setColour(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex]));
else state.setColour(state.baseColour);
if (colourRef != null)
state.setColourInstance(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex]));
else state.setColourInstance(state.baseColour);
}
};
public static VertexAttribute<int[]> lightingAttrib = new VertexAttribute<>() {
@@ -241,7 +242,7 @@ public class CCRenderState {
@Override
public void operate(CCRenderState state) {
state.setColour(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex]));
state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex]));
}
};
public static VertexAttribute<int[]> sideAttrib = new VertexAttribute<>() {
@@ -326,11 +327,15 @@ public class CCRenderState {
public boolean hasBrightness;
public int brightness;
// attrute storage
// attribute storage
public int side;
public LC lc = new LC();
public void reset() {
public static void reset() {
instance().resetInstance();
}
public void resetInstance() {
model = null;
pipeline.reset();
useNormals = hasNormal = hasBrightness = hasColour = false;
@@ -338,27 +343,27 @@ public class CCRenderState {
baseColour = alphaOverride = -1;
}
public void setPipeline(IVertexOperation... ops) {
public void setPipelineInstance(IVertexOperation... ops) {
pipeline.setPipeline(ops);
}
@Deprecated
public static void setPipelineStatic(IVertexOperation... ops) {
instance().setPipeline(ops);
public static void setPipeline(IVertexOperation... ops) {
instance().setPipelineInstance(ops);
}
public void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) {
public void setPipelineInstance(IVertexSource model, int start, int end, IVertexOperation... ops) {
pipeline.reset();
setModel(model, start, end);
setModelInstance(model, start, end);
pipeline.setPipeline(ops);
}
@Deprecated
public static void setPipelineStatic(IVertexSource model, int start, int end, IVertexOperation... ops) {
instance().setPipeline(model, start, end, ops);
public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) {
instance().setPipelineInstance(model, start, end, ops);
}
public void bindModel(IVertexSource model) {
public void bindModelInstance(IVertexSource model) {
if (this.model != model) {
this.model = model;
pipeline.rebuild();
@@ -366,74 +371,74 @@ public class CCRenderState {
}
@Deprecated
public static void bindModelStatic(IVertexSource model) {
instance().bindModel(model);
public static void bindModel(IVertexSource model) {
instance().bindModelInstance(model);
}
public void setModel(IVertexSource source) {
setModel(source, 0, source.getVertices().length);
public void setModelInstance(IVertexSource source) {
setModelInstance(source, 0, source.getVertices().length);
}
@Deprecated
public static void setModelStatic(IVertexSource source) {
instance().setModel(source);
public static void setModel(IVertexSource source) {
instance().setModelInstance(source);
}
public void setModel(IVertexSource source, int start, int end) {
bindModel(source);
setVertexRange(start, end);
public void setModelInstance(IVertexSource source, int start, int end) {
bindModelInstance(source);
setVertexRangeInstance(start, end);
}
@Deprecated
public static void setModelStatic(IVertexSource source, int start, int end) {
instance().setModel(source, start, end);
public static void setModel(IVertexSource source, int start, int end) {
instance().setModelInstance(source, start, end);
}
public void setVertexRange(int start, int end) {
public void setVertexRangeInstance(int start, int end) {
firstVertexIndex = start;
lastVertexIndex = end;
}
@Deprecated
public static void setVertexRangeStatic(int start, int end) {
instance().setVertexRange(start, end);
public static void setVertexRange(int start, int end) {
instance().setVertexRangeInstance(start, end);
}
public void render(IVertexOperation... ops) {
setPipeline(ops);
render();
public void renderInstance(IVertexOperation... ops) {
setPipelineInstance(ops);
renderInstance();
}
@Deprecated
public static void renderStatic(IVertexOperation... ops) {
instance().render(ops);
public static void render(IVertexOperation... ops) {
instance().renderInstance(ops);
}
public void render() {
public void renderInstance() {
Vertex5[] verts = model.getVertices();
for (vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) {
model.prepareVertex(this);
vert.set(verts[vertexIndex]);
runPipeline();
writeVert();
runPipelineInstance();
writeVertInstance();
}
}
@Deprecated
public static void renderStatic() {
instance().render();
public static void render() {
instance().renderInstance();
}
public void runPipeline() {
public void runPipelineInstance() {
pipeline.operate();
}
@Deprecated
public static void runPipelineStatic() {
instance().runPipeline();
public static void runPipeline() {
instance().runPipelineInstance();
}
public void writeVert() {
public void writeVertInstance() {
if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z);
if (hasColour) Tessellator.instance.setColorRGBA(
colour >>> 24,
@@ -445,71 +450,83 @@ public class CCRenderState {
}
@Deprecated
public static void writeVertStatic() {
instance().writeVert();
public static void writeVert() {
instance().writeVertInstance();
}
public void setNormal(double x, double y, double z) {
public void setNormalInstance(double x, double y, double z) {
hasNormal = true;
normal.set(x, y, z);
}
@Deprecated
public static void setNormalStatic(double x, double y, double z) {
instance().setNormal(x, y, z);
public static void setNormal(double x, double y, double z) {
instance().setNormalInstance(x, y, z);
}
public void setNormal(Vector3 n) {
public void setNormalInstance(Vector3 n) {
hasNormal = true;
normal.set(n);
}
@Deprecated
public static void setNormalStatic(Vector3 n) {
instance().setNormal(n);
public static void setNormal(Vector3 n) {
instance().setNormalInstance(n);
}
public void setColour(int c) {
public void setColourInstance(int c) {
hasColour = true;
colour = c;
}
@Deprecated
public static void setColourStatic(int c) {
instance().setColour(c);
public static void setColour(int c) {
instance().setColourInstance(c);
}
public void setBrightness(int b) {
public void setBrightnessInstance(int b) {
hasBrightness = true;
brightness = b;
}
@Deprecated
public static void setBrightnessStatic(int b) {
instance().setBrightness(b);
public static void setBrightness(int b) {
instance().setBrightnessInstance(b);
}
public void setBrightness(IBlockAccess world, int x, int y, int z) {
setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z));
public void setBrightnessInstance(IBlockAccess world, int x, int y, int z) {
setBrightnessInstance(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z));
}
@Deprecated
public static void setBrightnessStatic(IBlockAccess world, int x, int y, int z) {
instance().setBrightness(world, x, y, z);
public static void setBrightness(IBlockAccess world, int x, int y, int z) {
instance().setBrightnessInstance(world, x, y, z);
}
public void pullLightmap() {
setBrightness((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX);
public static void pullLightmap() {
instance().pullLightmapInstance();
}
public void pushLightmap() {
public void pullLightmapInstance() {
setBrightnessInstance((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX);
}
public static void pushLightmap() {
instance().pushLightmapInstance();
}
public void pushLightmapInstance() {
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness & 0xFFFF, brightness >>> 16);
}
/**
* Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting
*/
public void setDynamic() {
public static void setDynamic() {
instance().setDynamicInstance();
}
public void setDynamicInstance() {
useNormals = true;
computeLighting = false;
}
@@ -522,16 +539,16 @@ public class CCRenderState {
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
}
public void startDrawing() {
startDrawing(7);
public void startDrawingInstance() {
startDrawingInstance(7);
}
@Deprecated
public static void startDrawingStatic() {
instance().startDrawing();
public static void startDrawing() {
instance().startDrawingInstance();
}
public void startDrawing(int mode) {
public void startDrawingInstance(int mode) {
Tessellator.instance.startDrawing(mode);
if (hasColour) Tessellator.instance.setColorRGBA(
colour >>> 24,
@@ -542,11 +559,15 @@ public class CCRenderState {
}
@Deprecated
public static void startDrawingStatic(int mode) {
instance().startDrawing(mode);
public static void startDrawing(int mode) {
instance().startDrawingInstance(mode);
}
public void draw() {
public static void draw() {
Tessellator.instance.draw();
}
public void drawInstance() {
Tessellator.instance.draw();
}
}
@@ -23,7 +23,7 @@ public class ColourMultiplier implements CCRenderState.IVertexOperation {
@Override
public boolean load(CCRenderState state) {
if (colour == -1) {
state.setColour(-1);
state.setColourInstance(-1);
return false;
}
@@ -33,7 +33,7 @@ public class ColourMultiplier implements CCRenderState.IVertexOperation {
@Override
public void operate(CCRenderState state) {
state.setColour(ColourRGBA.multiply(state.colour, colour));
state.setColourInstance(ColourRGBA.multiply(state.colour, colour));
}
@Override
@@ -13,6 +13,7 @@ import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.fluids.Fluid;
@@ -26,87 +27,130 @@ import codechicken.lib.vec.Vector3;
public class RenderUtils {
static Vector3[] vectors = new Vector3[8];
static RenderItem uniformRenderItem = new RenderItem() {
public boolean shouldBob() {
return false;
}
};
static RenderItem uniformRenderItem;
static EntityItem entityItem;
static {
for (int i = 0; i < vectors.length; i++) vectors[i] = new Vector3();
uniformRenderItem = new RenderItem() {
public boolean shouldBob() {
return false;
}
};
uniformRenderItem.setRenderManager(RenderManager.instance);
entityItem = new EntityItem(null);
entityItem.hoverStart = 0;
}
@Deprecated
public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon,
double res) {
// spotless:off
renderFluidQuad(
point2,
vectors[0].set(point4).subtract(point1),
vectors[1].set(point1).subtract(point2),
icon,
res);
point2.x, point2.y, point2.z,
point4.x - point1.x, point4.y - point1.y, point4.z - point1.z,
point1.x - point2.x, point1.y - point2.y, point1.z - point2.z,
icon, res);
}
/**
* Draws a tessellated quadrilateral bottom to top, left to right
*
*
* @param base The bottom left corner of the quad
* @param wide The bottom of the quad
* @param high The left side of the quad
* @param res Units per icon
*/
@Deprecated
public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) {
Tessellator t = Tessellator.instance;
renderFluidQuad(
base.x, base.y, base.z,
wide.x, wide.y, wide.z,
wide.x, wide.y, wide.z,
icon, res);
}
double u1 = icon.getMinU();
/**
* Draws a tessellated quadrilateral bottom to top, left to right
* <p>
* base : The bottom left corner of the quad
* <p>
* wide : The bottom of the quad
* <p>
* high : The left side of the quad
* <p>
* res : Units per icon
*/
public static void renderFluidQuad(
double baseX, double baseY, double baseZ,
double wideX, double wideY, double wideZ,
double highX, double highY, double highZ,
IIcon icon, double res) {
Tessellator tessellator = Tessellator.instance;
double u = icon.getMinU();
double du = icon.getMaxU() - icon.getMinU();
double v2 = icon.getMaxV();
double v = icon.getMinV();
double dv = icon.getMaxV() - icon.getMinV();
double wlen = wide.mag();
double hlen = high.mag();
double wideLen = Math.sqrt(wideX * wideX + wideY * wideY + wideZ * wideZ);
double highLen = Math.sqrt(highX * highX + highY * highY + highZ * highZ);
double x = 0;
while (x < wlen) {
double rx = wlen - x;
while (x < wideLen) {
double rx = wideLen - x;
if (rx > res) rx = res;
double y = 0;
while (y < hlen) {
double ry = hlen - y;
while (y < highLen) {
double ry = highLen - y;
if (ry > res) ry = res;
Vector3 dx1 = vectors[2].set(wide).multiply(x / wlen);
Vector3 dx2 = vectors[3].set(wide).multiply((x + rx) / wlen);
Vector3 dy1 = vectors[4].set(high).multiply(y / hlen);
Vector3 dy2 = vectors[5].set(high).multiply((y + ry) / hlen);
final double mult1 = x / wideLen;
double dx1X = wideX * mult1;
double dx1Y = wideY * mult1;
double dx1Z = wideZ * mult1;
t.addVertexWithUV(
base.x + dx1.x + dy2.x,
base.y + dx1.y + dy2.y,
base.z + dx1.z + dy2.z,
u1,
v2 - ry / res * dv);
t.addVertexWithUV(base.x + dx1.x + dy1.x, base.y + dx1.y + dy1.y, base.z + dx1.z + dy1.z, u1, v2);
t.addVertexWithUV(
base.x + dx2.x + dy1.x,
base.y + dx2.y + dy1.y,
base.z + dx2.z + dy1.z,
u1 + rx / res * du,
v2);
t.addVertexWithUV(
base.x + dx2.x + dy2.x,
base.y + dx2.y + dy2.y,
base.z + dx2.z + dy2.z,
u1 + rx / res * du,
v2 - ry / res * dv);
final double mult2 = (x + rx) / wideLen;
double dx2X = wideX * mult2;
double dx2Y = wideY * mult2;
double dx2Z = wideZ * mult2;
final double mult3 = y / highLen;
double dy1X = highX * mult3;
double dy1Y = highY * mult3;
double dy1Z = highZ * mult3;
final double mult4 = (y + ry) / highLen;
double dy2X = highX * mult4;
double dy2Y = highY * mult4;
double dy2Z = highZ * mult4;
tessellator.addVertexWithUV(
baseX + dx1X + dy2X,
baseY + dx1Y + dy2Y,
baseZ + dx1Z + dy2Z,
u,
v + ry / res * dv);
tessellator.addVertexWithUV(
baseX + dx1X + dy1X,
baseY + dx1Y + dy1Y,
baseZ + dx1Z + dy1Z,
u,
v);
tessellator.addVertexWithUV(
baseX + dx2X + dy1X,
baseY + dx2Y + dy1Y,
baseZ + dx2Z + dy1Z,
u + rx / res * du,
v);
tessellator.addVertexWithUV(
baseX + dx2X + dy2X,
baseY + dx2Y + dy2Y,
baseZ + dx2Z + dy2Z,
u + rx / res * du,
v + ry / res * dv);
y += ry;
}
@@ -115,132 +159,130 @@ public class RenderUtils {
}
}
public static void translateToWorldCoords(Entity entity, float frame) {
double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame;
double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame;
double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame;
public static void translateToWorldCoords(Entity entity, float partialTicks) {
double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks;
double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks;
double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks;
GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ);
}
public static void drawCuboidOutline(Cuboid6 c) {
Tessellator var2 = Tessellator.instance;
var2.startDrawing(3);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.draw();
var2.startDrawing(3);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.draw();
var2.startDrawing(1);
var2.addVertex(c.min.x, c.min.y, c.min.z);
var2.addVertex(c.min.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.min.z);
var2.addVertex(c.max.x, c.max.y, c.min.z);
var2.addVertex(c.max.x, c.min.y, c.max.z);
var2.addVertex(c.max.x, c.max.y, c.max.z);
var2.addVertex(c.min.x, c.min.y, c.max.z);
var2.addVertex(c.min.x, c.max.y, c.max.z);
var2.draw();
Tessellator tess = Tessellator.instance;
tess.startDrawing(3);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.draw();
tess.startDrawing(3);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.draw();
tess.startDrawing(1);
tess.addVertex(c.min.x, c.min.y, c.min.z);
tess.addVertex(c.min.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.min.z);
tess.addVertex(c.max.x, c.max.y, c.min.z);
tess.addVertex(c.max.x, c.min.y, c.max.z);
tess.addVertex(c.max.x, c.max.y, c.max.z);
tess.addVertex(c.min.x, c.min.y, c.max.z);
tess.addVertex(c.min.x, c.max.y, c.max.z);
tess.draw();
}
public static void renderFluidCuboid(CCRenderState state, Cuboid6 bound, IIcon tex, double res) {
renderFluidQuad( // bottom
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
tex,
res);
renderFluidQuad( // top
new Vector3(bound.min.x, bound.max.y, bound.min.z),
new Vector3(bound.min.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // -x
new Vector3(bound.min.x, bound.max.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
new Vector3(bound.min.x, bound.max.y, bound.max.z),
tex,
res);
renderFluidQuad( // +x
new Vector3(bound.max.x, bound.max.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.max.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // -z
new Vector3(bound.max.x, bound.max.y, bound.min.z),
new Vector3(bound.max.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.min.y, bound.min.z),
new Vector3(bound.min.x, bound.max.y, bound.min.z),
tex,
res);
renderFluidQuad( // +z
new Vector3(bound.min.x, bound.max.y, bound.max.z),
new Vector3(bound.min.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.min.y, bound.max.z),
new Vector3(bound.max.x, bound.max.y, bound.max.z),
tex,
res);
renderFluidCuboid(bound, tex, res);
}
public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) {
renderFluidCuboid(CCRenderState.instance(), bound, tex, res);
final double minX = bound.min.x;
final double minY = bound.min.y;
final double minZ = bound.min.z;
final double maxX = bound.max.x;
final double maxY = bound.max.y;
final double maxZ = bound.max.z;
renderFluidQuad( // bottom
minX, minY, minZ,
maxX - minX, 0, 0,
0, 0, maxZ - minZ,
tex, res);
renderFluidQuad( // top
minX, maxY, minZ,
0, 0, maxZ - minZ,
maxX - minX, 0, 0,
tex, res);
renderFluidQuad( // -x
minX, maxY, minZ,
0, minY - maxY, 0,
0, 0, maxZ - minZ,
tex, res);
renderFluidQuad( // +x
maxX, maxY, maxZ,
0, minY - maxY, 0,
0, 0, minZ - maxZ,
tex, res);
renderFluidQuad( // -z
maxX, maxY, minZ,
0, minY - maxY, 0,
minX - maxX, 0, 0,
tex, res);
renderFluidQuad( // +z
minX, maxY, maxZ,
0, minY - maxY, 0,
maxX - minX, 0, 0,
tex, res);
}
// spotless:on
public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1,
double ty2) {
double[] points = new double[] { x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009 };
Tessellator tessellator = Tessellator.instance;
final double minX = x - 0.009;
final double maxX = x + 1.009;
final double minY = y - 0.009;
final double maxY = y + 1.009;
final double minZ = z - 0.009;
final double maxZ = z + 1.009;
switch (side) {
case 0:
tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2);
tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2);
break;
case 1:
tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty2);
break;
case 2:
tessellator.addVertexWithUV(points[0], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx1, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[4], tx2, ty2);
tessellator.addVertexWithUV(minX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, minZ, tx1, ty2);
tessellator.addVertexWithUV(minX, minY, minZ, tx2, ty2);
break;
case 3:
tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty1);
tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2);
break;
case 4:
tessellator.addVertexWithUV(points[0], points[3], points[5], tx2, ty1);
tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1);
tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty2);
tessellator.addVertexWithUV(points[0], points[2], points[5], tx2, ty2);
tessellator.addVertexWithUV(minX, maxY, maxZ, tx2, ty1);
tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1);
tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty2);
tessellator.addVertexWithUV(minX, minY, maxZ, tx2, ty2);
break;
case 5:
tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1);
tessellator.addVertexWithUV(points[1], points[3], points[5], tx1, ty1);
tessellator.addVertexWithUV(points[1], points[2], points[5], tx1, ty2);
tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty2);
tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1);
tessellator.addVertexWithUV(maxX, maxY, maxZ, tx1, ty1);
tessellator.addVertexWithUV(maxX, minY, maxZ, tx1, ty2);
tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty2);
break;
}
}
@@ -259,7 +301,7 @@ public class RenderUtils {
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
Fluid fluid = stack.getFluid();
state.setColour(fluid.getColor(stack) << 8 | alpha);
state.setColourInstance(fluid.getColor(stack) << 8 | alpha);
TextureUtils.bindAtlas(fluid.getSpriteNumber());
return TextureUtils.safeIcon(fluid.getIcon(stack));
}
@@ -276,66 +318,76 @@ public class RenderUtils {
GL11.glDisable(GL11.GL_BLEND);
}
public static double fluidDensityToAlpha(double density) {
return Math.pow(density, 0.4);
public static double fluidDensityToAlpha(double d) {
return Math.pow(d, 0.4);
}
/**
* Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal
* to density/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to density.
* to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate.
* Warning, bound will be mutated if the fluid is a liquid
*
* @param stack The fluid to render.
* @param bound The box within which the fluid is contained.
* @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids
* this determines the height.
* @param res The resolution to render at.
*
* @param stack The fluid to render.
* @param bound The bounding box within which the fluid is contained.
* @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1.
* @param res The resolution to render at.
*/
public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double density,
public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double fillRate,
double res) {
if (!shouldRenderFluid(stack)) return;
fillRate = MathHelper.clamp_double(fillRate, 0d, 1d);
int alpha = 255;
if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255);
else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density;
if (stack.getFluid().isGaseous()) {
alpha = (int) (fluidDensityToAlpha(fillRate) * 255);
} else {
bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * fillRate;
}
IIcon tex = prepareFluidRender(state, stack, alpha);
state.startDrawing();
renderFluidCuboid(state, bound, tex, res);
state.draw();
state.startDrawingInstance();
renderFluidCuboid(bound, tex, res);
state.drawInstance();
postFluidRender();
}
public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) {
renderFluidCuboid(CCRenderState.instance(), stack, bound, density, res);
/**
* Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal
* to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate.
* Warning, bound will be mutated if the fluid is a liquid
*
* @param stack The fluid to render.
* @param bound The bounding box within which the fluid is contained.
* @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1.
* @param res The resolution to render at.
*/
public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double fillRate, double res) {
renderFluidCuboid(CCRenderState.instance(), stack, bound, fillRate, res);
}
public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double density,
public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double fillRate,
double res) {
if (!shouldRenderFluid(stack)) return;
fillRate = MathHelper.clamp_double(fillRate, 0d, 1d);
int alpha = 255;
if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255);
else {
int height = (int) (rect.h * density);
if (stack.getFluid().isGaseous()) {
alpha = (int) (fluidDensityToAlpha(fillRate) * 255);
} else {
int height = (int) (rect.h * fillRate);
rect.y += rect.h - height;
rect.h = height;
}
IIcon tex = prepareFluidRender(state, stack, alpha);
state.startDrawing();
renderFluidQuad(
new Vector3(rect.x, rect.y + rect.h, 0),
new Vector3(rect.w, 0, 0),
new Vector3(0, -rect.h, 0),
tex,
res);
state.draw();
state.startDrawingInstance();
renderFluidQuad(rect.x, rect.y + rect.h, 0, rect.w, 0, 0, 0, -rect.h, 0, tex, res);
state.drawInstance();
postFluidRender();
}
public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) {
renderFluidGauge(CCRenderState.instance(), stack, rect, density, res);
public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double fillRate, double res) {
renderFluidGauge(CCRenderState.instance(), stack, rect, fillRate, res);
}
/**
@@ -347,7 +399,7 @@ public class RenderUtils {
/**
* Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately
*
*
* @param spin The spin angle of the item around the y axis in degrees
*/
public static void renderItemUniform(ItemStack item, double spin) {
+29 -1
View File
@@ -19,7 +19,10 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
.asDoubleBuffer();
// m<row><column>
public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;
public double m00, m01, m02, m03;
public double m10, m11, m12, m13;
public double m20, m21, m22, m23;
public double m30, m31, m32, m33;
public Matrix4() {
m00 = m11 = m22 = m33 = 1;
@@ -65,6 +68,15 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
return this;
}
public Matrix4 translate(double x, double y, double z) {
m03 += m00 * x + m01 * y + m02 * z;
m13 += m10 * x + m11 * y + m12 * z;
m23 += m20 * x + m21 * y + m22 * z;
m33 += m30 * x + m31 * y + m32 * z;
return this;
}
public Matrix4 scale(Vector3 vec) {
m00 *= vec.x;
m10 *= vec.x;
@@ -82,6 +94,22 @@ public class Matrix4 extends Transformation implements Copyable<Matrix4> {
return this;
}
public Matrix4 scale(double scale) {
m00 *= scale;
m10 *= scale;
m20 *= scale;
m30 *= scale;
m01 *= scale;
m11 *= scale;
m21 *= scale;
m31 *= scale;
m02 *= scale;
m12 *= scale;
m22 *= scale;
m32 *= scale;
return this;
}
public Matrix4 rotate(double angle, Vector3 axis) {
double c = Math.cos(angle);
double s = Math.sin(angle);
@@ -29,10 +29,10 @@ public class Vector3 implements Copyable<Vector3> {
public Vector3() {}
public Vector3(double d, double d1, double d2) {
x = d;
y = d1;
z = d2;
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3(Vector3 vec) {
@@ -398,7 +398,7 @@ public class Vector3 implements Copyable<Vector3> {
/**
* Equals method with tolerance
*
*
* @return true if this is equal to v within +-1E-5
*/
public boolean equalsT(Vector3 v) {