Basic map viewer and basic portrait

This commit is contained in:
Retera 2020-01-24 00:59:18 -06:00
parent 46942c2d8d
commit 67e37244bd
10 changed files with 176 additions and 27 deletions

View File

@ -73,12 +73,16 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
this.cameraManager = new CameraManager();
this.cameraManager.setupCamera(scene);
this.mainModel = (MdxModel) this.viewer.load("Buildings\\Undead\\Necropolis\\Necropolis.mdx", new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\MainMenu\\MainMenu3D_exp\\MainMenu3D_exp.mdx",
this.mainModel = (MdxModel) this.viewer.load("Units\\NightElf\\DruidOfTheClaw\\DruidOfTheClaw_Portrait.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
this.modelCamera = this.mainModel.cameras.get(0);
this.mainInstance = (MdxComplexInstance) this.mainModel.addInstance(0);
@ -343,6 +347,9 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
private int frame = 0;
private MdxComplexInstance mainInstance;
private MdxModel mainModel;
private com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
private final float[] cameraPositionTemp = new float[3];
private final float[] cameraTargetTemp = new float[3];
@Override
public void render() {
@ -406,6 +413,7 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
private Vector3 target;
private Vector3 worldUp;
private Vector3 vecHeap;
private Vector3 vecHeap2;
private Quaternion quatHeap;
private Quaternion quatHeap2;
@ -427,6 +435,7 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
this.target = new Vector3(0, 0, 50);
this.worldUp = new Vector3(0, 0, 1);
this.vecHeap = new Vector3();
this.vecHeap2 = new Vector3();
this.quatHeap = new Quaternion();
this.quatHeap2 = new Quaternion();
@ -451,6 +460,34 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
this.quatHeap.transform(this.position);
this.position.scl(this.distance);
this.position = this.position.add(this.target);
if (WarsmashGdxGame.this.modelCamera != null) {
WarsmashGdxGame.this.modelCamera.getPositionTranslation(WarsmashGdxGame.this.cameraPositionTemp,
WarsmashGdxGame.this.mainInstance.sequence, WarsmashGdxGame.this.mainInstance.frame,
WarsmashGdxGame.this.mainInstance.counter);
WarsmashGdxGame.this.modelCamera.getTargetTranslation(WarsmashGdxGame.this.cameraTargetTemp,
WarsmashGdxGame.this.mainInstance.sequence, WarsmashGdxGame.this.mainInstance.frame,
WarsmashGdxGame.this.mainInstance.counter);
this.position.set(WarsmashGdxGame.this.modelCamera.position);
this.target.set(WarsmashGdxGame.this.modelCamera.targetPosition);
// this.vecHeap2.set(this.target);
// this.vecHeap2.sub(this.position);
// this.vecHeap.set(this.vecHeap2);
// this.vecHeap.crs(this.worldUp);
// this.vecHeap.crs(this.vecHeap2);
// this.vecHeap.nor();
// this.vecHeap.scl(this.camera.rect.height / 2f);
// this.position.add(this.vecHeap);
this.position.add(WarsmashGdxGame.this.cameraPositionTemp[0],
WarsmashGdxGame.this.cameraPositionTemp[1], WarsmashGdxGame.this.cameraPositionTemp[2]);
this.target.add(WarsmashGdxGame.this.cameraTargetTemp[0], WarsmashGdxGame.this.cameraTargetTemp[1],
WarsmashGdxGame.this.cameraTargetTemp[2]);
this.camera.perspective(WarsmashGdxGame.this.modelCamera.fieldOfView,
Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight(),
WarsmashGdxGame.this.modelCamera.nearClippingPlane,
WarsmashGdxGame.this.modelCamera.farClippingPlane);
}
this.camera.moveToAndFace(this.position, this.target, this.worldUp);
}

View File

@ -11,6 +11,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Quaternion;
@ -23,7 +24,11 @@ import com.etheller.warsmash.datasources.DataSourceDescriptor;
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
import com.etheller.warsmash.viewer5.Camera;
import com.etheller.warsmash.viewer5.CanvasProvider;
import com.etheller.warsmash.viewer5.PathSolver;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.SolvedPath;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProvider, InputProcessor {
@ -34,6 +39,11 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
private BitmapFont font;
private SpriteBatch batch;
private CameraManager portraitCameraManager;
private MdxModel portraitModel;
private MdxComplexInstance portraitInstance;
private final float[] cameraPositionTemp = new float[3];
private final float[] cameraTargetTemp = new float[3];
@Override
public void create() {
@ -74,7 +84,35 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
this.cameraManager.setupCamera(this.viewer.worldScene);
System.out.println("Loaded");
Gdx.gl30.glClearColor(0.5f, 0.5f, 0.5f, 1); // TODO remove white background
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1); // TODO remove white background
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
this.portraitScene = this.viewer.addScene();
this.portraitCameraManager = new CameraManager();
this.portraitCameraManager.setupCamera(this.portraitScene);
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\MainMenu\\MainMenu3D_exp\\MainMenu3D_exp.mdx",
this.portraitModel = (MdxModel) this.viewer.load("Units\\NightElf\\Runner\\Runner_Portrait.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
this.portraitCameraManager.modelCamera = this.portraitModel.cameras.get(0);
this.portraitScene.camera.viewport(new Rectangle(100, 0, 100, 100));
this.portraitInstance = (MdxComplexInstance) this.portraitModel.addInstance(0);
this.portraitInstance.setTeamColor(1);
this.portraitInstance.setScene(this.portraitScene);
final int animIndex = 0;
this.portraitInstance.setSequence(animIndex);
this.portraitInstance.setSequenceLoopMode(0);
this.font = new BitmapFont();
this.batch = new SpriteBatch();
@ -87,6 +125,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
this.cameraManager.target.add(this.cameraVelocity.x, this.cameraVelocity.y, 0);
this.cameraManager.updateCamera();
this.portraitCameraManager.updateCamera();
this.viewer.updateAndRender();
// gl.glDrawElements(GL20.GL_TRIANGLES, this.elements, GL20.GL_UNSIGNED_SHORT, this.faceOffset);
@ -94,6 +133,11 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
// this.batch.begin();
// this.font.draw(this.batch, Integer.toString(Gdx.graphics.getFramesPerSecond()), 0, 0);
// this.batch.end();
if (this.portraitInstance.sequenceEnded) {
this.portraitInstance
.setSequence((this.portraitInstance.sequence + 1) % this.portraitModel.getSequences().size());
}
}
@Override
@ -112,12 +156,22 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
@Override
public void resize(final int width, final int height) {
this.tempRect.x = 0;
this.tempRect.y = 0;
this.tempRect.width = width;
this.tempRect.height = height;
this.cameraManager.camera.viewport(this.tempRect);
final float portraitTestWidth = (100 / 640f) * width;
final float portraitTestHeight = (100 / 480f) * height;
this.tempRect.x = portraitTestWidth;
this.tempRect.y = 0;
this.tempRect.width = portraitTestWidth;
this.tempRect.height = portraitTestHeight;
this.portraitScene.camera.viewport(this.tempRect);
}
class CameraManager {
public com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
private CanvasProvider canvas;
private Camera camera;
private float moveSpeed;
@ -175,6 +229,27 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
this.quatHeap.transform(this.position);
this.position.scl(this.distance);
this.position = this.position.add(this.target);
if (this.modelCamera != null) {
this.modelCamera.getPositionTranslation(WarsmashGdxMapGame.this.cameraPositionTemp,
WarsmashGdxMapGame.this.portraitInstance.sequence,
WarsmashGdxMapGame.this.portraitInstance.frame,
WarsmashGdxMapGame.this.portraitInstance.counter);
this.modelCamera.getTargetTranslation(WarsmashGdxMapGame.this.cameraTargetTemp,
WarsmashGdxMapGame.this.portraitInstance.sequence,
WarsmashGdxMapGame.this.portraitInstance.frame,
WarsmashGdxMapGame.this.portraitInstance.counter);
this.position.set(this.modelCamera.position);
this.target.set(this.modelCamera.targetPosition);
this.position.add(WarsmashGdxMapGame.this.cameraPositionTemp[0],
WarsmashGdxMapGame.this.cameraPositionTemp[1], WarsmashGdxMapGame.this.cameraPositionTemp[2]);
this.target.add(WarsmashGdxMapGame.this.cameraTargetTemp[0],
WarsmashGdxMapGame.this.cameraTargetTemp[1], WarsmashGdxMapGame.this.cameraTargetTemp[2]);
this.camera.perspective(this.modelCamera.fieldOfView,
Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight(), this.modelCamera.nearClippingPlane,
this.modelCamera.farClippingPlane);
}
this.camera.moveToAndFace(this.position, this.target, this.worldUp);
}
@ -186,6 +261,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
private final float cameraSpeed = 10.0f;
private final Vector2 cameraVelocity = new Vector2();
private Scene portraitScene;
@Override
public boolean keyDown(final int keycode) {

View File

@ -255,7 +255,7 @@ public class Scene {
// If this scene doesn't want alpha, clear it.
if (!this.alpha) {
gl.glDepthMask(true);
gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
gl.glClear(GL20.GL_DEPTH_BUFFER_BIT | GL20.GL_COLOR_BUFFER_BIT);
}
}

View File

@ -1,15 +1,16 @@
package com.etheller.warsmash.viewer5.handlers.mdx;
import com.etheller.warsmash.parsers.mdlx.AnimationMap;
import com.etheller.warsmash.util.RenderMathUtils;
public class Camera extends AnimatedObject {
private final String name;
private final float[] position;
private final float fieldOfView;
private final float farClippingPlane;
private final float nearClippingPlane;
private final float[] targetPosition;
public final String name;
public final float[] position;
public final float fieldOfView;
public final float farClippingPlane;
public final float nearClippingPlane;
public final float[] targetPosition;
public Camera(final MdxModel model, final com.etheller.warsmash.parsers.mdlx.Camera camera) {
super(model, camera);
@ -23,11 +24,13 @@ public class Camera extends AnimatedObject {
}
public int getPositionTranslation(final float[] out, final int sequence, final int frame, final int counter) {
return this.getVectorValue(out, AnimationMap.KCTR.getWar3id(), sequence, frame, counter, this.position);
return this.getVectorValue(out, AnimationMap.KCTR.getWar3id(), sequence, frame, counter,
RenderMathUtils.FLOAT_VEC3_ZERO);
}
public int getTargetTranslation(final float[] out, final int sequence, final int frame, final int counter) {
return this.getVectorValue(out, AnimationMap.KTTR.getWar3id(), sequence, frame, counter, this.targetPosition);
return this.getVectorValue(out, AnimationMap.KTTR.getWar3id(), sequence, frame, counter,
RenderMathUtils.FLOAT_VEC3_ZERO);
}
public int getRotation(final float[] out, final int sequence, final int frame, final int counter) {

View File

@ -16,6 +16,7 @@ import com.etheller.warsmash.viewer5.Node;
import com.etheller.warsmash.viewer5.RenderBatch;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.SkeletalNode;
import com.etheller.warsmash.viewer5.Texture;
import com.etheller.warsmash.viewer5.TextureMapper;
import com.etheller.warsmash.viewer5.UpdatableObject;
import com.etheller.warsmash.viewer5.gl.DataTexture;
@ -58,6 +59,7 @@ public class MdxComplexInstance extends ModelInstance {
public Matrix4[] worldMatrices;
public FloatBuffer worldMatricesCopyHeap;
public DataTexture boneTexture;
public Texture[] replaceableTextures = new Texture[64];
public MdxComplexInstance(final MdxModel model) {
super(model);

View File

@ -347,4 +347,8 @@ public class MdxModel extends com.etheller.warsmash.viewer5.Model<MdxHandler> {
}
public List<Camera> getCameras() {
return this.cameras;
}
}

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x;
import com.badlogic.gdx.math.Quaternion;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
import com.etheller.warsmash.util.RenderMathUtils;
import com.etheller.warsmash.viewer5.ModelInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
@ -11,7 +12,7 @@ public class Doodad {
private final MutableGameObject row;
public Doodad(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad) {
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type) {
final boolean isSimple = row.readSLKTagBoolean("lightweight");
ModelInstance instance;
@ -25,6 +26,10 @@ public class Doodad {
instance.move(doodad.getLocation());
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, doodad.getAngle()));
instance.scale(doodad.getScale());
if (type == WorldEditorDataType.DOODADS) {
final float defScale = row.readSLKTagFloat("defScale");
instance.uniformScale(defScale);
}
instance.setScene(map.worldScene);
this.instance = instance;

View File

@ -47,6 +47,8 @@ import mpq.MPQArchive;
import mpq.MPQException;
public class War3MapViewer extends ModelViewer {
private static final War3ID UNIT_FILE = War3ID.fromString("umdl");
private static final War3ID ITEM_FILE = War3ID.fromString("ifil");
private static final War3ID sloc = War3ID.fromString("sloc");
private static final LoadGenericCallback stringDataCallback = new StringDataCallbackImplementation();
public static final StreamDataCallbackImplementation streamDataCallback = new StreamDataCallbackImplementation();
@ -253,10 +255,11 @@ public class War3MapViewer extends ModelViewer {
final War3MapDoo doo = this.mapMpq.readDoodads();
for (final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad : doo.getDoodads()) {
WorldEditorDataType type = WorldEditorDataType.DOODADS;
MutableGameObject row = modifications.getDoodads().get(doodad.getId());
if (row == null) {
row = modifications.getDestructibles().get(doodad.getId());
type = WorldEditorDataType.DESTRUCTIBLES;
}
String file = row.readSLKTag("file");
final int numVar = row.readSLKTagInt("numVar");
@ -294,7 +297,7 @@ public class War3MapViewer extends ModelViewer {
model = (MdxModel) this.load(fileVar, this.mapPathSolver, this.solverParams);
}
this.doodads.add(new Doodad(this, model, row, doodad));
this.doodads.add(new Doodad(this, model, row, doodad, type));
}
// Cliff/Terrain doodads.
@ -341,10 +344,19 @@ public class War3MapViewer extends ModelViewer {
row = modifications.getUnits().get(unit.getId());
if (row == null) {
row = modifications.getItems().get(unit.getId());
}
path = row.getFieldAsString(ITEM_FILE, 0);
if (row != null) {
path = row.readSLKTag("file");
if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) {
path = path.substring(0, path.length() - 4);
}
if (row.readSLKTagInt("fileVerFlags") == 2) {
path += "_V1";
}
path += ".mdx";
}
else {
path = row.getFieldAsString(UNIT_FILE, 0);
if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) {
path = path.substring(0, path.length() - 4);
@ -402,6 +414,15 @@ public class War3MapViewer extends ModelViewer {
worldScene.renderOpaque();
this.terrain.renderWater();
worldScene.renderTranslucent();
final List<Scene> scenes = this.scenes;
for (final Scene scene : scenes) {
if (scene != worldScene) {
scene.startFrame();
scene.renderOpaque();
scene.renderTranslucent();
}
}
}
}

View File

@ -302,9 +302,9 @@ public class Terrain {
updateGroundHeights(new Rectangle(0, 0, width - 1, height - 1));
this.groundShader = webGL.createShaderProgram(HiveWEShaders.Terrain.vert, HiveWEShaders.Terrain.frag);
this.cliffShader = webGL.createShaderProgram(HiveWEShaders.Cliffs.vert, HiveWEShaders.Cliffs.frag);
this.waterShader = webGL.createShaderProgram(HiveWEShaders.Water.vert, HiveWEShaders.Water.frag);
this.groundShader = webGL.createShaderProgram(TerrainShaders.Terrain.vert, TerrainShaders.Terrain.frag);
this.cliffShader = webGL.createShaderProgram(TerrainShaders.Cliffs.vert, TerrainShaders.Cliffs.frag);
this.waterShader = webGL.createShaderProgram(TerrainShaders.Water.vert, TerrainShaders.Water.frag);
// TODO collision bodies (?)
@ -649,6 +649,7 @@ public class Terrain {
this.webGL.useShaderProgram(this.groundShader);
final GL30 gl = Gdx.gl30;
gl.glDisable(GL30.GL_CULL_FACE);
gl.glDisable(GL30.GL_BLEND);
gl.glUniformMatrix4fv(this.groundShader.getUniformLocation("MVP"), 1, false,

View File

@ -1,6 +1,6 @@
package com.etheller.warsmash.viewer5.handlers.w3x.environment;
public class HiveWEShaders {
public class TerrainShaders {
public static final class Cliffs {
private Cliffs() {
}
@ -273,7 +273,7 @@ public class HiveWEShaders {
" gl_Position = is_water ? MVP * vec4((vPosition.x + pos.x)*128.0 + centerOffsetX, (vPosition.y + pos.y)*128.0 + centerOffsetY, water_height*128.0, 1) : vec4(2.0, 0.0, 0.0, 1.0);\r\n"
+ //
"\r\n" + //
" UV = vec2(vPosition.x, 1 - vPosition.y);\r\n" + //
" UV = vec2(vPosition.x, vPosition.y);\r\n" + //
"\r\n" + //
" float ground_height = texelFetch(ground_height_texture, height_pos, 0).r;\r\n" + //
" float value = clamp(water_height - ground_height, 0.f, 1.f);\r\n" + //