mirror of
https://github.com/GTNewHorizons/CodeChickenCore.git
synced 2026-11-15 01:24:58 +00:00
Initial 1.7 commit
This commit is contained in:
1 parent
34154fc011
commit
ca675b5f31
72 files changed
+2967
-3335
No files matched your search
@@ -1,147 +1,383 @@
|
||||
package codechicken.lib.render;
|
||||
|
||||
import codechicken.lib.colour.ColourRGBA;
|
||||
import net.minecraft.block.Block;
|
||||
import codechicken.lib.lighting.LC;
|
||||
import codechicken.lib.lighting.LightMatrix;
|
||||
import codechicken.lib.util.Copyable;
|
||||
import codechicken.lib.vec.Rotation;
|
||||
import codechicken.lib.vec.Transformation;
|
||||
import codechicken.lib.vec.Vector3;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The core of the CodeChickenLib render system.
|
||||
* Rendering operations are written to avoid object allocations by reusing static variables.
|
||||
*/
|
||||
public class CCRenderState
|
||||
{
|
||||
private static boolean useNormals;
|
||||
private static boolean hasBrightness;
|
||||
private static int brightness;
|
||||
private static boolean useModelColours;
|
||||
private static int colour;
|
||||
private static boolean hasColour;
|
||||
private static int alpha;
|
||||
private static boolean alphaOverride;
|
||||
|
||||
public static void useNormals(boolean b)
|
||||
{
|
||||
useNormals = b;
|
||||
}
|
||||
|
||||
public static boolean useNormals()
|
||||
{
|
||||
return useNormals;
|
||||
}
|
||||
|
||||
public static void useModelColours(boolean b)
|
||||
{
|
||||
useModelColours = b;
|
||||
{
|
||||
private static int nextOperationIndex;
|
||||
|
||||
public static int registerOperation() {
|
||||
return nextOperationIndex++;
|
||||
}
|
||||
|
||||
public static boolean useModelColours()
|
||||
{
|
||||
return useModelColours;
|
||||
}
|
||||
|
||||
public static void setAlpha(int a)
|
||||
{
|
||||
alpha = a;
|
||||
alphaOverride = true;
|
||||
}
|
||||
|
||||
public static void clearAlphaOverride()
|
||||
{
|
||||
alphaOverride = false;
|
||||
}
|
||||
|
||||
public static void vertexColour(int c)
|
||||
{
|
||||
if(alphaOverride)
|
||||
setColour(c&0xFFFFFF00|alpha);
|
||||
else
|
||||
setColour(c);
|
||||
public static int operationCount() {
|
||||
return nextOperationIndex;
|
||||
}
|
||||
|
||||
public static void vertexColour(int r, int g, int b, int a)
|
||||
/**
|
||||
* Represents an operation to be run for each vertex that operates on and modifies the current state
|
||||
*/
|
||||
public static interface IVertexOperation
|
||||
{
|
||||
if(alphaOverride)
|
||||
Tessellator.instance.setColorRGBA(r, g, b, alpha);
|
||||
else
|
||||
Tessellator.instance.setColorRGBA(r, g, b, a);
|
||||
}
|
||||
|
||||
public static void setBrightness(IBlockAccess world, int x, int y, int z)
|
||||
{
|
||||
Block block = Block.blocksList[world.getBlockId(x, y, z)];
|
||||
setBrightness(block == null ? world.getLightBrightnessForSkyBlocks(x, y, z, 0) : block.getMixedBrightnessForBlock(world, x, y, z));
|
||||
setColour(0xFFFFFFFF);
|
||||
/**
|
||||
* Load any required references and add dependencies to the pipeline based on the current model (may be null)
|
||||
* Return false if this operation is redundant in the pipeline with the given model
|
||||
*/
|
||||
public boolean load();
|
||||
|
||||
/**
|
||||
* Perform the operation on the current render state
|
||||
*/
|
||||
public void operate();
|
||||
|
||||
/**
|
||||
* Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have unexpected results.
|
||||
* ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static variable
|
||||
*/
|
||||
public int operationID();
|
||||
}
|
||||
|
||||
public static void setBrightness(int b)
|
||||
{
|
||||
hasBrightness = true;
|
||||
Tessellator.instance.setBrightness(brightness = b);
|
||||
}
|
||||
|
||||
public static void setColourOpaque(int c)
|
||||
{
|
||||
setColour(c << 8 | 0xFF);
|
||||
}
|
||||
|
||||
//RGBA
|
||||
public static void setColour(int c)
|
||||
{
|
||||
hasColour = true;
|
||||
colour = c;
|
||||
Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF);
|
||||
}
|
||||
|
||||
public static void changeTexture(String texture)
|
||||
{
|
||||
changeTexture(new ResourceLocation(texture));
|
||||
}
|
||||
|
||||
public static void changeTexture(ResourceLocation texture)
|
||||
{
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
|
||||
private static ArrayList<VertexAttribute<?>> vertexAttributes = new ArrayList<VertexAttribute<?>>();
|
||||
private static int registerVertexAttribute(VertexAttribute<?> attr) {
|
||||
vertexAttributes.add(attr);
|
||||
return vertexAttributes.size()-1;
|
||||
}
|
||||
|
||||
public static void apply()
|
||||
public static VertexAttribute<?> getAttribute(int index) {
|
||||
return vertexAttributes.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 static abstract class VertexAttribute<T> implements IVertexOperation
|
||||
{
|
||||
public final int attributeIndex = registerVertexAttribute(this);
|
||||
private final int operationIndex = registerOperation();
|
||||
/**
|
||||
* Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when constructing the pipeline
|
||||
*/
|
||||
public boolean active = false;
|
||||
|
||||
/**
|
||||
* Construct a new array for storage of vertex attrutes in a model
|
||||
*/
|
||||
public abstract T newArray(int length);
|
||||
|
||||
@Override
|
||||
public int operationID() {
|
||||
return operationIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public static void arrayCopy(Object src, int srcPos, Object dst, int destPos, int length) {
|
||||
System.arraycopy(src, srcPos, dst, destPos, length);
|
||||
if(dst instanceof Copyable[]) {
|
||||
Object[] oa = (Object[])dst;
|
||||
Copyable<Object>[] c = (Copyable[])dst;
|
||||
for(int i = destPos; i < destPos+length; i++)
|
||||
if(c[i] != null)
|
||||
oa[i] = c[i].copy();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T copyOf(VertexAttribute<T> attr, T src, int length) {
|
||||
T dst = attr.newArray(length);
|
||||
arrayCopy(src, 0, dst, 0, length);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public static interface IVertexSource
|
||||
{
|
||||
public Vertex5[] getVertices();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public <T> T getAttributes(VertexAttribute<T> attr);
|
||||
|
||||
/**
|
||||
* @return True if the specified attrute is provided by this model, either by returning an array from getAttributes or by setting the state in prepareVertex
|
||||
*/
|
||||
public boolean hasAttribute(VertexAttribute<?> attr);
|
||||
|
||||
/**
|
||||
* Callback to set CCRenderState for a vertex before the pipeline runs
|
||||
*/
|
||||
public void prepareVertex();
|
||||
}
|
||||
|
||||
public static VertexAttribute<Vector3[]> normalAttrib = new VertexAttribute<Vector3[]>() {
|
||||
private Vector3[] normalRef;
|
||||
|
||||
@Override
|
||||
public Vector3[] newArray(int length) {
|
||||
return new Vector3[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load() {
|
||||
normalRef = model.getAttributes(this);
|
||||
if(model.hasAttribute(this))
|
||||
return normalRef != null;
|
||||
|
||||
if(model.hasAttribute(sideAttrib)) {
|
||||
pipeline.addDependency(sideAttrib);
|
||||
return true;
|
||||
}
|
||||
throw new IllegalStateException("Normals requested but neither normal or side attrutes are provided by the model");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate() {
|
||||
if(normalRef != null)
|
||||
setNormal(normalRef[vertexIndex]);
|
||||
else
|
||||
setNormal(Rotation.axes[side]);
|
||||
}
|
||||
};
|
||||
public static VertexAttribute<int[]> colourAttrib = new VertexAttribute<int[]>() {
|
||||
private int[] colourRef;
|
||||
|
||||
@Override
|
||||
public int[] newArray(int length) {
|
||||
return new int[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load() {
|
||||
colourRef = model.getAttributes(this);
|
||||
return colourRef != null || !model.hasAttribute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate() {
|
||||
if(colourRef != null)
|
||||
setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex]));
|
||||
else
|
||||
setColour(baseColour);
|
||||
}
|
||||
};
|
||||
public static VertexAttribute<int[]> sideAttrib = new VertexAttribute<int[]>() {
|
||||
private int[] sideRef;
|
||||
|
||||
@Override
|
||||
public int[] newArray(int length) {
|
||||
return new int[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load() {
|
||||
sideRef = model.getAttributes(this);
|
||||
if(model.hasAttribute(this))
|
||||
return sideRef != null;
|
||||
|
||||
pipeline.addDependency(normalAttrib);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate() {
|
||||
if(sideRef != null)
|
||||
side = sideRef[vertexIndex];
|
||||
else
|
||||
side = CCModel.findSide(normal);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Uses the position of the lightmatrix to compute LC if not provided
|
||||
*/
|
||||
public static VertexAttribute<LC[]> lightCoordAttrib = new VertexAttribute<LC[]>() {
|
||||
private LC[] lcRef;
|
||||
private Vector3 vec = new Vector3();//for computation
|
||||
private Vector3 pos = new Vector3();
|
||||
|
||||
@Override
|
||||
public LC[] newArray(int length) {
|
||||
return new LC[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load() {
|
||||
lcRef = model.getAttributes(this);
|
||||
if(model.hasAttribute(this))
|
||||
return lcRef != null;
|
||||
|
||||
pos.set(lightMatrix.pos.x, lightMatrix.pos.y, lightMatrix.pos.z);
|
||||
pipeline.addDependency(sideAttrib);
|
||||
pipeline.addRequirement(Transformation.operationIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate() {
|
||||
if(lcRef != null)
|
||||
lc.set(lcRef[vertexIndex]);
|
||||
else
|
||||
lc.compute(vec.set(vert.vec).sub(pos), side);
|
||||
}
|
||||
};
|
||||
|
||||
//pipeline state
|
||||
public static IVertexSource model;
|
||||
public static int firstVertexIndex;
|
||||
public static int lastVertexIndex;
|
||||
public static int vertexIndex;
|
||||
public static CCRenderPipeline pipeline = new CCRenderPipeline();
|
||||
|
||||
//context
|
||||
public static int baseColour;
|
||||
public static int alphaOverride;
|
||||
public static boolean useNormals;
|
||||
public static LightMatrix lightMatrix = new LightMatrix();
|
||||
|
||||
//vertex outputs
|
||||
public static Vertex5 vert = new Vertex5();
|
||||
public static boolean hasNormal;
|
||||
public static Vector3 normal = new Vector3();
|
||||
public static boolean hasColour;
|
||||
public static int colour;
|
||||
public static boolean hasBrightness;
|
||||
public static int brightness;
|
||||
|
||||
//attrute storage
|
||||
public static int side;
|
||||
public static LC lc = new LC();
|
||||
|
||||
public static void reset() {
|
||||
model = null;
|
||||
pipeline.reset();
|
||||
hasNormal = hasColour = hasBrightness = false;
|
||||
baseColour = alphaOverride = -1;
|
||||
}
|
||||
|
||||
public static void setPipeline(IVertexOperation... ops) {
|
||||
pipeline.setPipeline(ops);
|
||||
}
|
||||
|
||||
public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) {
|
||||
pipeline.reset();
|
||||
setModel(model, start, end);
|
||||
pipeline.setPipeline(ops);
|
||||
}
|
||||
|
||||
public static void bindModel(IVertexSource model) {
|
||||
if(CCRenderState.model != model) {
|
||||
CCRenderState.model = model;
|
||||
pipeline.rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setModel(IVertexSource source) {
|
||||
setModel(source, 0, source.getVertices().length);
|
||||
}
|
||||
|
||||
public static void setModel(IVertexSource source, int start, int end) {
|
||||
bindModel(source);
|
||||
firstVertexIndex = start;
|
||||
lastVertexIndex = end;
|
||||
}
|
||||
|
||||
public static void render(IVertexOperation... ops) {
|
||||
setPipeline(ops);
|
||||
render();
|
||||
}
|
||||
|
||||
public static void render() {
|
||||
Vertex5[] verts = model.getVertices();
|
||||
for(vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) {
|
||||
model.prepareVertex();
|
||||
vert.set(verts[vertexIndex]);
|
||||
runPipeline();
|
||||
writeVert();
|
||||
}
|
||||
}
|
||||
|
||||
public static void runPipeline() {
|
||||
pipeline.operate();
|
||||
}
|
||||
|
||||
public static void writeVert() {
|
||||
if(hasNormal)
|
||||
Tessellator.instance.setNormal((float)normal.x, (float)normal.y, (float)normal.z);
|
||||
if(hasColour)
|
||||
Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF);
|
||||
if(hasBrightness)
|
||||
Tessellator.instance.setBrightness(brightness);
|
||||
if(hasColour)
|
||||
Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF);
|
||||
Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v);
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
hasBrightness = false;
|
||||
useModelColours = false;
|
||||
hasColour = false;
|
||||
alphaOverride = false;
|
||||
useNormals = false;
|
||||
public static void setNormal(double x, double y, double z) {
|
||||
hasNormal = true;
|
||||
normal.set(x, y, z);
|
||||
}
|
||||
|
||||
public static void startDrawing(int i)
|
||||
{
|
||||
Tessellator.instance.startDrawing(i);
|
||||
apply();
|
||||
public static void setNormal(Vector3 n) {
|
||||
hasNormal = true;
|
||||
normal.set(n);
|
||||
}
|
||||
|
||||
public static void draw()
|
||||
{
|
||||
Tessellator.instance.draw();
|
||||
public static void setColour(int c) {
|
||||
hasColour = true;
|
||||
colour = c;
|
||||
}
|
||||
|
||||
public static void pullLightmap()
|
||||
{
|
||||
public static void setBrightness(int b) {
|
||||
hasBrightness = true;
|
||||
brightness = b;
|
||||
}
|
||||
|
||||
public static void setBrightness(IBlockAccess world, int x, int y, int z) {
|
||||
setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z));
|
||||
}
|
||||
|
||||
public static void pullLightmap() {
|
||||
setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX);
|
||||
}
|
||||
|
||||
public static void applyBrightnessTexCoords()
|
||||
{
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness&0xFFFF, brightness>>>16);
|
||||
public static void changeTexture(String texture) {
|
||||
changeTexture(new ResourceLocation(texture));
|
||||
}
|
||||
|
||||
public static void glColour()
|
||||
{
|
||||
new ColourRGBA(colour).glColour();
|
||||
public static void changeTexture(ResourceLocation texture) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
|
||||
}
|
||||
|
||||
public static void startDrawing() {
|
||||
startDrawing(7);
|
||||
}
|
||||
|
||||
private static void startDrawing(int mode) {
|
||||
Tessellator.instance.startDrawing(mode);
|
||||
if(hasColour)
|
||||
Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF);
|
||||
if(hasBrightness)
|
||||
Tessellator.instance.setBrightness(brightness);
|
||||
}
|
||||
|
||||
public static void draw() {
|
||||
Tessellator.instance.draw();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user