ForgePatch/src/main/java/net/minecraftforge/client/model/QuadTransformer.java

201 lines
7.0 KiB
Java
Raw Normal View History

/*
* Minecraft Forge
* Copyright (c) 2016-2019.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.client.model;
import com.google.common.collect.Lists;
import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import javax.vecmath.Vector3f;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class QuadTransformer
{
private final VertexFormat format;
private final int positionOffset;
private final int normalOffset;
private final TransformationMatrix transform;
public QuadTransformer(VertexFormat format, TransformationMatrix transform)
{
this.format = format;
this.positionOffset = findPositionOffset(format);
this.normalOffset = findNormalOffset(format);
this.transform = transform;
}
private void processVertices(int[] inData, int[] outData)
{
// TODO: Extract rotation matrix and fix NORMALs if present.
int stride = format.getSize() / 4;
for (int i=0;i<4;i++)
{
int offset = positionOffset + i * stride;
float x = Float.intBitsToFloat(inData[offset ]);
float y = Float.intBitsToFloat(inData[offset + 1]);
float z = Float.intBitsToFloat(inData[offset + 2]);
Vector4f pos = new Vector4f(x, y, z, 1);
transform.transformPosition(pos);
pos.func_229374_e_();
outData[offset] = Float.floatToRawIntBits(pos.getX());
outData[offset + 1] = Float.floatToRawIntBits(pos.getY());
outData[offset + 2] = Float.floatToRawIntBits(pos.getZ());
}
if (normalOffset >= 0)
{
for (int i=0;i<4;i++)
{
int offset = normalOffset + i * stride;
int normalIn = inData[offset];
float x = (((normalIn)>>24)&0xFF)/255.0f;
float y = (((normalIn<<8)>>24)&0xFF)/255.0f;
float z = (((normalIn<<16)>>24)&0xFF)/255.0f;
Vector3f pos = new Vector3f(x, y, z);
transform.transformNormal(pos);
int normalOut =
(((int)(x/255.0)&0xFF)<<24) |
(((int)(y/255.0)&0xFF)<<16) |
(((int)(z/255.0)&0xFF)<<8) |
(normalIn&0xFF);
outData[offset] = normalOut;
}
}
}
private static int findPositionOffset(VertexFormat fmt)
{
int index;
VertexFormatElement element = null;
for (index = 0; index < fmt.func_227894_c_().size(); index++)
{
VertexFormatElement el = fmt.func_227894_c_().get(index);
if (el.getUsage() == VertexFormatElement.Usage.POSITION)
{
element = el;
break;
}
}
if (index == fmt.func_227894_c_().size() || element == null)
throw new RuntimeException("Expected vertex format to have a POSITION attribute");
if (element.getType() != VertexFormatElement.Type.FLOAT)
throw new RuntimeException("Expected POSITION attribute to have data type FLOAT");
if (element.getSize() < 3)
throw new RuntimeException("Expected POSITION attribute to have at least 3 dimensions");
return fmt.getOffset(index);
}
private static int findNormalOffset(VertexFormat fmt)
{
int index;
VertexFormatElement element = null;
for (index = 0; index < fmt.func_227894_c_().size(); index++)
{
VertexFormatElement el = fmt.func_227894_c_().get(index);
if (el.getUsage() == VertexFormatElement.Usage.NORMAL)
{
element = el;
break;
}
}
if (index == fmt.func_227894_c_().size() || element == null)
return -1;
if (element.getType() != VertexFormatElement.Type.BYTE)
throw new RuntimeException("Expected NORMAL attribute to have data type BYTE");
if (element.getSize() < 3)
throw new RuntimeException("Expected NORMAL attribute to have at least 3 dimensions");
return fmt.getOffset(index);
}
/**
* Processes a single quad, producing a new quad.
* @param input A single quad to transform.
* @return A new BakedQuad object with the new position.
*/
public BakedQuad processOne(BakedQuad input)
{
int[] inData = input.getVertexData();
int[] outData = Arrays.copyOf(inData, inData.length);
processVertices(inData, outData);
return new BakedQuad(outData, input.getTintIndex(), input.getFace(), input.getSprite(), input.shouldApplyDiffuseLighting(), format);
}
/**
* Processes a single quad, modifying the input quad.
* @param input A single quad to transform.
* @return The input BakedQuad object with the new position applied.
*/
public BakedQuad processOneInPlace(BakedQuad input)
{
int[] data = input.getVertexData();
processVertices(data, data);
return input;
}
/**
* Processes multiple quads, producing a new array of new quads.
* @param inputs The list of quads to transform
* @return A new array of new BakedQuad objects.
*/
public List<BakedQuad> processMany(List<BakedQuad> inputs)
{
if(inputs.size() == 0)
return Collections.emptyList();
List<BakedQuad> outputs = Lists.newArrayList();
for(BakedQuad input : inputs)
{
int[] inData = input.getVertexData();
int[] outData = Arrays.copyOf(inData, inData.length);
processVertices(inData, outData);
outputs.add(new BakedQuad(outData, input.getTintIndex(), input.getFace(), input.getSprite(), input.shouldApplyDiffuseLighting(), format));
}
return outputs;
}
/**
* Processes multiple quads in place, modifying the input quads.
* @param inputs The list of quads to transform
*/
public void processManyInPlace(List<BakedQuad> inputs)
{
if(inputs.size() == 0)
return;
for(BakedQuad input : inputs)
{
int[] data = input.getVertexData();
processVertices(data, data);
}
}
}