Package aspect.resources

Source Code of aspect.resources.Resources

/*
* Copyright (C) 2014 MillerV
*
* 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 aspect.resources;

import aspect.render.Material;
import aspect.render.ViewModel;
import aspect.audio.Music;
import aspect.audio.Sound2D;
import aspect.audio.AudioClip;
import static aspect.core.AspectRenderer.GeometryType.*;
import aspect.render.LineModel;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.logging.Logger;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import javax.sound.sampled.UnsupportedAudioFileException;
import aspect.util.Vector2;
import aspect.util.Vector3;
import aspect.render.MultiModel;
import aspect.render.Texture;
import aspect.render.Mesh;
import aspect.render.shader.Shader;
import aspect.render.shader.ShaderProgram;
import aspect.resources.ArcFile.ArcEntry;
import aspect.resources.modeling.Vertex;
import aspect.util.Angles;
import aspect.util.Color;
import aspect.util.Matrix4x4;
import aspect.util.Trig;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import org.lwjgl.LWJGLException;
import org.lwjgl.util.WaveData;

/**
* A utility class for loading, storing, and retrieving assets such as audio,
* textures, and models.
*
* @author MillerV
*/
public class Resources {

    public static final HashMap<String, Sound2D> AUDIO_2D = new HashMap<>();
    public static final HashMap<String, AudioClip> AUDIO_3D = new HashMap<>();
    public static final HashMap<String, Music> MUSIC = new HashMap<>();
    public static final HashMap<String, Texture> TEXTURES = new HashMap();
    public static final HashMap<String, Material> MATERIALS = new HashMap<>();
    public static final HashMap<String, BufferedImage> IMAGES = new HashMap<>();
    public static final HashMap<String, ViewModel> MODELS = new HashMap<>();
    public static final HashMap<String, Shader> SHADERS = new HashMap<>();

    public static ArcFile archive = null;
    public static long audioMaxSize = (long) 1e6;

    public static final Sound2D UNLOADED_AUDIO2D;
    public static final Music UNLOADED_MUSIC;
    public static final BufferedImage UNLOADED_IMAGE;
    public static final Shader UNLOADED_SHADER;
   
    public static final int VERTEX_DATA_QUAD = 4 * 3;
    public static final int TEXCOORD_DATA_QUAD = 4 * 2;
    public static final int VERTEX_DATA_BOX = VERTEX_DATA_QUAD * 6;
    public static final int TEXCOORD_DATA_BOX = TEXCOORD_DATA_QUAD * 6;
    public static final int VERTEX_DATA_TRIANGLE = 3 * 3;
    public static final int TEXCOORD_DATA_TRIANGLE = 3 * 2;

    static {

        BufferedImage ui;
        try {
            ui = ImageIO.read(Resources.class.getResource("materials/unloaded.jpg"));
        } catch (IOException ex) {
            ui = null;
            Logger.getLogger(Material.class.getName()).log(Level.SEVERE, "Could not load default texture: ", ex);
        }
        UNLOADED_AUDIO2D = new Sound2D();
        UNLOADED_MUSIC = new Music();
        UNLOADED_IMAGE = ui;
        UNLOADED_SHADER = new Shader(0);
    }

    public static InputStream getStream(File file) throws IOException {
        if (archive == null) {
            return new FileInputStream(file);
        } else {
            return archive.getStream(file);
        }
    }

    public static Sound2D loadSound2D(File source) {
        try {
            return loadSound2D(getStream(source));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return UNLOADED_AUDIO2D;
        }
    }

    public static Sound2D loadSound2D(InputStream source) {
        try {
            Sound2D snd = new Sound2D(source);
            return snd;
        } catch (UnsupportedAudioFileException | IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Sound could not be loaded: ", ex);
            return UNLOADED_AUDIO2D;
        }
    }

    public static Sound2D loadSound2D(String name, File source) {
        if (AUDIO_2D.containsKey(name)) {
            return AUDIO_2D.get(name);
        }

        Sound2D snd = loadSound2D(source);
        addSound2D(name, snd);
        return snd;
    }

    public static Sound2D loadSound2D(String name, InputStream source) {
        if (AUDIO_2D.containsKey(name)) {
            return AUDIO_2D.get(name);
        }

        Sound2D snd = loadSound2D(source);
        addSound2D(name, snd);
        return snd;
    }

    public static void addSound2D(String name, Sound2D snd) {
        AUDIO_2D.put(name, snd);
    }

    public static Sound2D getSound2D(String name) {
        return AUDIO_2D.get(name);
    }

    public static AudioClip loadSound3D(File source) {
        try {
            return loadSound3D(getStream(source));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public static AudioClip loadSound3D(InputStream source) {
        try {
            WaveData data = WaveData.create(new BufferedInputStream(source));
            AudioClip clip = new AudioClip(data);
            return clip;
        } catch (LWJGLException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Sound could not be loaded: ", ex);
            return null;
        }
    }

    public static AudioClip loadSound3D(String name, File source) {
        if (AUDIO_3D.containsKey(name)) {
            return AUDIO_3D.get(name);
        }

        AudioClip clip = loadSound3D(source);
        addSound3D(name, clip);
        return clip;
    }

    public static AudioClip loadSound3D(String name, InputStream source) {
        if (AUDIO_3D.containsKey(name)) {
            return AUDIO_3D.get(name);
        }

        AudioClip clip = loadSound3D(source);
        addSound3D(name, clip);
        return clip;
    }

    public static void addSound3D(String name, AudioClip clip) {
        AUDIO_3D.put(name, clip);
    }

    public static AudioClip getSound3D(String name) {
        return AUDIO_3D.get(name);
    }

    public static Music loadMusic(File file) {
        try {
            return loadMusic(getStream(file));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return new Music();
        }
    }

    public static Music loadMusic(InputStream source) {
        return new Music(source);
    }

    public static Music loadMusic(String name, File file) {
        if (MUSIC.containsKey(name)) {
            return MUSIC.get(name);
        }

        Music mus = loadMusic(file);
        addMusic(name, mus);
        return mus;
    }

    public static Music loadMusic(String name, InputStream source) {
        if (MUSIC.containsKey(name)) {
            return MUSIC.get(name);
        }

        Music mus = loadMusic(source);
        addMusic(name, mus);
        return mus;
    }

    public static void addMusic(String name, Music mus) {
        MUSIC.put(name, mus);
    }

    public static Music getMusic(String name) {
        return MUSIC.get(name);
    }

    public static Texture loadTexture(File file) {
        try {
            return loadTexture(getStream(file));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Material could not be loaded: ", ex);
            return Texture.create(UNLOADED_IMAGE);
        }
    }

    public static Texture loadTexture(InputStream source) {
        try {
            Texture texture = Texture.create(source);
            return texture;
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Material could not be loaded: ", ex);
            return Texture.create(UNLOADED_IMAGE);
        }
    }

    public static Texture loadTexture(String name, File file) {
        if (TEXTURES.containsKey(name)) {
            return TEXTURES.get(name);
        }

        Texture texture = loadTexture(file);
        addTexture(name, texture);
        return texture;
    }

    public static Texture loadTexture(String name, InputStream source) {
        if (TEXTURES.containsKey(name)) {
            return TEXTURES.get(name);
        }

        Texture texture = loadTexture(source);
        addTexture(name, texture);
        return texture;
    }

    public static void addTexture(String name, Texture texture) {
        TEXTURES.put(name, texture);
    }

    public static Texture getTexture(String name) {
        return TEXTURES.get(name);
    }

    public static Shader loadShader(File file, Shader.Type type) {
        return new Shader(file, type);
    }

    public static Shader loadShader(InputStream stream, Shader.Type type) {
        return new Shader(loadTextFile(stream), type);
    }

    public static Shader loadShader(String name, File file, Shader.Type type) {
        if (SHADERS.containsKey(name)) {
            return SHADERS.get(name);
        }

        Shader shader = loadShader(file, type);
        addShader(name, shader);
        return shader;
    }

    public static Shader loadShader(String name, InputStream stream, Shader.Type type) {
        if (SHADERS.containsKey(name)) {
            return SHADERS.get(name);
        }

        Shader shader = loadShader(stream, type);
        addShader(name, shader);
        return shader;
    }

    public static void addShader(String name, Shader shader) {
        SHADERS.put(name, shader);
    }

    public static Shader getShader(String name) {
        return SHADERS.get(name);
    }

    public static Material loadMaterial(File source) {
        try {
            return loadMaterial(getStream(source));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return new Material();
        }
    }

    // When loading a Material from an InputStream, make sure to load the Shader
    // and Texture first.
    public static Material loadMaterial(InputStream source) {
        String s = loadTextFile(source);
        Material m = new Material();
        for (String line : s.trim().split("\n")) {
            line = line.trim();
            String[] args = line.split(" ");
            if (line.startsWith("#") || line.isEmpty()) {
                continue;
            }
            switch (args[0]) {
                case "texture:": {
                    m.texture = loadTexture(args[1], new File(args[1]));
                    break;
                }

                case "ambient:": {
                    m.ambient = new Color(Float.parseFloat(args[1]), Float.parseFloat(args[2]), Float.parseFloat(args[3]));
                    break;
                }

                case "diffuse:": {
                    m.diffuse = new Color(Float.parseFloat(args[1]), Float.parseFloat(args[2]), Float.parseFloat(args[3]));
                    break;
                }

                case "specular:": {
                    m.specular = new Color(Float.parseFloat(args[1]), Float.parseFloat(args[2]), Float.parseFloat(args[3]));
                    break;
                }
               
                case "emissive:": {
                    m.emissive = new Color(Float.parseFloat(args[1]), Float.parseFloat(args[2]), Float.parseFloat(args[3]));
                }
               
                case "shininess:": {
                    m.shininess = Float.parseFloat(args[1]);
                    break;
                }

                case "shader:": {
                    if (args[1].equals("prebuilt")) {
                        m.shader = ShaderProgram.loadPrebuilt(args[2]);
                    } else {
                        Shader vert = loadShader(args[1], new File(args[1]), Shader.Type.VERTEX);
                        Shader frag = loadShader(args[2], new File(args[2]), Shader.Type.FRAGMENT);
                       
                        ShaderProgram shader = new ShaderProgram(vert, frag);
                       
                        m.shader = shader;
                    }
                    break;
                }

                case "cull:": {
                    m.cull = Boolean.parseBoolean(args[1]);
                    break;
                }

                default: {
                    Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Could not parse line of amp file: {0}", line);
                }
            }
        }
        return m;
    }

    public static Material loadMaterial(String name, File source) {
        if (MATERIALS.containsKey(name)) {
            return MATERIALS.get(name);
        }

        Material material = loadMaterial(source);
        addMaterial(name, material);
        return material;
    }

    public static Material loadMaterial(String name, InputStream source) {
        if (MATERIALS.containsKey(name)) {
            return MATERIALS.get(name);
        }

        Material material = loadMaterial(source);
        addMaterial(name, material);
        return material;
    }

    public static void addMaterial(String name, Material mtl) {
        MATERIALS.put(name, mtl);
    }

    public static Material getMaterial(String name) {
        return MATERIALS.get(name);
    }

    public static BufferedImage loadImage(File file) {
        try {
            return loadImage(getStream(file));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return UNLOADED_IMAGE;
        }
    }

    public static BufferedImage loadImage(InputStream stream) {
        try {
            BufferedImage img = ImageIO.read(stream);
            return img;
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Image could not be loaded: ", ex);
            return UNLOADED_IMAGE;
        }
    }

    public static BufferedImage loadImage(String name, File file) {
        if (IMAGES.containsKey(name)) {
            return IMAGES.get(name);
        }

        BufferedImage img = loadImage(file);
        addImage(name, img);
        return img;
    }

    public static BufferedImage loadImage(String name, InputStream stream) {
        if (IMAGES.containsKey(name)) {
            return IMAGES.get(name);
        }

        BufferedImage img = loadImage(stream);
        addImage(name, img);
        return img;
    }

    public static void addImage(String name, BufferedImage img) {
        IMAGES.put(name, img);
    }

    public static BufferedImage getImage(String name) {
        return IMAGES.get(name);
    }

    public static BufferedImage createImage(int width, int height) {
        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

        return gc.createCompatibleImage(width, height, java.awt.Color.BITMASK);
    }

    public static String loadTextFile(File file) {
        try {
            return loadTextFile(getStream(file));
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return new String();
        }
    }

    public static String loadTextFile(InputStream stream) {
        try {
            return Shader.readIntoString(stream);
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, null, ex);
            return new String();
        }
    }

    public static ViewModel loadObjModel(File file, Vector3 scale) {
        try {
            String text = loadTextFile(file);
            return loadObj(text, scale);
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Model could not be loaded: ", ex);
            return new ViewModel() {
                @Override
                public void renderModel() {
                    Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Model not loaded.");
                }
            };
        }
    }

    public static ViewModel loadObjModel(InputStream stream, Vector3 scale) {
        try {
            String text = loadTextFile(stream);
            return loadObj(text, scale);
        } catch (IOException ex) {
            Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Model could not be loaded: ", ex);
            return new ViewModel() {
                @Override
                public void renderModel() {
                    Logger.getLogger(Resources.class.getName()).log(Level.SEVERE, "Model not loaded.");
                }
            };
        }
    }

    public static ViewModel loadObjModel(String name, File file, Vector3 scale) {
        if (MODELS.containsKey(name)) {
            return MODELS.get(name);
        }

        ViewModel mdl = loadObjModel(file, scale);
        addModel(name, mdl);
        return mdl;
    }

    public static ViewModel loadObjModel(String name, InputStream stream, Vector3 scale) {
        if (MODELS.containsKey(name)) {
            return MODELS.get(name);
        }

        ViewModel mdl = loadObjModel(stream, scale);
        addModel(name, mdl);
        return mdl;
    }

    public static void addModel(String name, ViewModel model) {
        MODELS.put(name, model);
    }

    public static ViewModel getModel(String name) {
        return MODELS.get(name);
    }
   
    public static int vertexDataPipe(int lod) {
        return lod * 4 * 3;
    }
   
    public static int texCoordDataPipe(int lod) {
        return lod * 4 * 2;
    }
   
    public static int vertexDataSphere(int lod) {
        return lod * (lod / 2) * 4 * 3;
    }
   
    public static int texCoordDataSphere(int lod) {
        return lod * (lod / 2) * 4 * 2;
    }
   
    public static int vertexDataPolygon(int npoints) {
        return npoints * 3;
    }
   
    public static int texCoordDataPolygon(int npoints) {
        return npoints * 2;
    }
   
    public static float[] polygonTexCoords(float hRepeat, float vRepeat, Vector3... points) {
        float[] f = new float[texCoordDataPolygon(points.length)];
        polygonTexCoords(hRepeat, vRepeat, points, f, 0);
        return f;
    }

    public static void polygonTexCoords(float hRepeat, float vRepeat, Vector3[] points, float[] dest, int start) {
        float minx = Float.POSITIVE_INFINITY;
        float miny = Float.POSITIVE_INFINITY;
        float minz = Float.POSITIVE_INFINITY;
        float maxx = Float.NEGATIVE_INFINITY;
        float maxy = Float.NEGATIVE_INFINITY;
        float maxz = Float.NEGATIVE_INFINITY;
        for (Vector3 point : points) {
            float x = point.x;
            float y = point.y;
            float z = point.z;
            minx = Math.min(minx, x);
            miny = Math.min(miny, y);
            minz = Math.min(minz, z);
            maxx = Math.max(maxx, x);
            maxy = Math.max(maxy, y);
            maxz = Math.max(maxz, z);
        }
        float w = new Vector2(maxx - minx, maxz - minz).mag();
        for (int i = 0; i < points.length; i++) {
            float x = (new Vector2(points[i].x - minx, points[i].z - minz).mag() / w) * hRepeat;
            float y = ((points[i].y - miny) / (maxy - miny)) * vRepeat;
            dest[i * 2 + start + 0] = x;
            dest[i * 2 + start + 1] = y;
        }
    }

    public static ViewModel loadObjLines(String obj, float scale) throws IOException {
        ArrayList<Vector3> allVertices = new ArrayList<>(100);

        LinkedList<Float> triangleVerts = new LinkedList<>();
        LinkedList<Float> lineVerts = new LinkedList<>();

        for (String s : obj.trim().split("\n")) {
            s = s.trim();
            String[] parts = s.split(" ");
            if (s.startsWith("#") || s.isEmpty()) {
                continue;
            }
            switch (parts[0]) {
                case "v": {
                    float x = Float.parseFloat(parts[1]);
                    float y = Float.parseFloat(parts[2]);
                    float z = Float.parseFloat(parts[3]);
                    allVertices.add(new Vector3(x, y, z).times(scale));
                    break;
                }

                case "f": {
                    for (int i = 0; i < 3; i++) {
                        String[] info = parts[i + 1].split("/");
                        int vertex = Integer.parseInt(info[0]);
                        if (vertex < 0) {
                            vertex = allVertices.size() + vertex;
                        } else {
                            vertex--;
                        }

                        Vector3 v = allVertices.get(vertex);
                        triangleVerts.add(v.x);
                        triangleVerts.add(v.y);
                        triangleVerts.add(v.z);
                    }
                    break;
                }

                case "l": {
                    for (int i = 0; i < 2; i++) {
                        int vertex = Integer.parseInt(parts[i + 1]);

                        if (vertex < 0) {
                            vertex = allVertices.size() + vertex;
                        } else {
                            vertex--;
                        }

                        Vector3 v = allVertices.get(vertex);
                        lineVerts.add(v.x);
                        lineVerts.add(v.y);
                        lineVerts.add(v.z);
                    }
                    break;
                }
            }
        }

        float[] triangles = new float[triangleVerts.size()];
        float[] lines = new float[lineVerts.size()];

        int i = 0;
        for (float f : triangleVerts) {
            triangles[i++] = f;
        }
        i = 0;
        for (float f : lineVerts) {
            lines[i++] = f;
        }

        Mesh triangleVBO = new Mesh(TRIANGLES, triangles, new float[triangles.length / 3]);
        Mesh lineVBO = new Mesh(LINES, lines, new float[lines.length / 3]);

        return new LineModel(triangleVBO, lineVBO);
    }

    public static ViewModel loadObj(String obj, Vector3 scale) throws IOException {
        ArrayList<Vector3> allVertices = new ArrayList<>(100);
        ArrayList<Vector2> allTexCoords = new ArrayList<>(100);
        ArrayList<Vector3> allNormals = new ArrayList<>(100);

        Material currentMaterial = null;
        //LinkedList<ViewModel> polygons = new LinkedList<>();

        HashMap<Material, LinkedList<Vertex>> triangles = new HashMap<>();

        for (String s : obj.trim().split("\n")) {
            s = s.trim();
            String[] parts = s.split(" ");
            if (s.startsWith("#") || s.isEmpty()) {
                continue;
            }
            switch (parts[0]) {
                case "mtllib": {
                    loadMtl(loadTextFile(new File("models/" + parts[1])));
                    break;
                }
                case "usemtl": {
                    currentMaterial = getMaterial(parts[1]);
                    break;
                }
                case "v": {
                    float x = Float.parseFloat(parts[1]);
                    float y = Float.parseFloat(parts[2]);
                    float z = Float.parseFloat(parts[3]);
                    allVertices.add(new Vector3(x, y, z).component(scale));
                    break;
                }
                case "vt": {
                    float x = Float.parseFloat(parts[1]);
                    float y = Float.parseFloat(parts[2]);
                    allTexCoords.add(new Vector2(x, y));
                    break;
                }
                case "vn": {
                    float x = Float.parseFloat(parts[1]);
                    float y = Float.parseFloat(parts[2]);
                    float z = Float.parseFloat(parts[3]);
                    allNormals.add(new Vector3(x / scale.x, y / scale.y, z / scale.z).normalize());
                    break;
                }
                case "f": {
                    LinkedList<Vertex> thisMtl = triangles.get(currentMaterial);

                    if (thisMtl == null) {
                        thisMtl = new LinkedList<>();
                        triangles.put(currentMaterial, thisMtl);
                    }

                    for (int i = 0; i < 3; i++) {
                        String[] info = parts[i + 1].split("/");
                        int vertex = Integer.parseInt(info[0]);
                        int texCoord = Integer.parseInt(info[1]);
                        int normal = Integer.parseInt(info[2]);
                        if (vertex < 0) {
                            vertex = allVertices.size() + vertex;
                        } else {
                            vertex--;
                        }
                        if (texCoord < 0) {
                            texCoord = allTexCoords.size() + texCoord;
                        } else {
                            texCoord--;
                        }
                        if (normal < 0) {
                            normal = allNormals.size() + normal;
                        } else {
                            normal--;
                        }

                        thisMtl.add(new Vertex(allVertices.get(vertex), allNormals.get(normal), allTexCoords.get(texCoord)));
                    }
                }
            }
        }

        LinkedList<ViewModel> polygons = new LinkedList<>();

        for (Material m : triangles.keySet()) {
            LinkedList<Vertex> vertices = triangles.get(m);
            float[] positions = new float[vertices.size() * 3];
            float[] texcoords = new float[vertices.size() * 2];
            float[] normals = new float[vertices.size() * 3];

            int i = 0;
            for (Vertex v : vertices) {
                positions[i * 3 + 0] = v.position.x;
                positions[i * 3 + 1] = v.position.y;
                positions[i * 3 + 2] = v.position.z;

                texcoords[i * 2 + 0] = v.texcoord.x;
                texcoords[i * 2 + 1] = v.texcoord.y;

                normals[i * 3 + 0] = v.normal.x;
                normals[i * 3 + 1] = v.normal.y;
                normals[i * 3 + 2] = v.normal.z;

                i++;
            }

            polygons.add(new Mesh(TRIANGLES, positions, normals, texcoords, m));
        }

        return new MultiModel(polygons);
    }

    public static void loadMtl(String mtl) throws IOException {
        HashMap<String, Color> colors = new HashMap<>();
        Material current = null;

        for (String s : mtl.trim().split("\n")) {
            s = s.trim();
            String[] parts = s.split(" ");
            switch (parts[0]) {
                case "newmtl": {
                    current = new Material();
                    current.shader = ShaderProgram.PHONG;
                    current.cull = false;
                    addMaterial(parts[1], current);
                    break;
                }
                case "Ka": {
                    float red = Float.parseFloat(parts[1]);
                    float green = Float.parseFloat(parts[2]);
                    float blue = Float.parseFloat(parts[3]);
                    current.emissive = new Color(red, green, blue);
                    break;
                }
                case "Kd": {
                    float red = Float.parseFloat(parts[1]);
                    float green = Float.parseFloat(parts[2]);
                    float blue = Float.parseFloat(parts[3]);
                    current.diffuse = new Color(red, green, blue);
                    current.ambient = new Color(red, green, blue);
                    break;
                }
                case "Ks": {/*
                    float red = Float.parseFloat(parts[1]);
                    float green = Float.parseFloat(parts[2]);
                    float blue = Float.parseFloat(parts[3]);
                    current.specular = new Color(red, green, blue);*/
                    break;
                }
                case "map_Kd": {
                    String path = "models/" + parts[1];
                    current.texture = loadTexture(path, getStream(new File(path)));
                    break;
                }
            }
        }
    }

    public static ViewModel rect(Material texture, float width, float height) {
        return rect(texture, 1, 1, width, height);
    }

    public static ViewModel rect(Material texture, float hRepeat, float vRepeat, float width, float height) {
        float[] vertices = rectVertices(width, height);
        float[] texCoords = rectTexCoords(hRepeat, vRepeat);
        return new Mesh(QUADS, vertices, copyVector3(Vector3.zAxis(), 4), texCoords, texture);
    }

    public static ViewModel rect(Color color, float width, float height) {
        return rect(new Material(color), width, height);
    }

    public static ViewModel sprite(Material image, float xscl, float yscl) {
        Texture tex = image.getTexture();
        return rect(image, tex.getWidth() * xscl, tex.getHeight() * yscl);
    }

    public static ViewModel ellipse(Material texture, float width, float height, int npoints) {
        float[] vertices = ellipseVertices(width, height, npoints);
        float[] texCoords = ellipseTexCoords(npoints);
        return new Mesh(POLYGON, vertices, copyVector3(Vector3.zAxis(), npoints), texCoords, texture);
    }

    public static ViewModel ellipse(Color color, float width, float height, int npoints) {
        return ellipse(new Material(color), width, height, npoints);
    }
   
    public static float[] pipeVertices(float radius, float length, int lod) {
        float[] f = new float[vertexDataPipe(lod)];
        pipeVertices(radius, length, lod, f, 0);
        return f;
    }
   
    public static int pipeVertices(float radius, float length, int lod, float[] dest, int start) {
        length /= 2;
        float angleStep = (Trig.FULL_CIRCLE / lod);
       
        int index = start;
        for (int i = 0; i < lod; i++) {
            float angle = i * angleStep;

            float x1 = Trig.cos(angle) * radius;
            float z1 = Trig.sin(angle) * radius;
           
            float x2 = Trig.cos(angle + angleStep) * radius;
            float z2 = Trig.sin(angle + angleStep) * radius;
           
            Vector3 vert1 = new Vector3(x1, -length, z1);
            Vector3 vert2 = new Vector3(x1, length, z1);
            Vector3 vert3 = new Vector3(x2, length, z2);
            Vector3 vert4 = new Vector3(x2, -length, z2);
           
            index += copyVector3(vert1, dest, index, 1);
            index += copyVector3(vert2, dest, index, 1);
            index += copyVector3(vert3, dest, index, 1);
            index += copyVector3(vert4, dest, index, 1);
        }
       
        return vertexDataPipe(lod);
    }
   
    public static float[] pipeTexCoords(float hRepeat, float vRepeat, int lod) {
        float[] f = new float[texCoordDataPipe(lod)];
        pipeTexCoords(hRepeat, vRepeat, lod, f, 0);
        return f;
    }
   
    public static int pipeTexCoords(float hRepeat, float vRepeat, int lod, float[] dest, int start) {
        float texStep = (1.0f / lod);
       
        int index = start;
        for (int i = 0; i < lod; i++) {
            float tex = i * texStep;
           
            Vector2 tex1 = new Vector2(tex * hRepeat, vRepeat);
            Vector2 tex2 = new Vector2(tex * hRepeat, 0);
            Vector2 tex3 = new Vector2((tex + texStep) * hRepeat, 0);
            Vector2 tex4 = new Vector2((tex + texStep) * hRepeat, vRepeat);

            index += copyVector2(tex1, dest, index, 1);
            index += copyVector2(tex2, dest, index, 1);
            index += copyVector2(tex3, dest, index, 1);
            index += copyVector2(tex4, dest, index, 1);
        }
       
        return texCoordDataPipe(lod);
    }
   
    public static float[] pipeNormals(int lod) {
        float[] f = new float[vertexDataPipe(lod)];
        pipeNormals(lod, f, 0);
        return f;
    }
   
    public static int pipeNormals(int lod, float[] dest, int start) {
        return pipeVertices(1.0f, 0.0f, lod, dest, start);
    }

    public static ViewModel pipe(Material sides, float hRepeat, float vRepeat, float radius, float length, int lod) {
        return new Mesh(QUADS, pipeVertices(radius, length, lod), pipeNormals(lod), pipeTexCoords(hRepeat, vRepeat, lod), sides);
    }
   
    public static int sphereVertices(float radius, int lod, float[] dest, int start) {
        float step = Trig.FULL_CIRCLE / lod;
       
        int vlod = lod / 2;
       
        int index = start;
        for (int i = 0; i < lod; i++) {
            float lon = i * step;
            for (int j = 0; j < vlod; j++) {
                float lat = j * step - 90.0f;
                Vector3 vert1 = Vector3.fromAngles(new Angles(lat, lon, 0.0f), radius);
                Vector3 vert2 = Vector3.fromAngles(new Angles(lat, lon + step, 0.0f), radius);
                Vector3 vert3 = Vector3.fromAngles(new Angles(lat + step, lon + step, 0.0f), radius);
                Vector3 vert4 = Vector3.fromAngles(new Angles(lat + step, lon, 0.0f), radius);
               
                index += copyVector3(vert1, dest, index, 1);
                index += copyVector3(vert2, dest, index, 1);
                index += copyVector3(vert3, dest, index, 1);
                index += copyVector3(vert4, dest, index, 1);
            }
        }
       
        return vertexDataSphere(lod);
    }
   
    public static float[] sphereVertices(float radius, int lod) {
        float[] f = new float[vertexDataSphere(lod)];
        sphereVertices(radius, lod, f, 0);
        return f;
    }
   
    public static int sphereTexCoords(int lod, float[] dest, int start) {
        float texstep = 1.0f / lod;
       
        int vlod = lod / 2;
       
        int index = start;
        for (int i = lod; i > 0; i--) {
            float u = i * texstep;
            for (int j = 0; j < vlod; j++) {
                float v = j * texstep * 2;
                Vector2 tex1 = new Vector2(u + texstep, v);
                Vector2 tex2 = new Vector2(u, v);
                Vector2 tex3 = new Vector2(u, v + texstep * 2);
                Vector2 tex4 = new Vector2(u + texstep, v + texstep * 2);
               
                index += copyVector2(tex1, dest, index, 1);
                index += copyVector2(tex2, dest, index, 1);
                index += copyVector2(tex3, dest, index, 1);
                index += copyVector2(tex4, dest, index, 1);
            }
        }
       
        return texCoordDataSphere(lod);
    }
   
    public static float[] sphereTexCoords(int lod) {
        float[] f = new float[texCoordDataSphere(lod)];
        sphereTexCoords(lod, f, 0);
        return f;
    }
   
    public static int sphereNormals(int lod, float[] dest, int start) {
        return sphereVertices(1.0f, lod, dest, start);
    }
   
    public static float[] sphereNormals(int lod) {
        return sphereVertices(1.0f, lod);
    }
   
    public static ViewModel sphere(float radius, int lod, Material mtl) {
        return new Mesh(QUADS, sphereVertices(radius, lod), sphereNormals(lod), sphereTexCoords(lod), mtl);
    }

    public static float[] rectVertices(float width, float height) {
        width /= 2;
        height /= 2;
        return new float[]{
            width, -height, 0,
            width, height, 0,
            -width, height, 0,
            -width, -height, 0
        };
    }
   
    public static int rectVertices(float width, float height, float[] dest, int start) {
        System.arraycopy(rectVertices(width, height), 0, dest, start, 12);
       
        return VERTEX_DATA_QUAD;
    }
   
    public static float[] ellipseTexCoords(int lod) {
        float[] f = new float[texCoordDataPolygon(lod)];
        ellipseTexCoords(lod, f, 0);
        return f;
    }

    public static int ellipseTexCoords(int lod, float[] dest, int start) {

        float step = (float) (2 * Math.PI / lod);
        for (int i = 0; i < lod; i++) {
            dest[i * 2 + start + 0] = -(float) (0.49 * Math.cos(i * step) + 0.5);
            dest[i * 2 + start + 1] = (float) (0.49 * Math.sin(i * step) + 0.5);
        }
       
        return texCoordDataPolygon(lod);
    }
   
    public static float[] ellipseVertices(float width, float height, int lod) {
        float[] f = new float[vertexDataPolygon(lod)];
        ellipseVertices(width, height, lod, f, 0);
        return f;
    }

    public static int ellipseVertices(float width, float height, int lod, float[] dest, int start) {
        width /= 2;
        height /= 2;

        float step = Trig.FULL_CIRCLE / lod;
        for (int i = 0; i < lod; i++) {
            dest[i * 3 + start + 0] = width * Trig.cos(i * step);
            dest[i * 3 + start + 1] = height * Trig.sin(i * step);
            dest[i * 3 + start + 2] = 0.0f;
        }
       
        return vertexDataPolygon(lod);
    }
   
    public static float[] rectTexCoords(float hRepeat, float vRepeat) {
        float[] f = new float[TEXCOORD_DATA_QUAD];
        rectTexCoords(hRepeat, vRepeat, f, 0);
        return f;
    }
   
    public static int rectTexCoords(float hRepeat, float vRepeat, float[] dest, int start) {
        dest[start + 0] = 0;
        dest[start + 1] = 0;
        dest[start + 2] = 0;
        dest[start + 3] = vRepeat;
        dest[start + 4] = hRepeat;
        dest[start + 5] = vRepeat;
        dest[start + 6] = hRepeat;
        dest[start + 7] = 0;
       
        return TEXCOORD_DATA_BOX;
    }

    public static ViewModel box(Material texture, float width, float height, float depth) {
        return box(texture, 1, 1, 1, width, height, depth);
    }

    public static ViewModel box(Material texture, float xRepeat, float yRepeat, float zRepeat, float width, float height, float depth) {
        float[] vertices = boxVertices(width, height, depth);
        float[] texCoords = boxTexCoords(xRepeat, yRepeat, zRepeat);
        return new Mesh(QUADS, vertices, boxNormals(), texCoords, texture);
    }

    public static ViewModel box(Color color, float width, float height, float depth) {
        return box(new Material(color), width, height, depth);
    }

    public static float[] boxVertices(float width, float height, float depth) {
        width /= 2;
        height /= 2;
        depth /= 2;
        return new float[]{
            // front (-z)
            -width, height, depth,
            -width, -height, depth,
            width, -height, depth,
            width, height, depth,
            // left (-x)
            -width, height, -depth,
            -width, -height, -depth,
            -width, -height, depth,
            -width, height, depth,
            // back (+z)
            width, height, -depth,
            width, -height, -depth,
            -width, -height, -depth,
            -width, height, -depth,
            // right (+x)
            width, height, depth,
            width, -height, depth,
            width, -height, -depth,
            width, height, -depth,
            // top (+y)
            width, height, -depth,
            -width, height, -depth,
            -width, height, depth,
            width, height, depth,
            // bottom (-y)
            width, -height, depth,
            -width, -height, depth,
            -width, -height, -depth,
            width, -height, -depth
        };
    }
   
    public static int boxVertices(float width, float height, float depth, float[] dest, int start) {
        System.arraycopy(boxVertices(width, height, depth), 0, dest, start, 6 * 4 * 3);
       
        return VERTEX_DATA_BOX;
    }
   
    public static float[] boxNormals() {
        float[] f = new float[VERTEX_DATA_BOX];
        boxNormals(f, 0);
        return f;
    }
   
    public static int boxNormals(float[] dest, int start) {
        copyVector3(Vector3.zAxis(), dest, start + 0 * 3, 4);
        copyVector3(Vector3.xAxis().negate(), dest, start + 4 * 3, 4);
        copyVector3(Vector3.zAxis().negate(), dest, start + 8 * 3, 4);
        copyVector3(Vector3.xAxis(), dest, start + 12 * 3, 4);
        copyVector3(Vector3.yAxis(), dest, start + 16 * 3, 4);
        copyVector3(Vector3.yAxis().negate(), dest, start + 20 * 3, 4);
       
        return VERTEX_DATA_BOX;
    }
   
    public static float[] polygonVertices(Vector3... points) {
        float[] f = new float[vertexDataPolygon(points.length)];
        polygonVertices(points, f, 0);
        return f;
    }

    public static int polygonVertices(Vector3[] points, float[] dest, int start) {
        for (int i = 0; i < points.length; i++) {
            copyVector3(points[i], dest, start + i * 3, 1);
        }
       
        return vertexDataPolygon(points.length);
    }
   
    public static float[] boxTexCoords(float xRepeat, float yRepeat, float zRepeat) {
        float[] f = new float[TEXCOORD_DATA_BOX];
        boxTexCoords(xRepeat, yRepeat, zRepeat, f, 0);
        return f;
    }

    public static int boxTexCoords(float xRepeat, float yRepeat, float zRepeat, float[] dest, int start) {
        float[] hRepeats = {xRepeat, zRepeat, xRepeat, zRepeat, zRepeat, zRepeat};
        float[] vRepeats = {yRepeat, yRepeat, yRepeat, yRepeat, xRepeat, xRepeat};
        for (int i = 0; i < 6; i++) {
            dest[i * 8 + start + 0] = hRepeats[i];
            dest[i * 8 + start + 1] = 0;
            dest[i * 8 + start + 2] = hRepeats[i];
            dest[i * 8 + start + 3] = vRepeats[i];
            dest[i * 8 + start + 4] = 0;
            dest[i * 8 + start + 5] = vRepeats[i];
            dest[i * 8 + start + 6] = 0;
            dest[i * 8 + start + 7] = 0;
        }
       
        return TEXCOORD_DATA_BOX;
    }
   
    public static int copyVector2(Vector2 vector, float[] dest, int start, int num) {
        for (int i = 0; i < num; i++) {
            dest[i * 2 + start + 0] = vector.x;
            dest[i * 2 + start + 1] = vector.y;
        }
       
        return num * 2;
    }
   
    public static float[] copyVector2(Vector2 vector, int num) {
        float[] f = new float[num * 2];
        copyVector2(vector, f, 0, num);
        return f;
    }

    public static int copyVector3(Vector3 vector, float[] dest, int start, int num) {
        for (int i = 0; i < num; i++) {
            dest[i * 3 + start + 0] = vector.x;
            dest[i * 3 + start + 1] = vector.y;
            dest[i * 3 + start + 2] = vector.z;
        }
       
        return num * 3;
    }
   
    public static float[] copyVector3(Vector3 vector, int num) {
        float[] f = new float[num * 3];
        copyVector3(vector, f, 0, num);
        return f;
    }
   
    public static int copyColorRGB(Color color, float[] dest, int start, int num) {
        for (int i = 0; i < num; i++) {
            dest[i * 3 + start + 0] = color.red;
            dest[i * 3 + start + 1] = color.green;
            dest[i * 3 + start + 2] = color.blue;
        }
       
        return num * 3;
    }
   
    public static float[] copyColorRGB(Color color, int num) {
        float[] f = new float[num * 3];
        copyColorRGB(color, f, 0, num);
        return f;
    }
   
    public static int copyColorRGBA(Color color, float[] dest, int start, int num) {
        for (int i = 0; i < num; i++) {
            dest[i * 4 + start + 0] = color.red;
            dest[i * 4 + start + 1] = color.green;
            dest[i * 4 + start + 2] = color.blue;
            dest[i * 4 + start + 3] = color.alpha;
        }
       
        return num * 4;
    }
   
    public static float[] copyColorRGBA(Color color, int num) {
        float[] f = new float[num * 4];
        copyColorRGBA(color, f, 0, num);
        return f;
    }
   
    public static void transformVectors(float[] vectors, Matrix4x4 matrix, int start, int num) {
        for (int i = start; i < start + num; i+= 3) {
            Vector3 vec = new Vector3(vectors[i], vectors[i + 1], vectors[i + 2]);
            Vector3 transformed = matrix.transformVector(vec);
            copyVector3(transformed, vectors, i, 1);
        }
    }
   
    public static void transformPoints(float[] vectors, Matrix4x4 matrix, int start, int num) {
        for (int i = start; i < start + num; i+= 3) {
            Vector3 vec = new Vector3(vectors[i], vectors[i + 1], vectors[i + 2]);
            Vector3 transformed = matrix.transformPoint(vec);
            copyVector3(transformed, vectors, i, 1);
        }
    }

    public static Vector3 normal(Vector3 v1, Vector3 v2, Vector3 v3) {
        Vector3 u = Vector3.subtract(v2, v1);
        Vector3 v = Vector3.subtract(v3, v1);
        Vector3 n = Vector3.cross(u, v).normalize();

        return n;
    }
   
    public static float[] faceNormals(Vector3... vertices) {
        float[] normals = new float[vertexDataPolygon(vertices.length)];
        faceNormals(vertices, normals, 0, vertices.length);
        return normals;
    }

    public static int faceNormals(Vector3[] vertices, float[] dest, int index, int num) {
        return copyVector3(normal(vertices[0], vertices[1], vertices[2]), dest, index, num);
    }

    public static ViewModel polygon(Material texture, Vector3... points) {
        return polygon(texture, 1, 1, points);
    }

    public static ViewModel polygon(Material texture, float hRepeat, float vRepeat, Vector3... points) {
        float[] vertices = polygonVertices(points);
        float[] texCoords = polygonTexCoords(hRepeat, vRepeat, points);
        return new Mesh(POLYGON, vertices, copyVector3(Vector3.zAxis(), points.length), texCoords, texture);
    }

    public static ViewModel polygon(Color color, Vector3... points) {
        return polygon(new Material(color), points);
    }
}
TOP

Related Classes of aspect.resources.Resources

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.