/**
* Copyright (C) 2013 Gundog Studios LLC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gundogstudios.models;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.HashMap;
import java.util.HashSet;
import com.gundogstudios.models.md2.MD2Parser;
import com.gundogstudios.models.tristripper.PrimitiveGroup;
import com.gundogstudios.models.tristripper.TriStrip;
public class SingleGSWriter {
private static final String LOCATION = "D:/Users/Joe/Documents/TowerDefenseWars/Graphics/Processed 3D Models/GS1/";
private static final String EXTENSION = ".gs1";
private static final short DEFAULT_ANIMATION_LENGTH = 1000;
private static final String ARCHER_HORSEMEN = "ArcherHorsemen";
private static final String ARCHERS = "Archers";
private static final String ARROW_PROJECTILES = "ArrowProjectiles";
private static final String BALL_PROJECTILES = "BallProjectiles";
private static final String BALLISTAS = "Ballistas";
private static final String BASE = "Base";
private static final String BEARS = "Bears";
private static final String BIRDS = "Birds";
private static final String BLADE = "Blade";
private static final String CACTUS = "Cactus";
private static final String CANNONS = "Cannons";
private static final String CATAPULTS = "Catapults";
private static final String CRYSTALLIZERS = "Crystallizers";
private static final String DEAD_HORSEMEN = "DeadHorsemen";
private static final String DEAD_SOLDIERS = "DeadSoldiers";
private static final String DRAGONS = "Dragons";
private static final String EMITTERS = "Emitters";
private static final String FEMALE_ANGELS = "FemaleAngels";
private static final String FEMALE_MAGES = "FemaleMages";
private static final String GOLEMS = "Golems";
private static final String HORSEMEN = "Horsemen";
private static final String HORSES = "Horses";
private static final String HUMANOIDS = "Humanoids";
private static final String HUMANOID_BEASTS = "HumanoidBeasts";
private static final String MAGES = "Mages";
private static final String MALE_ANGELS = "MaleAngels";
private static final String PILLARS = "Pillars";
private static final String ROCK = "Rock";
private static final String RUBBLE = "Rubble";
private static final String SOLDIERS = "Soldiers";
private static final String STATUES = "Statues";
private static final String TREE = "Tree";
private static final String WALL_CORNER = "WallCorner";
private static final String WALL_SIDE = "WallSide";
private static final String WHIP = "Whip";
private static final String[] MODELS = { ARCHER_HORSEMEN, ARCHERS, BALLISTAS, BASE, BEARS, BIRDS, BLADE, CACTUS,
CANNONS, CATAPULTS, CRYSTALLIZERS, DEAD_HORSEMEN, DEAD_SOLDIERS, DRAGONS, EMITTERS, FEMALE_ANGELS,
FEMALE_MAGES, GOLEMS, HORSEMEN, HORSES, HUMANOIDS, HUMANOID_BEASTS, MAGES, MALE_ANGELS, PILLARS,
BALL_PROJECTILES, ARROW_PROJECTILES, ROCK, RUBBLE, SOLDIERS, STATUES, TREE, WALL_CORNER, WALL_SIDE, WHIP };
private static final HashSet<String> REDUCE_IDLE = new HashSet<String>();
private static final HashSet<String> FLIP_AXIS = new HashSet<String>();
private static final HashMap<String, Integer> IDLE_ANIMATION_LENGTH = new HashMap<String, Integer>();
private static final HashMap<String, Integer> MOVE_ANIMATION_LENGTH = new HashMap<String, Integer>();
private static final HashMap<String, Integer> DEATH_ANIMATION_LENGTH = new HashMap<String, Integer>();
private static final HashMap<String, Integer> ATTACK_ANIMATION_LENGTH = new HashMap<String, Integer>();
static {
REDUCE_IDLE.add(ARROW_PROJECTILES);
REDUCE_IDLE.add(BALL_PROJECTILES);
REDUCE_IDLE.add(BALLISTAS);
REDUCE_IDLE.add(BASE);
REDUCE_IDLE.add(BLADE);
REDUCE_IDLE.add(CACTUS);
REDUCE_IDLE.add(CANNONS);
REDUCE_IDLE.add(CATAPULTS);
// REDUCE_IDLE.add(CRYSTALLIZERS);
REDUCE_IDLE.add(EMITTERS);
REDUCE_IDLE.add(PILLARS);
REDUCE_IDLE.add(ROCK);
REDUCE_IDLE.add(STATUES);
REDUCE_IDLE.add(TREE);
REDUCE_IDLE.add(WALL_CORNER);
REDUCE_IDLE.add(WALL_SIDE);
// REDUCE_IDLE.add(WHIP);
FLIP_AXIS.add(BALLISTAS);
IDLE_ANIMATION_LENGTH.put(DEAD_SOLDIERS, 1500);
IDLE_ANIMATION_LENGTH.put(HUMANOID_BEASTS, 1500);
IDLE_ANIMATION_LENGTH.put(FEMALE_MAGES, 1500);
IDLE_ANIMATION_LENGTH.put(DRAGONS, 2000);
IDLE_ANIMATION_LENGTH.put(CRYSTALLIZERS, 4000);
IDLE_ANIMATION_LENGTH.put(WHIP, 4000);
ATTACK_ANIMATION_LENGTH.put(DEAD_SOLDIERS, 1500);
ATTACK_ANIMATION_LENGTH.put(ARCHERS, 1500);
ATTACK_ANIMATION_LENGTH.put(GOLEMS, 1500);
ATTACK_ANIMATION_LENGTH.put(BIRDS, 2000);
ATTACK_ANIMATION_LENGTH.put(DRAGONS, 2000);
MOVE_ANIMATION_LENGTH.put(BIRDS, 2000);
MOVE_ANIMATION_LENGTH.put(DRAGONS, 2000);
}
public static void main(String[] argv) throws Exception {
for (String model : MODELS)
writeModel(model);
// writeModel(BALLISTAS);
// writeModel(CACTUS);
// writeModel(WALL_CORNER);
// writeModel(WALL_SIDE);
}
private static void writeModel(String baseName) throws Exception {
System.out.println("Writing: " + baseName);
CombinedModel model = MD2Parser.parseReduced(baseName);
if (REDUCE_IDLE.contains(baseName)) {
System.out.println("Reducing idle for " + baseName + " from " + model.getFloatIdleVertices().length);
float[][] vertices = new float[][] { model.getFloatIdleVertices()[0] };
model.setIdleVertices(vertices);
}
if (FLIP_AXIS.contains(baseName)) {
model.flipZAxis();
}
TriStrip strip = new TriStrip();
PrimitiveGroup[] groups = strip.generateStrips(model.getShortIndices());
short[] sindices = new short[groups[0].indices.length];
for (int i = 0; i < sindices.length; i++) {
sindices[i] = (short) groups[0].indices[i];
}
model.setIndices(sindices);
ReducedModel reduced = model.asReducedModel();
writeModel(baseName, reduced);
}
private static void writeModel(String baseName, ReducedModel model) throws IOException {
OutputStream output = new FileOutputStream(LOCATION + baseName + EXTENSION);
write(output, baseName, model);
write(output, model.getIndices());
write(output, model.getUVs());
writeVertices(output, model.getIdleVertices());
writeVertices(output, model.getMoveVertices());
writeVertices(output, model.getAttackVertices());
writeVertices(output, model.getDeathVertices());
output.close();
}
private static void write(OutputStream output, String baseName, ReducedModel model) throws IOException {
byte[] header = new byte[Short.SIZE / Byte.SIZE * 11];
ByteBuffer byteBuffer = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
shortBuffer.put((short) model.getIndices().length);
shortBuffer.put((short) model.getUVs().length);
shortBuffer.put((short) model.getIdleVertices()[0].length);
shortBuffer.put(getVertexLength(model.getIdleVertices()));
shortBuffer.put(getAnimationLength(IDLE_ANIMATION_LENGTH, baseName));
shortBuffer.put(getVertexLength(model.getMoveVertices()));
shortBuffer.put(getAnimationLength(MOVE_ANIMATION_LENGTH, baseName));
shortBuffer.put(getVertexLength(model.getAttackVertices()));
shortBuffer.put(getAnimationLength(ATTACK_ANIMATION_LENGTH, baseName));
shortBuffer.put(getVertexLength(model.getDeathVertices()));
shortBuffer.put(getAnimationLength(DEATH_ANIMATION_LENGTH, baseName));
shortBuffer.put(getVertexLength(model.getIdleVertices()));
shortBuffer.put(getAnimationLength(IDLE_ANIMATION_LENGTH, baseName));
write(output, header);
}
private static short getVertexLength(byte[][] vertices) {
if (vertices != null) {
return (short) vertices.length;
} else {
return (short) 0;
}
}
public static short getAnimationLength(HashMap<String, Integer> animationLengths, String baseName) {
Integer length = animationLengths.get(baseName);
if (length != null) {
return (short) length.intValue();
} else {
return DEFAULT_ANIMATION_LENGTH;
}
}
private static void write(OutputStream output, byte[] bytes) throws IOException {
if (bytes == null) {
return;
}
output.write(bytes);
}
private static void writeVertices(OutputStream output, byte[][] vertices) throws IOException {
if (vertices == null) {
return;
}
for (byte[] vertice : vertices) {
write(output, vertice);
}
}
}