443 lines
18 KiB
Java
443 lines
18 KiB
Java
/*
|
|
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
package net.runelite.cache.item;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.IOException;
|
|
import net.runelite.cache.definitions.ItemDefinition;
|
|
import net.runelite.cache.definitions.ModelDefinition;
|
|
import net.runelite.cache.definitions.providers.ItemProvider;
|
|
import net.runelite.cache.definitions.providers.ModelProvider;
|
|
import net.runelite.cache.definitions.providers.SpriteProvider;
|
|
import net.runelite.cache.definitions.providers.TextureProvider;
|
|
import net.runelite.cache.models.FaceNormal;
|
|
import net.runelite.cache.models.JagexColor;
|
|
import net.runelite.cache.models.VertexNormal;
|
|
|
|
public class ItemSpriteFactory
|
|
{
|
|
public static BufferedImage createSprite(ItemProvider itemProvider, ModelProvider modelProvider,
|
|
SpriteProvider spriteProvider, TextureProvider textureProvider,
|
|
int itemId, int quantity, int border, int shadowColor,
|
|
boolean noted) throws IOException
|
|
{
|
|
SpritePixels spritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider,
|
|
itemId, quantity, border, shadowColor, noted);
|
|
return spritePixels == null ? null : spritePixels.toBufferedImage();
|
|
}
|
|
|
|
private static SpritePixels createSpritePixels(ItemProvider itemProvider, ModelProvider modelProvider,
|
|
SpriteProvider spriteProvider, TextureProvider textureProvider,
|
|
int itemId, int quantity, int border, int shadowColor,
|
|
boolean noted) throws IOException
|
|
{
|
|
ItemDefinition item = itemProvider.provide(itemId);
|
|
|
|
if (quantity > 1 && item.countObj != null)
|
|
{
|
|
int stackItemID = -1;
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
if (quantity >= item.countCo[i] && item.countCo[i] != 0)
|
|
{
|
|
stackItemID = item.countObj[i];
|
|
}
|
|
}
|
|
|
|
if (stackItemID != -1)
|
|
{
|
|
item = itemProvider.provide(stackItemID);
|
|
}
|
|
}
|
|
|
|
Model itemModel = getModel(modelProvider, item);
|
|
if (itemModel == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
SpritePixels auxSpritePixels = null;
|
|
if (item.notedTemplate != -1)
|
|
{
|
|
auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider,
|
|
item.notedID, 10, 1, 0, true);
|
|
if (auxSpritePixels == null)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
else if (item.boughtTemplateId != -1)
|
|
{
|
|
auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider,
|
|
item.boughtId, quantity, border, 0, false);
|
|
if (auxSpritePixels == null)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
else if (item.placeholderTemplateId != -1)
|
|
{
|
|
auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider,
|
|
item.placeholderId, quantity, 0, 0, false);
|
|
if (auxSpritePixels == null)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
RSTextureProvider rsTextureProvider = new RSTextureProvider(textureProvider, spriteProvider);
|
|
|
|
int width = 36 * 2;
|
|
int height = 32 * 2;
|
|
SpritePixels spritePixels = new SpritePixels(width, height);
|
|
Graphics3D graphics = new Graphics3D(rsTextureProvider);
|
|
graphics.setBrightness(JagexColor.BRIGHTNESS_MAX);
|
|
graphics.setRasterBuffer(spritePixels.pixels, width, height);
|
|
graphics.reset();
|
|
graphics.setRasterClipping();
|
|
graphics.setOffset(16 * 2, 16 * 2);
|
|
graphics.rasterGouraudLowRes = false;
|
|
if (item.placeholderTemplateId != -1)
|
|
{
|
|
auxSpritePixels.drawAtOn(graphics, 0, 0);
|
|
}
|
|
|
|
int zoom2d;
|
|
// The holy symbol item for some reason needs a different zoom value otherwise it gets cut off
|
|
if (itemId == 1716 || itemId == 1718) {
|
|
zoom2d = (int) (((double) item.zoom2d) / 1.5D);
|
|
} else {
|
|
zoom2d = (int) (((double) item.zoom2d) / 1.95D);
|
|
}
|
|
|
|
if (noted)
|
|
{
|
|
zoom2d = (int) ((double) zoom2d * 1.5D);
|
|
}
|
|
else if (border == 2)
|
|
{
|
|
zoom2d = (int) ((double) zoom2d * 1.04D);
|
|
}
|
|
|
|
int var17 = zoom2d * Graphics3D.SINE[item.xan2d] >> 16;
|
|
int var18 = zoom2d * Graphics3D.COSINE[item.xan2d] >> 16;
|
|
|
|
itemModel.calculateBoundsCylinder();
|
|
itemModel.projectAndDraw(graphics, 0,
|
|
item.yan2d,
|
|
item.zan2d,
|
|
item.xan2d,
|
|
item.xOffset2d,
|
|
itemModel.modelHeight / 2 + var17 + item.yOffset2d,
|
|
var18 + item.yOffset2d);
|
|
if (item.boughtTemplateId != -1)
|
|
{
|
|
auxSpritePixels.drawAtOn(graphics, 0, 0);
|
|
}
|
|
|
|
if (border >= 1)
|
|
{
|
|
spritePixels.drawBorder(1);
|
|
}
|
|
|
|
if (border >= 2)
|
|
{
|
|
spritePixels.drawBorder(0xffffff);
|
|
}
|
|
|
|
if (shadowColor != 0)
|
|
{
|
|
spritePixels.drawShadow(shadowColor);
|
|
}
|
|
|
|
graphics.setRasterBuffer(spritePixels.pixels, width, height);
|
|
if (item.notedTemplate != -1)
|
|
{
|
|
auxSpritePixels.drawAtOn(graphics, 0, 0);
|
|
}
|
|
|
|
graphics.setRasterBuffer(graphics.graphicsPixels,
|
|
graphics.graphicsPixelsWidth,
|
|
graphics.graphicsPixelsHeight);
|
|
|
|
graphics.setRasterClipping();
|
|
graphics.rasterGouraudLowRes = true;
|
|
return spritePixels;
|
|
}
|
|
|
|
private static Model getModel(ModelProvider modelProvider, ItemDefinition item) throws IOException
|
|
{
|
|
Model itemModel;
|
|
ModelDefinition inventoryModel = modelProvider.provide(item.inventoryModel);
|
|
if (inventoryModel == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (item.resizeX != 128 || item.resizeY != 128 || item.resizeZ != 128)
|
|
{
|
|
inventoryModel.resize(item.resizeX, item.resizeY, item.resizeZ);
|
|
}
|
|
|
|
if (item.colorFind != null)
|
|
{
|
|
for (int i = 0; i < item.colorFind.length; ++i)
|
|
{
|
|
inventoryModel.recolor(item.colorFind[i], item.colorReplace[i]);
|
|
}
|
|
}
|
|
|
|
if (item.textureFind != null)
|
|
{
|
|
for (int i = 0; i < item.textureFind.length; ++i)
|
|
{
|
|
inventoryModel.retexture(item.textureFind[i], item.textureReplace[i]);
|
|
}
|
|
}
|
|
|
|
itemModel = light(inventoryModel, item.ambient + 64, item.contrast + 768, -50, -10, -50);
|
|
return itemModel;
|
|
}
|
|
|
|
private static Model light(ModelDefinition def, int ambient, int contrast, int x, int y, int z)
|
|
{
|
|
def.computeNormals();
|
|
int somethingMagnitude = (int) Math.sqrt((double) (z * z + x * x + y * y));
|
|
int var7 = somethingMagnitude * contrast >> 8;
|
|
Model litModel = new Model();
|
|
litModel.faceColors1 = new int[def.faceCount];
|
|
litModel.faceColors2 = new int[def.faceCount];
|
|
litModel.faceColors3 = new int[def.faceCount];
|
|
if (def.numTextureFaces > 0 && def.textureCoords != null)
|
|
{
|
|
int[] var9 = new int[def.numTextureFaces];
|
|
|
|
int var10;
|
|
for (var10 = 0; var10 < def.faceCount; ++var10)
|
|
{
|
|
if (def.textureCoords[var10] != -1)
|
|
{
|
|
++var9[def.textureCoords[var10] & 255];
|
|
}
|
|
}
|
|
|
|
litModel.numTextureFaces = 0;
|
|
|
|
for (var10 = 0; var10 < def.numTextureFaces; ++var10)
|
|
{
|
|
if (var9[var10] > 0 && def.textureRenderTypes[var10] == 0)
|
|
{
|
|
++litModel.numTextureFaces;
|
|
}
|
|
}
|
|
|
|
litModel.texIndices1 = new int[litModel.numTextureFaces];
|
|
litModel.texIndices2 = new int[litModel.numTextureFaces];
|
|
litModel.texIndices3 = new int[litModel.numTextureFaces];
|
|
var10 = 0;
|
|
|
|
|
|
for (int i = 0; i < def.numTextureFaces; ++i)
|
|
{
|
|
if (var9[i] > 0 && def.textureRenderTypes[i] == 0)
|
|
{
|
|
litModel.texIndices1[var10] = def.texIndices1[i] & '\uffff';
|
|
litModel.texIndices2[var10] = def.texIndices2[i] & '\uffff';
|
|
litModel.texIndices3[var10] = def.texIndices3[i] & '\uffff';
|
|
var9[i] = var10++;
|
|
}
|
|
else
|
|
{
|
|
var9[i] = -1;
|
|
}
|
|
}
|
|
|
|
litModel.textureCoords = new byte[def.faceCount];
|
|
|
|
for (int i = 0; i < def.faceCount; ++i)
|
|
{
|
|
if (def.textureCoords[i] != -1)
|
|
{
|
|
litModel.textureCoords[i] = (byte) var9[def.textureCoords[i] & 255];
|
|
}
|
|
else
|
|
{
|
|
litModel.textureCoords[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int faceIdx = 0; faceIdx < def.faceCount; ++faceIdx)
|
|
{
|
|
byte faceType;
|
|
if (def.faceRenderTypes == null)
|
|
{
|
|
faceType = 0;
|
|
}
|
|
else
|
|
{
|
|
faceType = def.faceRenderTypes[faceIdx];
|
|
}
|
|
|
|
byte faceAlpha;
|
|
if (def.faceTransparencies == null)
|
|
{
|
|
faceAlpha = 0;
|
|
}
|
|
else
|
|
{
|
|
faceAlpha = def.faceTransparencies[faceIdx];
|
|
}
|
|
|
|
short faceTexture;
|
|
if (def.faceTextures == null)
|
|
{
|
|
faceTexture = -1;
|
|
}
|
|
else
|
|
{
|
|
faceTexture = def.faceTextures[faceIdx];
|
|
}
|
|
|
|
if (faceAlpha == -2)
|
|
{
|
|
faceType = 3;
|
|
}
|
|
|
|
if (faceAlpha == -1)
|
|
{
|
|
faceType = 2;
|
|
}
|
|
|
|
VertexNormal vertexNormal;
|
|
int tmp;
|
|
FaceNormal faceNormal;
|
|
if (faceTexture == -1)
|
|
{
|
|
if (faceType != 0)
|
|
{
|
|
if (faceType == 1)
|
|
{
|
|
faceNormal = def.faceNormals[faceIdx];
|
|
tmp = (y * faceNormal.y + z * faceNormal.z + x * faceNormal.x) / (var7 / 2 + var7) + ambient;
|
|
litModel.faceColors1[faceIdx] = method2608(def.faceColors[faceIdx] & '\uffff', tmp);
|
|
litModel.faceColors3[faceIdx] = -1;
|
|
}
|
|
else if (faceType == 3)
|
|
{
|
|
litModel.faceColors1[faceIdx] = 128;
|
|
litModel.faceColors3[faceIdx] = -1;
|
|
}
|
|
else
|
|
{
|
|
litModel.faceColors3[faceIdx] = -2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int var15 = def.faceColors[faceIdx] & '\uffff';
|
|
vertexNormal = def.vertexNormals[def.faceIndices1[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors1[faceIdx] = method2608(var15, tmp);
|
|
vertexNormal = def.vertexNormals[def.faceIndices2[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors2[faceIdx] = method2608(var15, tmp);
|
|
vertexNormal = def.vertexNormals[def.faceIndices3[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors3[faceIdx] = method2608(var15, tmp);
|
|
}
|
|
}
|
|
else if (faceType != 0)
|
|
{
|
|
if (faceType == 1)
|
|
{
|
|
faceNormal = def.faceNormals[faceIdx];
|
|
tmp = (y * faceNormal.y + z * faceNormal.z + x * faceNormal.x) / (var7 / 2 + var7) + ambient;
|
|
litModel.faceColors1[faceIdx] = bound2to126(tmp);
|
|
litModel.faceColors3[faceIdx] = -1;
|
|
}
|
|
else
|
|
{
|
|
litModel.faceColors3[faceIdx] = -2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vertexNormal = def.vertexNormals[def.faceIndices1[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors1[faceIdx] = bound2to126(tmp);
|
|
vertexNormal = def.vertexNormals[def.faceIndices2[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors2[faceIdx] = bound2to126(tmp);
|
|
vertexNormal = def.vertexNormals[def.faceIndices3[faceIdx]];
|
|
|
|
tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient;
|
|
litModel.faceColors3[faceIdx] = bound2to126(tmp);
|
|
}
|
|
}
|
|
|
|
litModel.verticesCount = def.vertexCount;
|
|
litModel.verticesX = def.vertexX;
|
|
litModel.verticesY = def.vertexY;
|
|
litModel.verticesZ = def.vertexZ;
|
|
litModel.indicesCount = def.faceCount;
|
|
litModel.indices1 = def.faceIndices1;
|
|
litModel.indices2 = def.faceIndices2;
|
|
litModel.indices3 = def.faceIndices3;
|
|
litModel.facePriorities = def.faceRenderPriorities;
|
|
litModel.faceTransparencies = def.faceTransparencies;
|
|
litModel.faceTextures = def.faceTextures;
|
|
return litModel;
|
|
}
|
|
|
|
static int method2608(int var0, int var1)
|
|
{
|
|
var1 = ((var0 & 127) * var1) >> 7;
|
|
var1 = bound2to126(var1);
|
|
|
|
return (var0 & 65408) + var1;
|
|
}
|
|
|
|
static int bound2to126(int var0)
|
|
{
|
|
if (var0 < 2)
|
|
{
|
|
var0 = 2;
|
|
}
|
|
else if (var0 > 126)
|
|
{
|
|
var0 = 126;
|
|
}
|
|
|
|
return var0;
|
|
}
|
|
}
|