mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Merge branch 'blasphemy' into experimental
This commit is contained in:
commit
a93618dc32
@ -821,6 +821,12 @@ public class WarsmashGdxFDFTestRenderScreen implements InputProcessor, Screen, S
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceableTextureHD(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LibGDXContentLayerModel extends Model {
|
||||
|
@ -452,6 +452,12 @@ public class WarsmashGdxMapScreen implements InputProcessor, Screen {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceableTextureHD(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LibGDXContentLayerModel extends Model {
|
||||
|
@ -857,6 +857,12 @@ public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleMode
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceableTextureHD(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LibGDXContentLayerModel extends Model {
|
||||
|
@ -3112,48 +3112,6 @@ public class Jass2 {
|
||||
throw new JassException(globalScope, "Needs to sleep " + time, null);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerNeutralAggressive", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 4);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJPlayerNeutralVictim", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 3);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJPlayerNeutralExtra", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 2);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerNeutralPassive", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 1);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJMaxPlayers", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 4);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJMaxPlayerSlots", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("AddSpecialEffectTarget", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
@ -4890,6 +4848,49 @@ public class Jass2 {
|
||||
return new IntegerJassValue(whichPlayer.getId());
|
||||
}
|
||||
});
|
||||
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerNeutralAggressive", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 4);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJPlayerNeutralVictim", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 3);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJPlayerNeutralExtra", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 2);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerNeutralPassive", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 1);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJMaxPlayers", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS - 4);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetBJMaxPlayerSlots", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new IntegerJassValue(WarsmashConstants.MAX_PLAYERS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void registerTypingNatives(final JassProgramVisitor jassProgramVisitor, final HandleJassType raceType,
|
||||
|
@ -38,7 +38,7 @@ public class Camera {
|
||||
/**
|
||||
* World -> View.
|
||||
*/
|
||||
private final Matrix4 viewMatrix;
|
||||
public final Matrix4 viewMatrix;
|
||||
/**
|
||||
* View -> Clip.
|
||||
*/
|
||||
|
@ -225,5 +225,7 @@ public abstract class ModelInstance extends Node {
|
||||
|
||||
public abstract void setReplaceableTexture(int replaceableTextureId, String replaceableTextureFile);
|
||||
|
||||
public abstract void setReplaceableTextureHD(int replaceableTextureId, String replaceableTextureFile);
|
||||
|
||||
protected abstract void removeLights(Scene scene2);
|
||||
}
|
||||
|
@ -22,6 +22,63 @@ public class Shaders {
|
||||
" texture2D(u_boneMap, vec2(column + u_vectorSize * 2.0, row)),\r\n" + //
|
||||
" texture2D(u_boneMap, vec2(column + u_vectorSize * 3.0, row)));\r\n" + //
|
||||
" }";
|
||||
public static final String transforms = "#ifdef SKIN\r\n" + //
|
||||
"attribute vec4 a_bones;\r\n" + //
|
||||
"attribute vec4 a_weights;\r\n" + //
|
||||
"void transformSkin(inout vec3 position, inout vec3 normal, inout vec3 tangent, inout vec3 binormal) {\r\n"
|
||||
+ //
|
||||
" mat4 bone = mat4(0);\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[0], 0.0) * a_weights[0];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[1], 0.0) * a_weights[1];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[2], 0.0) * a_weights[2];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[3], 0.0) * a_weights[3];\r\n" + //
|
||||
" mat3 rotation = mat3(bone);\r\n" + //
|
||||
" position = vec3(bone * vec4(position, 1.0));\r\n" + //
|
||||
" normal = rotation * normal;\r\n" + //
|
||||
" tangent = rotation * tangent;\r\n" + //
|
||||
" binormal = rotation * binormal;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"#else\r\n" + //
|
||||
"attribute vec4 a_bones;\r\n" + //
|
||||
"#ifdef EXTENDED_BONES\r\n" + //
|
||||
"attribute vec4 a_extendedBones;\r\n" + //
|
||||
"#endif\r\n" + //
|
||||
"attribute float a_boneNumber;\r\n" + //
|
||||
"mat4 getVertexGroupMatrix() {\r\n" + //
|
||||
" mat4 bone;\r\n" + //
|
||||
" // For the broken models out there, since the game supports this.\r\n" + //
|
||||
" if (a_boneNumber > 0.0) {\r\n" + //
|
||||
" for (int i = 0; i < 4; i++) {\r\n" + //
|
||||
" if (a_bones[i] > 0.0) {\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[i] - 1.0, 0.0);\r\n" + //
|
||||
" }\r\n" + //
|
||||
" }\r\n" + //
|
||||
" #ifdef EXTENDED_BONES\r\n" + //
|
||||
" for (int i = 0; i < 4; i++) {\r\n" + //
|
||||
" if (a_extendedBones[i] > 0.0) {\r\n" + //
|
||||
" bone += fetchMatrix(a_extendedBones[i] - 1.0, 0.0);\r\n" + //
|
||||
" }\r\n" + //
|
||||
" }\r\n" + //
|
||||
" #endif\r\n" + //
|
||||
" }\r\n" + //
|
||||
" return bone / a_boneNumber;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void transformVertexGroups(inout vec3 position, inout vec3 normal) {\r\n" + //
|
||||
" mat4 bone = getVertexGroupMatrix();\r\n" + //
|
||||
" mat3 rotation = mat3(bone);\r\n" + //
|
||||
" position = vec3(bone * vec4(position, 1.0));\r\n" + //
|
||||
" normal = normalize(rotation * normal);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void transformVertexGroupsHD(inout vec3 position, inout vec3 normal, inout vec3 tangent, inout vec3 binormal) {\r\n"
|
||||
+ //
|
||||
" mat4 bone = getVertexGroupMatrix();\r\n" + //
|
||||
" mat3 rotation = mat3(bone);\r\n" + //
|
||||
" position = vec3(bone * vec4(position, 1.0));\r\n" + //
|
||||
" normal = normalize(rotation * normal);\r\n" + //
|
||||
" tangent = normalize(rotation * tangent);\r\n" + //
|
||||
" binormal = normalize(rotation * binormal);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"#endif";
|
||||
|
||||
public static final String decodeFloat = "\r\n" + //
|
||||
" vec2 decodeFloat2(float f) {\r\n" + //
|
||||
|
@ -4,13 +4,26 @@ public class Batch implements GenericIndexed {
|
||||
public int index;
|
||||
public Geoset geoset;
|
||||
public Layer layer;
|
||||
public boolean isExtended;
|
||||
public Material material;
|
||||
public final SkinningType skinningType;
|
||||
public final boolean hd;
|
||||
|
||||
public Batch(final int index, final Geoset geoset, final Layer layer, final boolean isExtended) {
|
||||
public Batch(final int index, final Geoset geoset, final Layer layer, final SkinningType skinningType) {
|
||||
this.index = index;
|
||||
this.geoset = geoset;
|
||||
this.layer = layer;
|
||||
this.isExtended = isExtended;
|
||||
this.material = null;
|
||||
this.skinningType = skinningType;
|
||||
this.hd = false;
|
||||
}
|
||||
|
||||
public Batch(final int index, final Geoset geoset, final Material material, final SkinningType skinningType) {
|
||||
this.index = index;
|
||||
this.geoset = geoset;
|
||||
this.material = material;
|
||||
this.layer = material.layers.get(0);
|
||||
this.skinningType = skinningType;
|
||||
this.hd = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.etheller.warsmash.util.WarsmashConstants;
|
||||
import com.etheller.warsmash.viewer5.Camera;
|
||||
import com.etheller.warsmash.viewer5.ModelViewer;
|
||||
import com.etheller.warsmash.viewer5.Scene;
|
||||
import com.etheller.warsmash.viewer5.Texture;
|
||||
@ -15,18 +16,22 @@ import com.etheller.warsmash.viewer5.handlers.w3x.DynamicShadowManager;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.W3xSceneLightManager;
|
||||
|
||||
public class BatchGroup extends GenericGroup {
|
||||
private static float[] tempFloat3Array = new float[3];
|
||||
|
||||
private final MdxModel model;
|
||||
public final boolean isExtended;
|
||||
public final SkinningType skinningType;
|
||||
public final boolean hd;
|
||||
|
||||
public BatchGroup(final MdxModel model, final boolean isExtended) {
|
||||
public BatchGroup(final MdxModel model, final SkinningType skinningType, final boolean hd) {
|
||||
this.model = model;
|
||||
this.isExtended = isExtended;
|
||||
this.skinningType = skinningType;
|
||||
this.hd = hd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(final MdxComplexInstance instance, final Matrix4 mvp) {
|
||||
final Scene scene = instance.scene;
|
||||
final Camera camera = scene.camera;
|
||||
final MdxModel model = this.model;
|
||||
final List<Texture> textures = model.getTextures();
|
||||
final MdxHandler handler = model.handler;
|
||||
@ -35,11 +40,15 @@ public class BatchGroup extends GenericGroup {
|
||||
final ModelViewer viewer = model.viewer;
|
||||
final GL20 gl = viewer.gl;
|
||||
final WebGL webGL = viewer.webGL;
|
||||
final boolean isExtended = this.isExtended;
|
||||
final SkinningType skinningType = this.skinningType;
|
||||
final boolean hd = this.hd;
|
||||
final ShaderProgram shader;
|
||||
final W3xSceneLightManager lightManager = (W3xSceneLightManager) scene.getLightManager();
|
||||
|
||||
if (isExtended) {
|
||||
if (hd) {
|
||||
shader = handler.shaders.hd;
|
||||
}
|
||||
else if (skinningType == SkinningType.ExtendedVertexGroups) {
|
||||
if (DynamicShadowManager.IS_SHADOW_MAPPING) {
|
||||
shader = handler.shaders.extendedShadowMap;
|
||||
}
|
||||
@ -58,7 +67,7 @@ public class BatchGroup extends GenericGroup {
|
||||
|
||||
webGL.useShaderProgram(shader);
|
||||
|
||||
shader.setUniformMatrix("u_mvp", mvp);
|
||||
shader.setUniformMatrix(hd ? "u_VP" : "u_mvp", mvp);
|
||||
|
||||
final DataTexture boneTexture = instance.boneTexture;
|
||||
final DataTexture unitLightsTexture = lightManager.getUnitLightsTexture();
|
||||
@ -81,79 +90,185 @@ public class BatchGroup extends GenericGroup {
|
||||
shader.setUniformf("u_hasBones", 0);
|
||||
}
|
||||
|
||||
shader.setUniformi("u_texture", 0);
|
||||
|
||||
gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, model.arrayBuffer);
|
||||
gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, model.elementBuffer);
|
||||
|
||||
shader.setUniform4fv("u_vertexColor", instance.vertexColor, 0, instance.vertexColor.length);
|
||||
if (hd) {
|
||||
shader.setUniformi("u_diffuseMap", 0);
|
||||
shader.setUniformi("u_normalsMap", 1);
|
||||
shader.setUniformi("u_ormMap", 2);
|
||||
shader.setUniformi("u_emissiveMap", 3);
|
||||
shader.setUniformi("u_teamColorMap", 4);
|
||||
shader.setUniformi("u_environmentMap", 5);
|
||||
|
||||
for (final int index : this.objects) {
|
||||
final Batch batch = batches.get(index);
|
||||
final Geoset geoset = batch.geoset;
|
||||
final Layer layer = batch.layer;
|
||||
final int geosetIndex = geoset.index;
|
||||
final int layerIndex = layer.index;
|
||||
final float[] geosetColor = instance.geosetColors[geosetIndex];
|
||||
final float layerAlpha = instance.layerAlphas[layerIndex];
|
||||
gl.glEnable(GL20.GL_BLEND);
|
||||
gl.glEnable(GL20.GL_DEPTH_TEST);
|
||||
gl.glDepthMask(true);
|
||||
|
||||
if ((geosetColor[3] > 0.01) && (layerAlpha > 0.01)) {
|
||||
// BELOW: I updated it to "Math.max(0," because MDL and MDX parser for PRSCMOD
|
||||
// menu screen behaved differently,
|
||||
// the MDL case was getting "no data" for default value when unanimated, and "no
|
||||
// data" resolved to -1,
|
||||
// whereas MDX binary contained an "unused" 0 value.
|
||||
final int layerTexture = Math.max(0, instance.layerTextures[layerIndex]);
|
||||
final float[] uvAnim = instance.uvAnims[layerIndex];
|
||||
shader.setUniformMatrix("u_MV", camera.viewMatrix);
|
||||
|
||||
shader.setUniform4fv("u_geosetColor", geosetColor, 0, geosetColor.length);
|
||||
tempFloat3Array[0] = camera.location.x;
|
||||
tempFloat3Array[1] = camera.location.y;
|
||||
tempFloat3Array[2] = camera.location.z;
|
||||
shader.setUniform3fv("u_eyePos", tempFloat3Array, 0, 3);
|
||||
|
||||
shader.setUniformf("u_layerAlpha", layerAlpha);
|
||||
shader.setUniformf("u_unshaded", layer.unshaded);
|
||||
for (final int index : this.objects) {
|
||||
final Batch batch = batches.get(index);
|
||||
final Geoset geoset = batch.geoset;
|
||||
final Material material = batch.material;
|
||||
final Layer diffuseLayer = material.layers.get(0);
|
||||
final Layer normalsLayer = material.layers.get(1);
|
||||
final Layer ormLayer = material.layers.get(2);
|
||||
final Layer emissiveLayer = material.layers.get(3);
|
||||
final Layer teamColorLayer = material.layers.get(4);
|
||||
final Layer environmentMapLayer = material.layers.get(5);
|
||||
final float layerAlpha = instance.layerAlphas[diffuseLayer.index];
|
||||
|
||||
shader.setUniform2fv("u_uvTrans", uvAnim, 0, 2);
|
||||
shader.setUniform2fv("u_uvRot", uvAnim, 2, 2);
|
||||
shader.setUniform1fv("u_uvScale", uvAnim, 4, 1);
|
||||
if (layerAlpha > 0) {
|
||||
shader.setUniformf("u_layerAlpha", layerAlpha);
|
||||
shader.setUniformf("u_filterMode", diffuseLayer.filterMode);
|
||||
|
||||
if (instance.additiveOverrideMeshMode) {
|
||||
layer.bindBlended(shader);
|
||||
gl.glBlendFunc(FilterMode.ADDITIVE_ALPHA[0], FilterMode.ADDITIVE_ALPHA[1]);
|
||||
}
|
||||
else if (instance.vertexColor[3] < 1.0f) {
|
||||
layer.bindBlended(shader);
|
||||
}
|
||||
else {
|
||||
layer.bind(shader);
|
||||
}
|
||||
final int diffuseId = Math.max(0, instance.layerTextures[diffuseLayer.index]);
|
||||
final int normalsId = Math.max(0, instance.layerTextures[normalsLayer.index]);
|
||||
final int ormId = Math.max(0, instance.layerTextures[ormLayer.index]);
|
||||
final int emissiveId = Math.max(0, instance.layerTextures[emissiveLayer.index]);
|
||||
final int teamColorId = Math.max(0, instance.layerTextures[teamColorLayer.index]);
|
||||
final int environmentMapId = Math.max(0, instance.layerTextures[environmentMapLayer.index]);
|
||||
|
||||
final Integer replaceable = replaceables.get(layerTexture); // TODO is this OK?
|
||||
Texture texture;
|
||||
final Texture diffuseTexture;
|
||||
final Texture normalsTexture;
|
||||
final Texture ormTexture;
|
||||
final Texture emissiveTexture = textures.get(emissiveId);
|
||||
final Texture teamColorTexture;
|
||||
final Texture environmentMapTexture = textures.get(environmentMapId);
|
||||
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures[replaceable] != null)) {
|
||||
texture = instance.replaceableTextures[replaceable];
|
||||
}
|
||||
else {
|
||||
texture = textures.get(layerTexture);
|
||||
|
||||
Texture textureLookup = instance.textureMapper.get(texture);
|
||||
if (textureLookup == null) {
|
||||
textureLookup = texture;
|
||||
{
|
||||
final Integer replaceable = replaceables.get(diffuseId);
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures_diffuse[replaceable] != null)) {
|
||||
diffuseTexture = instance.replaceableTextures_diffuse[replaceable];
|
||||
}
|
||||
else {
|
||||
diffuseTexture = textures.get(diffuseId);
|
||||
}
|
||||
}
|
||||
texture = textureLookup;
|
||||
}
|
||||
|
||||
viewer.webGL.bindTexture(texture, 0);
|
||||
{
|
||||
final Integer replaceable = replaceables.get(normalsId);
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures_normal[replaceable] != null)) {
|
||||
normalsTexture = instance.replaceableTextures_normal[replaceable];
|
||||
}
|
||||
else {
|
||||
normalsTexture = textures.get(normalsId);
|
||||
}
|
||||
}
|
||||
|
||||
if (isExtended) {
|
||||
geoset.bindExtended(shader, layer.coordId);
|
||||
}
|
||||
else {
|
||||
geoset.bind(shader, layer.coordId);
|
||||
}
|
||||
{
|
||||
final Integer replaceable = replaceables.get(ormId);
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures_orm[replaceable] != null)) {
|
||||
ormTexture = instance.replaceableTextures_orm[replaceable];
|
||||
}
|
||||
else {
|
||||
ormTexture = textures.get(ormId);
|
||||
}
|
||||
}
|
||||
|
||||
geoset.render();
|
||||
final Integer replaceable = replaceables.get(teamColorId);
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures[replaceable] != null)) {
|
||||
teamColorTexture = instance.replaceableTextures[replaceable];
|
||||
}
|
||||
else {
|
||||
teamColorTexture = textures.get(teamColorId);
|
||||
}
|
||||
|
||||
webGL.bindTexture(diffuseTexture, 0);
|
||||
webGL.bindTexture(normalsTexture, 1);
|
||||
webGL.bindTexture(ormTexture, 2);
|
||||
webGL.bindTexture(emissiveTexture, 3);
|
||||
webGL.bindTexture(teamColorTexture, 4);
|
||||
webGL.bindTexture(environmentMapTexture, 5);
|
||||
|
||||
geoset.bindHd(shader, batch.skinningType, diffuseLayer.coordId);
|
||||
geoset.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
shader.setUniformi("u_texture", 0);
|
||||
|
||||
shader.setUniform4fv("u_vertexColor", instance.vertexColor, 0, instance.vertexColor.length);
|
||||
|
||||
for (final int index : this.objects) {
|
||||
final Batch batch = batches.get(index);
|
||||
final Geoset geoset = batch.geoset;
|
||||
final Layer layer = batch.layer;
|
||||
final int geosetIndex = geoset.index;
|
||||
final int layerIndex = layer.index;
|
||||
final float[] geosetColor = instance.geosetColors[geosetIndex];
|
||||
final float layerAlpha = instance.layerAlphas[layerIndex];
|
||||
|
||||
if ((geosetColor[3] > 0.01) && (layerAlpha > 0.01)) {
|
||||
// BELOW: I updated it to "Math.max(0," because MDL and MDX parser for PRSCMOD
|
||||
// menu screen behaved differently,
|
||||
// the MDL case was getting "no data" for default value when unanimated, and "no
|
||||
// data" resolved to -1,
|
||||
// whereas MDX binary contained an "unused" 0 value.
|
||||
final int layerTexture = Math.max(0, instance.layerTextures[layerIndex]);
|
||||
final float[] uvAnim = instance.uvAnims[layerIndex];
|
||||
|
||||
shader.setUniform4fv("u_geosetColor", geosetColor, 0, geosetColor.length);
|
||||
|
||||
shader.setUniformf("u_layerAlpha", layerAlpha);
|
||||
shader.setUniformf("u_unshaded", layer.unshaded);
|
||||
|
||||
shader.setUniform2fv("u_uvTrans", uvAnim, 0, 2);
|
||||
shader.setUniform2fv("u_uvRot", uvAnim, 2, 2);
|
||||
shader.setUniform1fv("u_uvScale", uvAnim, 4, 1);
|
||||
|
||||
if (instance.additiveOverrideMeshMode) {
|
||||
layer.bindBlended(shader);
|
||||
gl.glBlendFunc(FilterMode.ADDITIVE_ALPHA[0], FilterMode.ADDITIVE_ALPHA[1]);
|
||||
}
|
||||
else if (instance.vertexColor[3] < 1.0f) {
|
||||
layer.bindBlended(shader);
|
||||
}
|
||||
else {
|
||||
layer.bind(shader);
|
||||
}
|
||||
|
||||
final Integer replaceable = replaceables.get(layerTexture); // TODO is this OK?
|
||||
Texture texture;
|
||||
|
||||
if ((replaceable > 0) && (replaceable < WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT)
|
||||
&& (instance.replaceableTextures[replaceable] != null)) {
|
||||
texture = instance.replaceableTextures[replaceable];
|
||||
}
|
||||
else {
|
||||
texture = textures.get(layerTexture);
|
||||
|
||||
Texture textureLookup = instance.textureMapper.get(texture);
|
||||
if (textureLookup == null) {
|
||||
textureLookup = texture;
|
||||
}
|
||||
texture = textureLookup;
|
||||
}
|
||||
|
||||
viewer.webGL.bindTexture(texture, 0);
|
||||
|
||||
if (skinningType == SkinningType.ExtendedVertexGroups) {
|
||||
geoset.bindExtended(shader, layer.coordId);
|
||||
}
|
||||
else {
|
||||
geoset.bind(shader, layer.coordId);
|
||||
}
|
||||
|
||||
geoset.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ public class Geoset {
|
||||
public int positionOffset;
|
||||
public int normalOffset;
|
||||
public int uvOffset;
|
||||
public final int tangentOffset;
|
||||
public int skinOffset;
|
||||
public int faceOffset;
|
||||
public int vertices;
|
||||
@ -29,14 +30,15 @@ public class Geoset {
|
||||
public final MdlxGeoset mdlxGeoset;
|
||||
|
||||
public Geoset(final MdxModel model, final int index, final int positionOffset, final int normalOffset,
|
||||
final int uvOffset, final int skinOffset, final int faceOffset, final int vertices, final int elements,
|
||||
final int openGLSkinType, final int skinStride, final int boneCountOffsetBytes, final boolean unselectable,
|
||||
final MdlxGeoset mdlxGeoset) {
|
||||
final int uvOffset, final int tangentOffset, final int skinOffset, final int faceOffset, final int vertices,
|
||||
final int elements, final int openGLSkinType, final int skinStride, final int boneCountOffsetBytes,
|
||||
final boolean unselectable, final MdlxGeoset mdlxGeoset) {
|
||||
this.model = model;
|
||||
this.index = index;
|
||||
this.positionOffset = positionOffset;
|
||||
this.normalOffset = normalOffset;
|
||||
this.uvOffset = uvOffset;
|
||||
this.tangentOffset = tangentOffset;
|
||||
this.skinOffset = skinOffset;
|
||||
this.faceOffset = faceOffset;
|
||||
this.vertices = vertices;
|
||||
@ -143,12 +145,16 @@ public class Geoset {
|
||||
this.faceOffset, instances);
|
||||
}
|
||||
|
||||
public void bindHd(final ShaderProgram shader, final int coordId) {
|
||||
public void bindHd(final ShaderProgram shader, final SkinningType skinningType, final int coordId) {
|
||||
shader.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, this.positionOffset);
|
||||
shader.setVertexAttribute("a_normal", 3, GL20.GL_FLOAT, false, 0, this.positionOffset);
|
||||
shader.setVertexAttribute("a_normal", 3, GL20.GL_FLOAT, false, 0, this.normalOffset);
|
||||
shader.setVertexAttribute("a_uv", 2, GL20.GL_FLOAT, false, 0, this.uvOffset + (coordId * this.vertices * 8));
|
||||
|
||||
shader.setVertexAttribute("a_tangent", 4, GL20.GL_FLOAT, false, 0, this.tangentOffset);
|
||||
|
||||
// TODO ghostwolf splits here and allows HD with non-skin, or SD with skin
|
||||
shader.setVertexAttribute("a_bones", 4, GL20.GL_UNSIGNED_BYTE, false, 8, this.skinOffset);
|
||||
shader.setVertexAttribute("a_weights", 4, GL20.GL_UNSIGNED_BYTE, false, 8, this.skinOffset + 4);
|
||||
shader.setVertexAttribute("a_weights", 4, GL20.GL_UNSIGNED_BYTE, true, 8, this.skinOffset + 4);
|
||||
}
|
||||
|
||||
private static final class Variants {
|
||||
|
@ -70,6 +70,9 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
public FloatBuffer worldMatricesCopyHeap;
|
||||
public DataTexture boneTexture;
|
||||
public Texture[] replaceableTextures = new Texture[WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT];
|
||||
public Texture[] replaceableTextures_diffuse = new Texture[WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT];
|
||||
public Texture[] replaceableTextures_normal = new Texture[WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT];
|
||||
public Texture[] replaceableTextures_orm = new Texture[WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT];
|
||||
private float animationSpeed = 1.0f;
|
||||
private float blendTime;
|
||||
private float blendTimeRemaining;
|
||||
@ -681,6 +684,16 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
PathSolver.DEFAULT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceableTextureHD(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||
this.replaceableTextures_diffuse[replaceableTextureId] = (Texture) this.model.viewer
|
||||
.load(replaceableTextureFile + "_diffuse.dds", PathSolver.DEFAULT, null);
|
||||
this.replaceableTextures_normal[replaceableTextureId] = (Texture) this.model.viewer
|
||||
.load(replaceableTextureFile + "_normal.dds", PathSolver.DEFAULT, null);
|
||||
this.replaceableTextures_orm[replaceableTextureId] = (Texture) this.model.viewer
|
||||
.load(replaceableTextureFile + "_orm.dds", PathSolver.DEFAULT, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the vertex color of this instance.
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ public class MdxHandler extends ModelHandler {
|
||||
this.shaders.particles = viewer.webGL.createShaderProgram(MdxShaders.vsParticles(), MdxShaders.fsParticles);
|
||||
// Shaders.simple = viewer.webGL.createShaderProgram(MdxShaders.vsSimple,
|
||||
// MdxShaders.fsSimple);
|
||||
// Shaders.hd = viewer.webGL.createShaderProgram(MdxShaders.vsHd, MdxShaders.fsHd);
|
||||
this.shaders.hd = viewer.webGL.createShaderProgram(MdxShaders.vsHd, MdxShaders.fsHd());
|
||||
// TODO HD reforged
|
||||
|
||||
// If a shader failed to compile, don't allow the handler to be registered, and
|
||||
|
@ -144,9 +144,9 @@ public class MdxModel extends com.etheller.warsmash.viewer5.Model<MdxHandler> {
|
||||
this.layers.add(vLayer);
|
||||
}
|
||||
|
||||
this.materials.add(new Material(this, "" /* material.shader */, layers));
|
||||
this.materials.add(new Material(this, material.shader, layers));
|
||||
|
||||
if (false /* !"".equals(material.shader) */) {
|
||||
if (!"".equals(material.shader)) {
|
||||
this.hd = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,353 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.mdx;
|
||||
|
||||
import com.etheller.warsmash.viewer5.Shaders;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler.ShaderEnvironmentType;
|
||||
|
||||
public class MdxShaders {
|
||||
public static final String vsHd = Shaders.boneTexture + "\r\n" + //
|
||||
" uniform mat4 u_mvp;\r\n" + //
|
||||
public static final String vsHd = "#version 120\r\n" + Shaders.boneTexture + "\r\n" + //
|
||||
" uniform mat4 u_VP;\r\n" + //
|
||||
" uniform mat4 u_MV;\r\n" + //
|
||||
" uniform vec3 u_eyePos;\r\n" + //
|
||||
" uniform sampler2D u_lightTexture;\r\n" + //
|
||||
" uniform float u_lightTextureHeight;\r\n" + //
|
||||
" uniform float u_layerAlpha;\r\n" + //
|
||||
" uniform bool u_hasBones;\r\n" + //
|
||||
" " + //
|
||||
" attribute vec3 a_position;\r\n" + //
|
||||
" attribute vec3 a_normal;\r\n" + //
|
||||
" attribute vec2 a_uv;\r\n" + //
|
||||
" attribute vec4 a_bones;\r\n" + //
|
||||
" attribute vec4 a_weights;\r\n" + //
|
||||
" varying vec3 v_normal;\r\n" + //
|
||||
" attribute vec4 a_tangent;\r\n" + //
|
||||
// TODO ONLY_TANGENTS
|
||||
" \r\n" + //
|
||||
" \r\n" + //
|
||||
"#define SKIN\r\n" + // TODO make this conditional
|
||||
Shaders.transforms + //
|
||||
" \r\n" + //
|
||||
" \r\n" + //
|
||||
"vec3 TBN(vec3 vector, vec3 tangent, vec3 binormal, vec3 normal) {\r\n" + //
|
||||
" return vec3(dot(vector, tangent), dot(vector, binormal), dot(vector, normal));\r\n" + //
|
||||
"}\r\n" + //
|
||||
" \r\n" + //
|
||||
" \r\n" + //
|
||||
" varying vec2 v_uv;\r\n" + //
|
||||
" varying float v_layerAlpha;\r\n" + //
|
||||
" void transform(inout vec3 position, inout vec3 normal) {\r\n" + //
|
||||
" mat4 bone;\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[0], 0.0) * a_weights[0];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[1], 0.0) * a_weights[1];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[2], 0.0) * a_weights[2];\r\n" + //
|
||||
" bone += fetchMatrix(a_bones[3], 0.0) * a_weights[3];\r\n" + //
|
||||
" position = vec3(bone * vec4(position, 1.0));\r\n" + //
|
||||
" normal = mat3(bone) * normal;\r\n" + //
|
||||
" }\r\n" + //
|
||||
" varying vec3 v_lightDir;\r\n" + //
|
||||
" varying vec3 v_eyeVec;\r\n" + //
|
||||
" varying vec3 v_normal;\r\n" + //
|
||||
" \r\n" + //
|
||||
" \r\n" + //
|
||||
" void main() {\r\n" + //
|
||||
" vec3 position = a_position;\r\n" + //
|
||||
" vec3 normal = a_normal;\r\n" + //
|
||||
" transform(position, normal);\r\n" + //
|
||||
" v_normal = normal;\r\n" + //
|
||||
" vec3 tangent = a_tangent.xyz;\r\n" + //
|
||||
" \r\n" + //
|
||||
// Re-orthogonalize the tangent in case it wasnt normalized.
|
||||
// See "One last thing" at
|
||||
// https://learnopengl.com/Advanced-Lighting/Normal-Mapping
|
||||
" \r\n" + //
|
||||
" tangent = normalize(tangent - dot(tangent, normal) * normal);\r\n" + //
|
||||
" \r\n" + //
|
||||
" vec3 binormal = cross(normal, tangent) * a_tangent.w;\r\n" + //
|
||||
" \r\n" + //
|
||||
" if (u_hasBones) {\r\n" + //
|
||||
" #ifdef SKIN\r\n" + //
|
||||
" transformSkin(position, normal, tangent, binormal);\r\n" + //
|
||||
" #else\r\n" + //
|
||||
" transformVertexGroupsHD(position, normal, tangent, binormal);\r\n" + //
|
||||
" #endif\r\n" + //
|
||||
" }\r\n" + //
|
||||
" \r\n" + //
|
||||
" vec3 position_mv = vec3(u_MV * vec4(position, 1));\r\n" + //
|
||||
" \r\n" + //
|
||||
" mat3 mv = mat3(u_MV);\r\n" + //
|
||||
" vec3 t = normalize(mv * tangent);\r\n" + //
|
||||
" vec3 b = normalize(mv * binormal);\r\n" + //
|
||||
" vec3 n = normalize(mv * normal);\r\n" + //
|
||||
" \r\n" + //
|
||||
" v_eyeVec = normalize(u_eyePos - position_mv);\r\n" + //
|
||||
" \r\n" + //
|
||||
// TODO fix giant hack on lighting
|
||||
" float rowPos = (0.5) / u_lightTextureHeight;\r\n" + //
|
||||
" vec4 lightPosition = texture2D(u_lightTexture, vec2(0.125, rowPos));\r\n" + //
|
||||
" vec3 u_lightPos = lightPosition.xyz;\r\n" + //
|
||||
" vec3 lightDir = normalize(u_lightPos - position_mv);\r\n" + //
|
||||
" v_lightDir = normalize(TBN(lightDir, t, b, n));\r\n" + //
|
||||
" \r\n" + //
|
||||
" v_uv = a_uv;\r\n" + //
|
||||
" v_layerAlpha = u_layerAlpha;\r\n" + //
|
||||
" gl_Position = u_mvp * vec4(position, 1.0);\r\n" + //
|
||||
" \r\n" + //
|
||||
" v_normal = normal;\r\n" + //
|
||||
" // v_lightDirWorld = normalize(lightDir);\r\n" + //
|
||||
" \r\n" + //
|
||||
// TODO ONLY_TANGENTS
|
||||
" gl_Position = u_VP * vec4(position, 1.0);\r\n" + //
|
||||
" }";
|
||||
|
||||
public static final String fsHd = "\r\n" + //
|
||||
" uniform sampler2D u_diffuseMap;\r\n" + //
|
||||
" uniform sampler2D u_ormMap;\r\n" + //
|
||||
" uniform sampler2D u_teamColorMap;\r\n" + //
|
||||
" uniform float u_filterMode;\r\n" + //
|
||||
" varying vec3 v_normal;\r\n" + //
|
||||
" varying vec2 v_uv;\r\n" + //
|
||||
" varying float v_layerAlpha;\r\n" + //
|
||||
" void main() {\r\n" + //
|
||||
" vec4 texel = texture2D(u_diffuseMap, v_uv);\r\n" + //
|
||||
" vec4 color = vec4(texel.rgb, texel.a * v_layerAlpha);\r\n" + //
|
||||
" vec4 orma = texture2D(u_ormMap, v_uv);\r\n" + //
|
||||
" if (orma.a > 0.1) {\r\n" + //
|
||||
" color *= texture2D(u_teamColorMap, v_uv) * orma.a;\r\n" + //
|
||||
" }\r\n" + //
|
||||
" // 1bit Alpha\r\n" + //
|
||||
" if (u_filterMode == 1.0 && color.a < 0.75) {\r\n" + //
|
||||
" discard;\r\n" + //
|
||||
" }\r\n" + //
|
||||
" gl_FragColor = color;\r\n" + //
|
||||
" }";
|
||||
public static final String fsHd() {
|
||||
return "#version 120\r\n" + //
|
||||
"\r\n" + //
|
||||
"\r\n" + //
|
||||
"\r\n" + //
|
||||
"uniform sampler2D u_diffuseMap;\r\n" + //
|
||||
"uniform sampler2D u_normalsMap;\r\n" + //
|
||||
"uniform sampler2D u_ormMap;\r\n" + //
|
||||
"uniform sampler2D u_emissiveMap;\r\n" + //
|
||||
"uniform sampler2D u_teamColorMap;\r\n" + //
|
||||
"uniform sampler2D u_environmentMap;\r\n" + //
|
||||
"uniform float u_filterMode;\r\n" + //
|
||||
"// uniform sampler2D u_lutMap;\r\n" + //
|
||||
"// uniform sampler2D u_envDiffuseMap;\r\n" + //
|
||||
"// uniform sampler2D u_envSpecularMap;\r\n" + //
|
||||
"varying vec2 v_uv;\r\n" + //
|
||||
"varying float v_layerAlpha;\r\n" + //
|
||||
"varying vec3 v_lightDir;\r\n" + //
|
||||
"varying vec3 v_eyeVec;\r\n" + //
|
||||
"varying vec3 v_normal;\r\n" + //
|
||||
"// varying vec3 v_lightDirWorld;\r\n" + //
|
||||
"#if defined(ONLY_TANGENTS)\r\n" + //
|
||||
"varying vec3 v_tangent;\r\n" + //
|
||||
"#endif\r\n" + //
|
||||
"vec3 decodeNormal() {\r\n" + //
|
||||
" vec2 xy = texture2D(u_normalsMap, v_uv).xy * 2.0 - 1.0;\r\n" + //
|
||||
" \r\n" + //
|
||||
" return vec3(xy, sqrt(1.0 - dot(xy, xy)));\r\n" + //
|
||||
"}\r\n" + //
|
||||
"const vec2 invAtan = vec2(0.1591, 0.3183);\r\n" + //
|
||||
"vec2 sampleEnvironmentMap(vec3 normal) {\r\n" + //
|
||||
" vec2 uv = vec2(atan(normal.x, normal.y), -asin(normal.z));\r\n" + //
|
||||
" uv *= invAtan;\r\n" + //
|
||||
" uv += 0.5;\r\n" + //
|
||||
" return uv;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"vec4 getDiffuseColor() {\r\n" + //
|
||||
" vec4 color = texture2D(u_diffuseMap, v_uv);\r\n" + //
|
||||
" // 1bit Alpha\r\n" + //
|
||||
" if (u_filterMode == 1.0 && color.a < 0.75) {\r\n" + //
|
||||
" discard;\r\n" + //
|
||||
" }\r\n" + //
|
||||
" return color;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"vec4 getOrmColor() {\r\n" + //
|
||||
" return texture2D(u_ormMap, v_uv);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"vec3 getEmissiveColor() {\r\n" + //
|
||||
" return texture2D(u_emissiveMap, v_uv).rgb;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"vec3 getTeamColor() {\r\n" + //
|
||||
" return texture2D(u_teamColorMap, v_uv).rgb;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"// const float PI = 3.14159265359;\r\n" + //
|
||||
"// const float RECIPROCAL_PI = 0.31830988618;\r\n" + //
|
||||
"// const float RECIPROCAL_PI2 = 0.15915494;\r\n" + //
|
||||
"// const float LN2 = 0.6931472;\r\n" + //
|
||||
"// const float ENV_LODS = 6.0;\r\n" + //
|
||||
"// vec4 SRGBtoLinear(vec4 srgb) {\r\n" + //
|
||||
"// vec3 linOut = pow(srgb.xyz, vec3(2.2));\r\n" + //
|
||||
"// return vec4(linOut, srgb.w);;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// vec4 RGBMToLinear(in vec4 value) {\r\n" + //
|
||||
"// float maxRange = 6.0;\r\n" + //
|
||||
"// return vec4(value.xyz * value.w * maxRange, 1.0);\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// vec3 linearToSRGB(vec3 color) {\r\n" + //
|
||||
"// return pow(color, vec3(1.0 / 2.2));\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// // vec3 getNormal() {\r\n" + //
|
||||
"// // vec3 pos_dx = dFdx(vMPos.xyz);\r\n" + //
|
||||
"// // vec3 pos_dy = dFdy(vMPos.xyz);\r\n" + //
|
||||
"// // vec2 tex_dx = dFdx(vUv);\r\n" + //
|
||||
"// // vec2 tex_dy = dFdy(vUv);\r\n" + //
|
||||
"// // vec3 t = normalize(pos_dx * tex_dy.t - pos_dy * tex_dx.t);\r\n" + //
|
||||
"// // vec3 b = normalize(-pos_dx * tex_dy.s + pos_dy * tex_dx.s);\r\n" + //
|
||||
"// // mat3 tbn = mat3(t, b, normalize(vNormal));\r\n" + //
|
||||
"// // vec3 n = texture2D(tNormal, vUv * uNormalUVScale).rgb * 2.0 - 1.0;\r\n" + //
|
||||
"// // n.xy *= uNormalScale;\r\n" + //
|
||||
"// // vec3 normal = normalize(tbn * n);\r\n" + //
|
||||
"// // // Get world normal from view normal (normalMatrix * normal)\r\n" + //
|
||||
"// // return normalize((vec4(normal, 0.0) * viewMatrix).xyz);\r\n" + //
|
||||
"// // }\r\n" + //
|
||||
"// vec3 specularReflection(vec3 specularEnvR0, vec3 specularEnvR90, float VdH) {\r\n" + //
|
||||
"// return specularEnvR0 + (specularEnvR90 - specularEnvR0) * pow(clamp(1.0 - VdH, 0.0, 1.0), 5.0);\r\n"
|
||||
+ //
|
||||
"// }\r\n" + //
|
||||
"// float geometricOcclusion(float NdL, float NdV, float roughness) {\r\n" + //
|
||||
"// float r = roughness;\r\n" + //
|
||||
"// float attenuationL = 2.0 * NdL / (NdL + sqrt(r * r + (1.0 - r * r) * (NdL * NdL)));\r\n" + //
|
||||
"// float attenuationV = 2.0 * NdV / (NdV + sqrt(r * r + (1.0 - r * r) * (NdV * NdV)));\r\n" + //
|
||||
"// return attenuationL * attenuationV;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// float microfacetDistribution(float roughness, float NdH) {\r\n" + //
|
||||
"// float roughnessSq = roughness * roughness;\r\n" + //
|
||||
"// float f = (NdH * roughnessSq - NdH) * NdH + 1.0;\r\n" + //
|
||||
"// return roughnessSq / (PI * f * f);\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// vec2 cartesianToPolar(vec3 n) {\r\n" + //
|
||||
"// vec2 uv;\r\n" + //
|
||||
"// uv.x = atan(n.z, n.x) * RECIPROCAL_PI2 + 0.5;\r\n" + //
|
||||
"// uv.y = asin(n.y) * RECIPROCAL_PI + 0.5;\r\n" + //
|
||||
"// return uv;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// void getIBLContribution(inout vec3 diffuse, inout vec3 specular, float NdV, float roughness, vec3 n, vec3 reflection, vec3 diffuseColor, vec3 specularColor) {\r\n"
|
||||
+ //
|
||||
"// vec3 brdf = SRGBtoLinear(texture2D(u_lutMap, vec2(NdV, roughness))).rgb;\r\n" + //
|
||||
"// vec3 diffuseLight = RGBMToLinear(texture2D(u_envDiffuseMap, sampleEnvironmentMap(n))).rgb;\r\n" + //
|
||||
"// // Sample 2 levels and mix between to get smoother degradation\r\n" + //
|
||||
"// float blend = roughness * ENV_LODS;\r\n" + //
|
||||
"// float level0 = floor(blend);\r\n" + //
|
||||
"// float level1 = min(ENV_LODS, level0 + 1.0);\r\n" + //
|
||||
"// blend -= level0;\r\n" + //
|
||||
" \r\n" + //
|
||||
"// // Sample the specular env map atlas depending on the roughness value\r\n" + //
|
||||
"// vec2 uvSpec = sampleEnvironmentMap(reflection);\r\n" + //
|
||||
"// uvSpec.y /= 2.0;\r\n" + //
|
||||
"// vec2 uv0 = uvSpec;\r\n" + //
|
||||
"// vec2 uv1 = uvSpec;\r\n" + //
|
||||
"// uv0 /= pow(2.0, level0);\r\n" + //
|
||||
"// uv0.y += 1.0 - exp(-LN2 * level0);\r\n" + //
|
||||
"// uv1 /= pow(2.0, level1);\r\n" + //
|
||||
"// uv1.y += 1.0 - exp(-LN2 * level1);\r\n" + //
|
||||
"// vec3 specular0 = RGBMToLinear(texture2D(u_envSpecularMap, uv0)).rgb;\r\n" + //
|
||||
"// vec3 specular1 = RGBMToLinear(texture2D(u_envSpecularMap, uv1)).rgb;\r\n" + //
|
||||
"// vec3 specularLight = mix(specular0, specular1, blend);\r\n" + //
|
||||
"// diffuse = diffuseLight * diffuseColor;\r\n" + //
|
||||
" \r\n" + //
|
||||
"// // Bit of extra reflection for smooth materials\r\n" + //
|
||||
"// float reflectivity = pow((1.0 - roughness), 2.0) * 0.05;\r\n" + //
|
||||
"// specular = specularLight * (specularColor * brdf.x + brdf.y + reflectivity);\r\n" + //
|
||||
"// // specular *= uEnvSpecular;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// void PBR() {\r\n" + //
|
||||
"// vec4 baseDiffuseColor = getDiffuseColor();\r\n" + //
|
||||
"// vec3 baseColor = baseDiffuseColor.rgb;\r\n" + //
|
||||
"// vec4 orm = getOrmColor();\r\n" + //
|
||||
"// vec3 tc = getTeamColor();\r\n" + //
|
||||
"// float tcFactor = getOrmColor().a;\r\n" + //
|
||||
"// if (tcFactor > 0.1) {\r\n" + //
|
||||
"// baseColor *= tc * tcFactor;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"// float roughness = clamp(orm.g, 0.04, 1.0);\r\n" + //
|
||||
"// float metallic = clamp(orm.b, 0.04, 1.0);\r\n" + //
|
||||
"// vec3 f0 = vec3(0.04);\r\n" + //
|
||||
"// vec3 diffuseColor = baseColor * (vec3(1.0) - f0) * (1.0 - metallic);\r\n" + //
|
||||
"// vec3 specularColor = mix(f0, baseColor, metallic);\r\n" + //
|
||||
"// vec3 specularEnvR0 = specularColor;\r\n" + //
|
||||
"// vec3 specularEnvR90 = vec3(clamp(max(max(specularColor.r, specularColor.g), specularColor.b) * 25.0, 0.0, 1.0));\r\n"
|
||||
+ //
|
||||
"// vec3 N = v_normal;\r\n" + //
|
||||
"// vec3 V = normalize(v_eyeVec);\r\n" + //
|
||||
"// vec3 L = normalize(v_lightDirWorld);\r\n" + //
|
||||
"// vec3 H = normalize(L + V);\r\n" + //
|
||||
"// vec3 reflection = normalize(reflect(-V, N));\r\n" + //
|
||||
"// float NdL = clamp(dot(N, L), 0.001, 1.0);\r\n" + //
|
||||
"// float NdV = clamp(abs(dot(N, V)), 0.001, 1.0);\r\n" + //
|
||||
"// float NdH = clamp(dot(N, H), 0.0, 1.0);\r\n" + //
|
||||
"// float LdH = clamp(dot(L, H), 0.0, 1.0);\r\n" + //
|
||||
"// float VdH = clamp(dot(V, H), 0.0, 1.0);\r\n" + //
|
||||
"// vec3 F = specularReflection(specularEnvR0, specularEnvR90, VdH);\r\n" + //
|
||||
"// float G = geometricOcclusion(NdL, NdV, roughness);\r\n" + //
|
||||
"// float D = microfacetDistribution(roughness, NdH);\r\n" + //
|
||||
"// vec3 diffuseContrib = (1.0 - F) * (diffuseColor / PI);\r\n" + //
|
||||
"// vec3 specContrib = F * G * D / (4.0 * NdL * NdV);\r\n" + //
|
||||
" \r\n" + //
|
||||
"// // Shading based off lights\r\n" + //
|
||||
"// // vec3 color = NdL * uLightColor * (diffuseContrib + specContrib);\r\n" + //
|
||||
"// vec3 color = NdL * (diffuseContrib + specContrib);\r\n" + //
|
||||
"// // Calculate IBL lighting\r\n" + //
|
||||
"// vec3 diffuseIBL;\r\n" + //
|
||||
"// vec3 specularIBL;\r\n" + //
|
||||
"// getIBLContribution(diffuseIBL, specularIBL, NdV, roughness, N, reflection, diffuseColor, specularColor);\r\n"
|
||||
+ //
|
||||
"// // Add IBL on top of color\r\n" + //
|
||||
"// color += specularIBL;\r\n" + //
|
||||
"// color *= orm.r;\r\n" + //
|
||||
"// color += getEmissiveColor();\r\n" + //
|
||||
"// // Convert to sRGB to display\r\n" + //
|
||||
"// gl_FragColor.rgb = color;\r\n" + //
|
||||
"// gl_FragColor.a = baseDiffuseColor.a;\r\n" + //
|
||||
"// }\r\n" + //
|
||||
"void onlyDiffuse() {\r\n" + //
|
||||
" vec4 baseColor = getDiffuseColor();\r\n" + //
|
||||
" vec3 tc = getTeamColor();\r\n" + //
|
||||
" float tcFactor = getOrmColor().a;\r\n" + //
|
||||
" if (tcFactor > 0.1) {\r\n" + //
|
||||
" baseColor.rgb *= tc * tcFactor;\r\n" + //
|
||||
" }\r\n" + //
|
||||
" gl_FragColor = baseColor;\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyNormalMap() {\r\n" + //
|
||||
" gl_FragColor = vec4(decodeNormal(), 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyOcclusion() {\r\n" + //
|
||||
" gl_FragColor = vec4(getOrmColor().rrr, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyRoughness() {\r\n" + //
|
||||
" gl_FragColor = vec4(getOrmColor().ggg, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyMetallic() {\r\n" + //
|
||||
" gl_FragColor = vec4(getOrmColor().bbb, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyTeamColorFactor() {\r\n" + //
|
||||
" gl_FragColor = vec4(getOrmColor().aaa, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyEmissiveMap() {\r\n" + //
|
||||
" gl_FragColor = vec4(getEmissiveColor(), 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyTexCoords() {\r\n" + //
|
||||
" gl_FragColor = vec4(v_uv, 0.0, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void onlyNormals() {\r\n" + //
|
||||
" gl_FragColor = vec4(v_normal, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"#if defined(ONLY_TANGENTS)\r\n" + //
|
||||
"void onlyTangents() {\r\n" + //
|
||||
" gl_FragColor = vec4(v_tangent, 1.0);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"#endif\r\n" + //
|
||||
"void lambert() {\r\n" + //
|
||||
" vec4 baseColor = getDiffuseColor();\r\n" + //
|
||||
" vec3 normal = decodeNormal();\r\n" + //
|
||||
" vec4 orm = getOrmColor();\r\n" + //
|
||||
" vec3 emissive = getEmissiveColor();\r\n" + //
|
||||
" vec3 tc = getTeamColor();\r\n" + //
|
||||
" float aoFactor = orm.r;\r\n" + //
|
||||
" float tcFactor = orm.a;\r\n" + //
|
||||
" float lambertFactor = clamp(dot(normal, v_lightDir), 0.0, 1.0);\r\n" + //
|
||||
" vec3 color = baseColor.rgb;\r\n" + //
|
||||
(MdxHandler.CURRENT_SHADER_TYPE != ShaderEnvironmentType.MENU ? " if (tcFactor > 0.1) {\r\n" + //
|
||||
" color = color * (1.0 - tcFactor) + color * tc * tcFactor;\r\n" + //
|
||||
" }\r\n" : "\r\n")
|
||||
+ //
|
||||
" \r\n" + //
|
||||
" color *= clamp(lambertFactor * aoFactor + 0.1, 0.0, 1.0);\r\n" + //
|
||||
" color += emissive;\r\n" + //
|
||||
" gl_FragColor = vec4(color, baseColor.a);\r\n" + //
|
||||
"}\r\n" + //
|
||||
"void main() {\r\n" + //
|
||||
" #if defined(ONLY_DIFFUSE)\r\n" + //
|
||||
" onlyDiffuse();\r\n" + //
|
||||
" #elif defined(ONLY_NORMAL_MAP)\r\n" + //
|
||||
" onlyNormalMap();\r\n" + //
|
||||
" #elif defined(ONLY_OCCLUSION)\r\n" + //
|
||||
" onlyOcclusion();\r\n" + //
|
||||
" #elif defined(ONLY_ROUGHNESS)\r\n" + //
|
||||
" onlyRoughness();\r\n" + //
|
||||
" #elif defined(ONLY_METALLIC)\r\n" + //
|
||||
" onlyMetallic();\r\n" + //
|
||||
" #elif defined(ONLY_TC_FACTOR)\r\n" + //
|
||||
" onlyTeamColorFactor();\r\n" + //
|
||||
" #elif defined(ONLY_EMISSIVE)\r\n" + //
|
||||
" onlyEmissiveMap();\r\n" + //
|
||||
" #elif defined(ONLY_TEXCOORDS)\r\n" + //
|
||||
" onlyTexCoords();\r\n" + //
|
||||
" #elif defined(ONLY_NORMALS)\r\n" + //
|
||||
" onlyNormals();\r\n" + //
|
||||
" #elif defined(ONLY_TANGENTS)\r\n" + //
|
||||
" onlyTangents();\r\n" + //
|
||||
" #else\r\n" + //
|
||||
" lambert();\r\n" + //
|
||||
" #endif\r\n" + //
|
||||
"}";
|
||||
}
|
||||
|
||||
public static final String vsSimple = "\r\n" + //
|
||||
" uniform mat4 u_VP;\r\n" + //
|
||||
|
@ -55,4 +55,9 @@ public class MdxSimpleInstance extends BatchedInstance {
|
||||
this.replaceableTextures[replaceableTextureId] = (Texture) this.model.viewer.load(replaceableTextureFile,
|
||||
PathSolver.DEFAULT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceableTextureHD(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,14 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler.ShaderEnvironmentTy
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.W3xScenePortraitLightManager;
|
||||
|
||||
public class MdxViewer extends AbstractMdxModelViewer {
|
||||
public static ShaderEnvironmentType DEFAULT_SHADER_ENV = ShaderEnvironmentType.MENU;
|
||||
|
||||
private final WorldEditStrings worldEditStrings;
|
||||
private final Vector3 defaultLighting;
|
||||
|
||||
public MdxViewer(final DataSource dataSource, final CanvasProvider canvas, final Vector3 defaultLighting) {
|
||||
super(dataSource, canvas);
|
||||
MdxHandler.CURRENT_SHADER_TYPE = ShaderEnvironmentType.MENU;
|
||||
MdxHandler.CURRENT_SHADER_TYPE = DEFAULT_SHADER_ENV;
|
||||
this.defaultLighting = defaultLighting;
|
||||
this.worldEditStrings = new WorldEditStrings(this.dataSource);
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ import com.etheller.warsmash.util.RenderMathUtils;
|
||||
import com.hiveworkshop.rms.parsers.mdlx.MdlxGeoset;
|
||||
|
||||
public class SetupGeosets {
|
||||
private static final int NORMAL_BATCH = 0;
|
||||
private static final int EXTENDED_BATCH = 1;
|
||||
private static final int REFORGED_BATCH = 2;
|
||||
|
||||
public static void setupGeosets(final MdxModel model, final List<MdlxGeoset> geosets, final boolean bigNodeSpace) {
|
||||
if (geosets.size() > 0) {
|
||||
@ -19,9 +16,10 @@ public class SetupGeosets {
|
||||
int positionBytes = 0;
|
||||
int normalBytes = 0;
|
||||
int uvBytes = 0;
|
||||
int tangentBytes = 0;
|
||||
int skinBytes = 0;
|
||||
int faceBytes = 0;
|
||||
final int[] batchTypes = new int[geosets.size()];
|
||||
final SkinningType[] batchTypes = new SkinningType[geosets.size()];
|
||||
|
||||
final int extendedBatchStride = bigNodeSpace ? 36 : 9;
|
||||
final int normalBatchStride = bigNodeSpace ? 20 : 5;
|
||||
@ -32,17 +30,21 @@ public class SetupGeosets {
|
||||
for (int i = 0, l = geosets.size(); i < l; i++) {
|
||||
final MdlxGeoset geoset = geosets.get(i);
|
||||
|
||||
if (true /* geoset.getLod() == 0 */) {
|
||||
if ((geoset.lod == 0) || (geoset.lod == -1)) {
|
||||
final int vertices = geoset.getVertices().length / 3;
|
||||
|
||||
positionBytes += vertices * 12;
|
||||
normalBytes += vertices * 12;
|
||||
uvBytes += geoset.getUvSets().length * vertices * 8;
|
||||
|
||||
if (false /* geoset.skin.length */) {
|
||||
if (geoset.tangents != null) {
|
||||
tangentBytes += vertices * 16;
|
||||
}
|
||||
|
||||
if (geoset.skin != null) {
|
||||
skinBytes += vertices * 8;
|
||||
|
||||
batchTypes[i] = REFORGED_BATCH;
|
||||
batchTypes[i] = SkinningType.Skin;
|
||||
}
|
||||
else {
|
||||
long biggestGroup = 0;
|
||||
@ -56,12 +58,12 @@ public class SetupGeosets {
|
||||
if (biggestGroup > 4) {
|
||||
skinBytes += vertices * extendedBatchStride;
|
||||
|
||||
batchTypes[i] = EXTENDED_BATCH;
|
||||
batchTypes[i] = SkinningType.ExtendedVertexGroups;
|
||||
}
|
||||
else {
|
||||
skinBytes += vertices * normalBatchStride;
|
||||
|
||||
batchTypes[i] = NORMAL_BATCH;
|
||||
batchTypes[i] = SkinningType.VertexGroups;
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +74,8 @@ public class SetupGeosets {
|
||||
int positionOffset = 0;
|
||||
int normalOffset = positionOffset + positionBytes;
|
||||
int uvOffset = normalOffset + normalBytes;
|
||||
int skinOffset = uvOffset + uvBytes;
|
||||
int tangentOffset = uvOffset + uvBytes;
|
||||
int skinOffset = tangentOffset + tangentBytes;
|
||||
int faceOffset = 0;
|
||||
|
||||
model.arrayBuffer = gl.glGenBuffer();
|
||||
@ -86,11 +89,12 @@ public class SetupGeosets {
|
||||
for (int i = 0, l = geosets.size(); i < l; i++) {
|
||||
final MdlxGeoset geoset = geosets.get(i);
|
||||
|
||||
final int batchType = batchTypes[i];
|
||||
if (true /* geoset.lod == 0 */) {
|
||||
final SkinningType batchType = batchTypes[i];
|
||||
if ((geoset.lod == 0) || (geoset.lod == -1)) {
|
||||
final float[] positions = geoset.getVertices();
|
||||
final float[] normals = geoset.getNormals();
|
||||
final float[][] uvSets = geoset.getUvSets();
|
||||
final float[] tangents = geoset.getTangents();
|
||||
final int[] faces = geoset.getFaces();
|
||||
int[] skin = null;
|
||||
final int vertices = geoset.getVertices().length / 3;
|
||||
@ -98,7 +102,7 @@ public class SetupGeosets {
|
||||
int maxBones;
|
||||
int skinStride;
|
||||
int boneCountOffsetBytes;
|
||||
if (batchType == EXTENDED_BATCH) {
|
||||
if (batchType == SkinningType.ExtendedVertexGroups) {
|
||||
maxBones = 8;
|
||||
skinStride = extendedBatchStride;
|
||||
boneCountOffsetBytes = extendedBatchBoneCountOffsetBytes;
|
||||
@ -109,8 +113,11 @@ public class SetupGeosets {
|
||||
boneCountOffsetBytes = normalBatchBoneCountOffsetBytes;
|
||||
}
|
||||
|
||||
if (batchType == REFORGED_BATCH) {
|
||||
// skin = geoset.skin; // THIS IS NOT IMPLEMENTED
|
||||
if (batchType == SkinningType.Skin) {
|
||||
skin = new int[geoset.skin.length];
|
||||
for (int j = 0; j < geoset.skin.length; j++) {
|
||||
skin[j] = geoset.skin[j];
|
||||
}
|
||||
}
|
||||
else {
|
||||
final long[] matrixIndices = geoset.getMatrixIndices();
|
||||
@ -157,20 +164,20 @@ public class SetupGeosets {
|
||||
|
||||
final boolean unselectable = geoset.getSelectionFlags() == 4;
|
||||
final Geoset vGeoset = new Geoset(model, model.getGeosets().size(), positionOffset, normalOffset,
|
||||
uvOffset, skinOffset, faceOffset, vertices, faces.length, openGLSkinType, skinStride,
|
||||
boneCountOffsetBytes, unselectable, geoset);
|
||||
uvOffset, tangentOffset, skinOffset, faceOffset, vertices, faces.length, openGLSkinType,
|
||||
skinStride, boneCountOffsetBytes, unselectable, geoset);
|
||||
|
||||
model.getGeosets().add(vGeoset);
|
||||
|
||||
if (batchType == REFORGED_BATCH) {
|
||||
throw new UnsupportedOperationException("NYI");
|
||||
// model.batches.add(new Reforged)
|
||||
final Material material = model.materials.get((int) geoset.getMaterialId());
|
||||
final boolean isHd = "Shader_HD_DefaultUnit".equals(material.shader);
|
||||
|
||||
if (isHd) {
|
||||
model.batches.add(new Batch(model.batches.size(), vGeoset, material, batchType));
|
||||
}
|
||||
else {
|
||||
final boolean isExtended = batchType == EXTENDED_BATCH;
|
||||
|
||||
for (final Layer layer : model.getMaterials().get((int) geoset.getMaterialId()).layers) {
|
||||
model.batches.add(new Batch(model.batches.size(), vGeoset, layer, isExtended));
|
||||
model.batches.add(new Batch(model.batches.size(), vGeoset, layer, batchType));
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +197,12 @@ public class SetupGeosets {
|
||||
uvOffset += uvSet.length * 4;
|
||||
}
|
||||
|
||||
if (tangents != null) {
|
||||
gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, tangentOffset, tangents.length,
|
||||
RenderMathUtils.wrap(tangents));
|
||||
tangentOffset += tangents.length * 4;
|
||||
}
|
||||
|
||||
// Skin.
|
||||
gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, skinOffset, skin.length,
|
||||
bigNodeSpace ? RenderMathUtils.wrap(skin) : RenderMathUtils.wrapAsBytes(skin));
|
||||
|
@ -64,7 +64,8 @@ public class SetupGroups {
|
||||
|
||||
public static boolean matchingGroup(final Object group, final Object object) {
|
||||
if (group instanceof BatchGroup) {
|
||||
return (object instanceof Batch) && (((Batch) object).isExtended == ((BatchGroup) group).isExtended);
|
||||
return (object instanceof Batch) && (((Batch) object).skinningType == ((BatchGroup) group).skinningType)
|
||||
&& (((Batch) object).hd == ((BatchGroup) group).hd);
|
||||
// } else if(group instanceof ReforgedBatch) { TODO
|
||||
// return (object instanceof ReforgedBatch) && (object.material.shader === group.shader);
|
||||
}
|
||||
@ -76,7 +77,7 @@ public class SetupGroups {
|
||||
|
||||
public static GenericGroup createMatchingGroup(final MdxModel model, final Object object) {
|
||||
if (object instanceof Batch) {
|
||||
return new BatchGroup(model, ((Batch) object).isExtended);
|
||||
return new BatchGroup(model, ((Batch) object).skinningType, ((Batch) object).hd);
|
||||
// } else if(object instanceof ReforgedBatch) { TODO
|
||||
// return new ReforgedBatchGroup(model, ((ReforgedBatch)object).material.shader);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class SetupSimpleGroups {
|
||||
GenericGroup simpleGroup;
|
||||
|
||||
if (group instanceof BatchGroup) {
|
||||
simpleGroup = new BatchGroup(model, ((BatchGroup) group).isExtended);
|
||||
simpleGroup = new BatchGroup(model, ((BatchGroup) group).skinningType, ((BatchGroup) group).hd);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("reforged?"); // TODO
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.mdx;
|
||||
|
||||
public enum SkinningType {
|
||||
Skin,
|
||||
ExtendedVertexGroups,
|
||||
VertexGroups;
|
||||
}
|
@ -55,6 +55,7 @@ public class RenderDestructable extends RenderDoodad implements RenderWidget {
|
||||
this.replaceableTextureFile += "Blight";
|
||||
}
|
||||
this.instance.setReplaceableTexture(this.replaceableTextureId, this.replaceableTextureFile + ".blp");
|
||||
this.instance.setReplaceableTextureHD(this.replaceableTextureId, this.replaceableTextureFile);
|
||||
}
|
||||
this.selectionScale *= row.getFieldAsFloat(SEL_CIRCLE_SIZE, 0);
|
||||
this.unitAnimationListenerImpl = new UnitAnimationListenerImpl((MdxComplexInstance) this.instance, 0, 0);
|
||||
|
@ -6,11 +6,14 @@ import javax.swing.UIManager;
|
||||
import com.etheller.warsmash.desktop.DesktopLauncher;
|
||||
import com.etheller.warsmash.desktop.editor.mdx.ui.YseraFrame;
|
||||
import com.etheller.warsmash.units.DataTable;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler.ShaderEnvironmentType;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
|
||||
|
||||
public class MdxEditorMain {
|
||||
|
||||
public static void main(final String[] args) {
|
||||
DesktopLauncher.loadExtensions();
|
||||
MdxViewer.DEFAULT_SHADER_ENV = ShaderEnvironmentType.GAME;
|
||||
|
||||
try {
|
||||
// UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
|
||||
|
@ -38,7 +38,7 @@ public class JassArrayedAssignmentStatement implements JassStatement {
|
||||
if (arrayValue != null) {
|
||||
final Integer indexInt = index.visit(IntegerJassValueVisitor.getInstance());
|
||||
if ((indexInt != null) && (indexInt >= 0)) {
|
||||
arrayValue.set(indexInt, this.expression.evaluate(globalScope, localScope, triggerScope));
|
||||
arrayValue.set(globalScope, indexInt, this.expression.evaluate(globalScope, localScope, triggerScope));
|
||||
}
|
||||
else {
|
||||
throw new JassException(globalScope,
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.etheller.interpreter.ast.statement;
|
||||
|
||||
import com.etheller.interpreter.ast.Assignable;
|
||||
import com.etheller.interpreter.ast.debug.JassException;
|
||||
import com.etheller.interpreter.ast.expression.JassExpression;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.scope.LocalScope;
|
||||
@ -11,7 +10,6 @@ import com.etheller.interpreter.ast.value.JassValue;
|
||||
public class JassSetStatement implements JassStatement {
|
||||
private final String identifier;
|
||||
private final JassExpression expression;
|
||||
private static JassException zeroGuy = null;
|
||||
|
||||
public JassSetStatement(final String identifier, final JassExpression expression) {
|
||||
this.identifier = identifier;
|
||||
|
@ -2,6 +2,8 @@ package com.etheller.interpreter.ast.value;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.etheller.interpreter.ast.debug.JassException;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.util.JassSettings;
|
||||
import com.etheller.interpreter.ast.value.visitor.JassTypeGettingValueVisitor;
|
||||
|
||||
@ -33,7 +35,7 @@ public class ArrayJassValue implements JassValue {
|
||||
return visitor.accept(this);
|
||||
}
|
||||
|
||||
public void set(final int index, JassValue value) {
|
||||
public void set(final GlobalScope globalScope, final int index, JassValue value) {
|
||||
final JassType primitiveType = this.type.getPrimitiveType();
|
||||
if (value == null) {
|
||||
if (primitiveType.isNullable()) {
|
||||
@ -49,6 +51,10 @@ public class ArrayJassValue implements JassValue {
|
||||
throw new IllegalStateException("Illegal type for assignment to " + primitiveType.getName() + " array: "
|
||||
+ (valueType == null ? "null" : valueType.getName()));
|
||||
}
|
||||
if (index >= this.data.length) {
|
||||
throw new JassException(globalScope, "Max jass array size exceeded",
|
||||
new ArrayIndexOutOfBoundsException(index));
|
||||
}
|
||||
this.data[index] = value;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user