thothbot.parallax.loader.shared.JsonLoader.java Source code

Java tutorial

Introduction

Here is the source code for thothbot.parallax.loader.shared.JsonLoader.java

Source

/*
 * Copyright 2012 Alex Usachev, thothbot@gmail.com
 * 
 * This file is part of Parallax project.
 * 
 * Parallax is free software: you can redistribute it and/or modify it 
 * under the terms of the Creative Commons Attribution 3.0 Unported License.
 * 
 * Parallax 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 Creative Commons Attribution 
 * 3.0 Unported License. for more details.
 * 
 * You should have received a copy of the the Creative Commons Attribution 
 * 3.0 Unported License along with Parallax. 
 * If not, see http://creativecommons.org/licenses/by/3.0/.
 */

package thothbot.parallax.loader.shared;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import thothbot.parallax.core.client.gl2.enums.TextureWrapMode;
import thothbot.parallax.core.client.shaders.NormalMapShader;
import thothbot.parallax.core.client.shaders.Uniform;
import thothbot.parallax.core.client.textures.CompressedTexture;
import thothbot.parallax.core.client.textures.Texture;
import thothbot.parallax.core.shared.Log;
import thothbot.parallax.core.shared.core.AbstractGeometry;
import thothbot.parallax.core.shared.core.Face3;
import thothbot.parallax.core.shared.core.Geometry;
import thothbot.parallax.core.shared.core.Geometry.MorphColor;
import thothbot.parallax.core.shared.materials.HasAlphaMap;
import thothbot.parallax.core.shared.materials.HasAmbientEmissiveColor;
import thothbot.parallax.core.shared.materials.HasBumpMap;
import thothbot.parallax.core.shared.materials.HasColor;
import thothbot.parallax.core.shared.materials.HasLightMap;
import thothbot.parallax.core.shared.materials.HasMap;
import thothbot.parallax.core.shared.materials.HasNormalMap;
import thothbot.parallax.core.shared.materials.HasSpecularMap;
import thothbot.parallax.core.shared.materials.HasVertexColors;
import thothbot.parallax.core.shared.materials.Material;
import thothbot.parallax.core.shared.materials.Material.COLORS;
import thothbot.parallax.core.shared.materials.MeshBasicMaterial;
import thothbot.parallax.core.shared.materials.MeshLambertMaterial;
import thothbot.parallax.core.shared.materials.MeshPhongMaterial;
import thothbot.parallax.core.shared.materials.ShaderMaterial;
import thothbot.parallax.core.shared.math.Color;
import thothbot.parallax.core.shared.math.Mathematics;
import thothbot.parallax.core.shared.math.Vector2;
import thothbot.parallax.core.shared.math.Vector3;
import thothbot.parallax.core.shared.math.Vector4;
import thothbot.parallax.loader.shared.json.JsoMaterial;
import thothbot.parallax.loader.shared.json.JsoMorphColors;
import thothbot.parallax.loader.shared.json.JsoMorphTargets;
import thothbot.parallax.loader.shared.json.JsoObject;
import thothbot.parallax.loader.shared.json.JsoObjectFactory;
import thothbot.parallax.loader.shared.json.JsoTextureWrapMode;

import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.json.client.JSONException;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;

public class JsonLoader extends XHRLoader {
    private JsoObject object;

    private List<Material> materials;

    public JsonLoader(String url, ModelLoadHandler modelLoadHandler) {
        super(url, modelLoadHandler);

        load();
    }

    @Override
    protected AbstractGeometry parse(String string) {
        if (!isThisJsonStringValid(string))
            return null;

        Log.debug("JSON parse()");

        Geometry geometry = new Geometry();

        parseMaterials();
        parseModel(geometry);

        parseSkin(geometry);
        parseMorphing(geometry);

        geometry.computeFaceNormals();
        geometry.computeBoundingSphere();

        if (hasNormals())
            geometry.computeTangents();

        geometry.computeMorphNormals();

        return geometry;
    }

    public List<Material> getMaterials() {
        return this.materials;
    }

    public void morphColorsToFaceColors(Geometry geometry) {
        if (geometry.getMorphColors() != null && geometry.getMorphColors().size() > 0) {
            MorphColor colorMap = geometry.getMorphColors().get(0);

            for (int i = 0; i < colorMap.colors.size(); i++) {
                geometry.getFaces().get(i).setColor(colorMap.colors.get(i));
                geometry.getFaces().get(i).getColor().offsetHSL(0, 0.3, 0);
            }
        }
    }

    private boolean isThisJsonStringValid(String iJSonString) {
        JsoObjectFactory factory = GWT.create(JsoObjectFactory.class);

        try {
            AutoBean<JsoObject> bean = AutoBeanCodex.decode(factory, JsoObject.class, iJSonString);
            object = bean.as();
        } catch (JSONException e) {
            Log.error("Could not parser JSON data");
            return false;
        }

        return true;
    }

    private void parseMaterials() {
        if (object.getMaterials() == null)
            return;

        Log.debug("JSON parseMaterials()");

        this.materials = new ArrayList<Material>();
        for (JsoMaterial material : object.getMaterials()) {
            this.materials.add(createMaterial(material));
        }
        //      geometry.setMaterials(this.materials);
    }

    private Material createMaterial(JsoMaterial jsonMaterial) {
        // defaults
        Material material = new MeshLambertMaterial();
        material.setOpacity(1.0);
        ((MeshLambertMaterial) material).setColor(new Color(0xeeeeee));

        if (jsonMaterial.getShading() != null) {
            if (jsonMaterial.getShading().compareToIgnoreCase("phong") == 0) {
                material = new MeshPhongMaterial();
            } else if (jsonMaterial.getShading().compareToIgnoreCase("basic") == 0) {
                material = new MeshBasicMaterial();
            }
        }

        // Special case for normal map
        if (jsonMaterial.getMapNormal() != null) {
            material = new ShaderMaterial(new NormalMapShader());
            ((ShaderMaterial) material).setLights(true);
            ((ShaderMaterial) material).setFog(true);
        }

        // parameters from model file

        if (jsonMaterial.getBlending() != null) {
            material.setBlending(jsonMaterial.getBlending().getValue());
        }

        material.setTransparent(jsonMaterial.getTransparent());
        material.setDepthTest(jsonMaterial.getDepthTest());
        material.setDepthWrite(jsonMaterial.getDepthWrite());

        if (jsonMaterial.getVertexColors() && material instanceof HasVertexColors) {
            ((HasVertexColors) material).setVertexColors(COLORS.VERTEX);
        }

        Color diffuseColor = (jsonMaterial.getColorDiffuse() != null) ? getColor(jsonMaterial.getColorDiffuse())
                : (jsonMaterial.getDbgColor() > 0) ? new Color(jsonMaterial.getDbgColor()) : null;

        if (diffuseColor != null) {
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("diffuse").setValue(diffuseColor);
            } else if (material instanceof HasColor) {
                ((HasColor) material).setColor(diffuseColor);
            }
        }

        if (jsonMaterial.getColorSpecular() != null) {
            Color color = getColor(jsonMaterial.getColorSpecular());
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("specular").setValue(color);
            } else if (material instanceof MeshPhongMaterial) {
                ((MeshPhongMaterial) material).setSpecular(color);
            }
        }

        if (jsonMaterial.getColorAmbient() != null) {
            Color color = getColor(jsonMaterial.getColorAmbient());
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("ambient").setValue(color);
            } else if (material instanceof HasAmbientEmissiveColor) {
                ((HasAmbientEmissiveColor) material).setAmbient(color);
            }
        }

        if (jsonMaterial.getColorEmissive() != null) {
            Color color = getColor(jsonMaterial.getColorEmissive());
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("emissive").setValue(color);
            } else if (material instanceof HasAmbientEmissiveColor) {
                ((HasAmbientEmissiveColor) material).setEmissive(color);
            }
        }

        if (jsonMaterial.getTransparent()) {
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("opacity").setValue(jsonMaterial.getTransparency());
            } else {

                material.setOpacity(jsonMaterial.getTransparency());
            }
        }

        if (jsonMaterial.getSpecularCoef() > 0) {
            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("shininess").setValue(jsonMaterial.getSpecularCoef());
            } else if (material instanceof MeshPhongMaterial) {
                ((MeshPhongMaterial) material).setShininess(jsonMaterial.getSpecularCoef());
            }
        }

        // textures

        if (jsonMaterial.getMapDiffuse() != null) {
            Texture texture = create_texture(jsonMaterial.getMapDiffuse(), jsonMaterial.getMapDiffuseRepeat(),
                    jsonMaterial.getMapDiffuseOffset(), jsonMaterial.getMapDiffuseWrap(),
                    jsonMaterial.getMapDiffuseAnisotropy());

            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("tDiffuse").setValue(texture);
                uniforms.get("enableDiffuse").setValue(true);
            } else if (material instanceof HasMap) {
                ((HasMap) material).setMap(texture);
            }
        }

        if (jsonMaterial.getMapLight() != null) {
            Texture texture = create_texture(jsonMaterial.getMapLight(), jsonMaterial.getMapLightRepeat(),
                    jsonMaterial.getMapLightOffset(), jsonMaterial.getMapLightWrap(),
                    jsonMaterial.getMapLightAnisotropy());

            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("tAO").setValue(texture);
                uniforms.get("enableAO").setValue(true);
            } else if (material instanceof HasLightMap) {
                ((HasLightMap) material).setLightMap(texture);
            }
        }

        if (jsonMaterial.getMapBump() != null && material instanceof HasBumpMap) {
            ((HasBumpMap) material).setBumpMap(create_texture(jsonMaterial.getMapBump(),
                    jsonMaterial.getMapBumpRepeat(), jsonMaterial.getMapBumpOffset(), jsonMaterial.getMapBumpWrap(),
                    jsonMaterial.getMapBumpAnisotropy()));

            if (jsonMaterial.getMapBumpScale() > 0) {
                ((HasBumpMap) material).setBumpScale(jsonMaterial.getMapBumpScale());
            }
        }

        if (jsonMaterial.getMapNormal() != null && material instanceof HasNormalMap) {
            Map<String, Uniform> uniforms = material.getShader().getUniforms();

            uniforms.get("tNormal")
                    .setValue(create_texture(jsonMaterial.getMapNormal(), jsonMaterial.getMapNormalRepeat(),
                            jsonMaterial.getMapNormalOffset(), jsonMaterial.getMapNormalWrap(),
                            jsonMaterial.getMapNormalAnisotropy()));

            if (jsonMaterial.getMapNormalFactor() > 0) {
                ((Vector2) uniforms.get("uNormalScale").getValue()).set(jsonMaterial.getMapNormalFactor(),
                        jsonMaterial.getMapNormalFactor());
            }
        }

        if (jsonMaterial.getMapSpecular() != null) {
            Texture texture = create_texture(jsonMaterial.getMapSpecular(), jsonMaterial.getMapSpecularRepeat(),
                    jsonMaterial.getMapSpecularOffset(), jsonMaterial.getMapSpecularWrap(),
                    jsonMaterial.getMapSpecularAnisotropy());

            if (material instanceof ShaderMaterial) {
                Map<String, Uniform> uniforms = material.getShader().getUniforms();
                uniforms.get("tSpecular").setValue(texture);
                uniforms.get("enableSpecular").setValue(true);
            } else if (material instanceof HasSpecularMap) {
                ((HasSpecularMap) material).setSpecularMap(texture);
            }
        }

        if (jsonMaterial.getMapAlpha() != null) {
            Texture texture = create_texture(jsonMaterial.getMapAlpha(), jsonMaterial.getMapAlphaRepeat(),
                    jsonMaterial.getMapAlphaOffset(), jsonMaterial.getMapAlphaWrap(),
                    jsonMaterial.getMapAlphaAnisotropy());

            if (material instanceof HasAlphaMap) {
                ((HasAlphaMap) material).setAlphaMap(texture);
            }
        }

        if (jsonMaterial.getDbgName() != null) {
            material.setName(jsonMaterial.getDbgName());
        }

        return material;
    }

    private void parseModel(Geometry geometry) {
        if (object.getFaces() == null)
            return;

        Log.debug("JSON parseFaces()");

        double scale = object.getScale() > 0 ? 1.0 / object.getScale() : 1.0;

        List<Integer> faces = object.getFaces();
        List<Double> vertices = object.getVertices();
        List<List<Double>> uvs = object.getUvs();
        List<Double> normals = object.getNormals();
        List<Integer> colors = object.getColors();

        int nUvLayers = 0;

        if (uvs != null) {
            // disregard empty arrays
            for (int i = 0; i < uvs.size(); i++) {
                if (uvs.get(i).size() > 0)
                    nUvLayers++;
            }

            // 0-index is initialized already
            for (int i = 0; i < nUvLayers; i++) {
                geometry.getFaceVertexUvs().add(i, new ArrayList<List<Vector2>>());
            }
        }

        int offset = 0;
        int zLength = vertices.size();

        while (offset < zLength) {

            Vector3 vertex = new Vector3();

            vertex.setX(vertices.get(offset++) * scale);
            vertex.setY(vertices.get(offset++) * scale);
            vertex.setZ(vertices.get(offset++) * scale);

            geometry.getVertices().add(vertex);

        }

        offset = 0;
        zLength = faces.size();

        while (offset < zLength) {
            int type = faces.get(offset++);

            boolean isQuad = isBitSet(type, 0);
            boolean hasMaterial = isBitSet(type, 1);
            boolean hasFaceVertexUv = isBitSet(type, 3);
            boolean hasFaceNormal = isBitSet(type, 4);
            boolean hasFaceVertexNormal = isBitSet(type, 5);
            boolean hasFaceColor = isBitSet(type, 6);
            boolean hasFaceVertexColor = isBitSet(type, 7);

            if (isQuad) {
                Face3 faceA = new Face3(faces.get(offset), faces.get(offset + 1), faces.get(offset + 3));

                Face3 faceB = new Face3(faces.get(offset + 1), faces.get(offset + 2), faces.get(offset + 3));

                offset += 4;

                if (hasMaterial) {

                    int materialIndex = faces.get(offset++);
                    faceA.setMaterialIndex(materialIndex);
                    faceB.setMaterialIndex(materialIndex);

                }

                // to get face <=> uv index correspondence

                int fi = geometry.getFaces().size();

                if (hasFaceVertexUv) {

                    for (int i = 0; i < nUvLayers; i++) {

                        List<Double> uvLayer = uvs.get(i);

                        geometry.getFaceVertexUvs().get(i).add(fi, new ArrayList<Vector2>());
                        geometry.getFaceVertexUvs().get(i).add(fi + 1, new ArrayList<Vector2>());

                        for (int j = 0; j < 4; j++) {

                            Integer uvIndex = faces.get(offset++);

                            Double u = uvLayer.get(uvIndex * 2);
                            Double v = uvLayer.get(uvIndex * 2 + 1);

                            Vector2 uv = new Vector2(u, v);

                            if (j != 2)
                                geometry.getFaceVertexUvs().get(i).get(fi).add(uv);
                            if (j != 0)
                                geometry.getFaceVertexUvs().get(i).get(fi + 1).add(uv);

                        }

                    }

                }

                if (hasFaceNormal) {

                    Integer normalIndex = faces.get(offset++) * 3;

                    faceA.getNormal().set(normals.get(normalIndex++), normals.get(normalIndex++),
                            normals.get(normalIndex));

                    faceB.getNormal().copy(faceA.getNormal());

                }

                if (hasFaceVertexNormal) {

                    for (int i = 0; i < 4; i++) {

                        Integer normalIndex = faces.get(offset++) * 3;

                        Vector3 normal = new Vector3(normals.get(normalIndex++), normals.get(normalIndex++),
                                normals.get(normalIndex));

                        if (i != 2)
                            faceA.getVertexNormals().add(normal);
                        if (i != 0)
                            faceB.getVertexNormals().add(normal);

                    }

                }

                if (hasFaceColor) {

                    Integer colorIndex = faces.get(offset++);
                    Integer hex = colors.get(colorIndex);

                    faceA.getColor().setHex(hex);
                    faceB.getColor().setHex(hex);

                }

                if (hasFaceVertexColor) {

                    for (int i = 0; i < 4; i++) {

                        Integer colorIndex = faces.get(offset++);
                        Integer hex = colors.get(colorIndex);

                        if (i != 2)
                            faceA.getVertexColors().add(new Color(hex));
                        if (i != 0)
                            faceB.getVertexColors().add(new Color(hex));

                    }

                }

                geometry.getFaces().add(faceA);
                geometry.getFaces().add(faceB);

            } else {

                Face3 face = new Face3(faces.get(offset++), faces.get(offset++), faces.get(offset++));

                if (hasMaterial) {

                    int materialIndex = faces.get(offset++);
                    face.setMaterialIndex(materialIndex);

                }

                // to get face <=> uv index correspondence

                if (hasFaceVertexUv) {

                    for (int i = 0; i < nUvLayers; i++) {

                        List<Double> uvLayer = uvs.get(i);

                        ArrayList<Vector2> getFaceVertexUvs = new ArrayList<Vector2>();
                        int fi = geometry.getFaces().size();

                        for (int j = 0; j < 3; j++) {

                            Integer uvIndex = faces.get(offset++);

                            double u = uvLayer.get(uvIndex * 2);
                            double v = uvLayer.get(uvIndex * 2 + 1);

                            Vector2 uv = new Vector2(u, v);

                            getFaceVertexUvs.add(uv);

                        }

                        geometry.getFaceVertexUvs().get(i).add(getFaceVertexUvs);

                    }

                }

                if (hasFaceNormal) {

                    Integer normalIndex = faces.get(offset++) * 3;

                    face.getNormal().set(normals.get(normalIndex++), normals.get(normalIndex++),
                            normals.get(normalIndex));

                }

                if (hasFaceVertexNormal) {

                    for (int i = 0; i < 3; i++) {

                        Integer normalIndex = faces.get(offset++) * 3;

                        Vector3 normal = new Vector3(normals.get(normalIndex++), normals.get(normalIndex++),
                                normals.get(normalIndex));

                        face.getVertexNormals().add(normal);

                    }

                }

                if (hasFaceColor) {

                    Integer colorIndex = faces.get(offset++);
                    face.getColor().setHex(colors.get(colorIndex));

                }

                if (hasFaceVertexColor) {

                    for (int i = 0; i < 3; i++) {

                        Integer colorIndex = faces.get(offset++);
                        face.getVertexColors().add(new Color(colors.get(colorIndex)));

                    }

                }

                geometry.getFaces().add(face);

            }
        }
    }

    private void parseSkin(Geometry geometry) {
        int influencesPerVertex = (object.getInfluencesPerVertex() > 0) ? object.getInfluencesPerVertex() : 2;

        Log.debug("JSON parseSkin()");

        if (object.getSkinWeights() != null) {
            List<Double> skinWeights = object.getSkinWeights();
            for (int i = 0, l = skinWeights.size(); i < l; i += influencesPerVertex) {
                double x = skinWeights.get(i);
                double y = (influencesPerVertex > 1) ? skinWeights.get(i + 1) : 0;
                double z = (influencesPerVertex > 2) ? skinWeights.get(i + 2) : 0;
                double w = (influencesPerVertex > 3) ? skinWeights.get(i + 3) : 0;

                geometry.getSkinWeights().add(new Vector4(x, y, z, w));
            }

        }

        if (object.getSkinIndices() != null) {
            List<Integer> skinIndices = object.getSkinIndices();

            for (int i = 0, l = skinIndices.size(); i < l; i += 2) {
                double a = skinIndices.get(i);
                double b = (influencesPerVertex > 1) ? skinIndices.get(i + 1) : 0;
                double c = (influencesPerVertex > 2) ? skinIndices.get(i + 2) : 0;
                double d = (influencesPerVertex > 3) ? skinIndices.get(i + 3) : 0;

                geometry.getSkinIndices().add(new Vector4(a, b, c, d));
            }
        }

        //       geometry.bones = json.bones;
        //      geometry.animation = json.animation;
    }

    private void parseMorphing(Geometry geometry) {
        Log.debug("JSON parseMorphing()");

        double scale = object.getScale() > 0 ? 1.0 / object.getScale() : 1.0;

        if (object.getMorphTargets() != null) {
            List<JsoMorphTargets> morphTargets = object.getMorphTargets();

            for (int i = 0, l = morphTargets.size(); i < l; i++) {
                Geometry.MorphTarget morphTarget = geometry.new MorphTarget();
                morphTarget.name = morphTargets.get(i).getName();
                morphTarget.vertices = new ArrayList<Vector3>();

                List<Double> srcVertices = morphTargets.get(i).getVertices();
                for (int v = 0, vl = srcVertices.size(); v < vl; v += 3) {
                    morphTarget.vertices.add(new Vector3(srcVertices.get(v) * scale, srcVertices.get(v + 1) * scale,
                            srcVertices.get(v + 2) * scale));
                }

                geometry.getMorphTargets().add(morphTarget);
            }
        }

        if (object.getMorphColors() != null) {
            List<JsoMorphColors> morphColors = object.getMorphColors();

            for (int i = 0, l = morphColors.size(); i < l; i++) {
                Geometry.MorphColor morphColor = geometry.new MorphColor();
                morphColor.name = morphColors.get(i).getName();
                morphColor.colors = new ArrayList<Color>();

                List<Double> srcColors = morphColors.get(i).getColors();
                for (int c = 0, cl = srcColors.size(); c < cl; c += 3) {
                    Color color = new Color(0xffaa00);
                    color.setRGB(srcColors.get(c), srcColors.get(c + 1), srcColors.get(c + 2));
                    morphColor.colors.add(color);
                }

                geometry.getMorphColors().add(morphColor);
            }
        }
    }

    private boolean isBitSet(int value, int position) {
        return (value & (1 << position)) > 0;
    }

    private Texture create_texture(String sourceFile, List<Integer> repeat, List<Double> offset,
            List<JsoTextureWrapMode> wrap, int anisotropy) {
        boolean isCompressed = sourceFile.toLowerCase().endsWith(".dds");
        final String fullPath = getTexturePath() + sourceFile;

        final Texture texture;

        if (isCompressed) {
            texture = new CompressedTexture(fullPath);
        } else {
            texture = new Texture(fullPath, new Texture.ImageLoadHandler() {

                @Override
                public void onImageLoad(Texture texture) {
                    int oWidth = texture.getImage().getOffsetWidth();
                    int oHeight = texture.getImage().getOffsetHeight();

                    if (!Mathematics.isPowerOfTwo(oWidth) || !Mathematics.isPowerOfTwo(oHeight)) {
                        CanvasElement canvas = Document.get().createElement("canvas").cast();
                        int width = Mathematics.getNextHighestPowerOfTwo(oWidth);
                        int height = Mathematics.getNextHighestPowerOfTwo(oHeight);
                        canvas.setWidth(width);
                        canvas.setHeight(height);

                        Context2d context = canvas.getContext2d();
                        context.drawImage((ImageElement) texture.getImage(), 0, 0, width, height);

                        texture.setImage(canvas);
                    }

                    texture.setNeedsUpdate(true);
                }
            });
            texture.setNeedsUpdate(false);
        }

        if (repeat != null) {
            texture.getRepeat().set(repeat.get(0), repeat.get(1));

            if (repeat.get(0) != 1)
                texture.setWrapS(TextureWrapMode.REPEAT);
            if (repeat.get(1) != 1)
                texture.setWrapT(TextureWrapMode.REPEAT);
        }

        if (offset != null) {
            texture.getOffset().set(offset.get(0), offset.get(1));
        }

        if (wrap != null) {
            if (wrap.get(0) != null)
                texture.setWrapS(wrap.get(0).getValue());
            if (wrap.get(1) != null)
                texture.setWrapT(wrap.get(1).getValue());
        }

        if (anisotropy > 0) {
            texture.setAnisotropy(anisotropy);
        }
        return texture;
    }

    private Color getColor(List<Double> rgb) {
        return new Color(
                ((int) (rgb.get(0) * 255) << 16) + ((int) (rgb.get(1) * 255) << 8) + (int) (rgb.get(2) * 255));
    }

    private boolean hasNormals() {
        for (int i = 0; i < this.materials.size(); i++)
            if (this.materials.get(i) instanceof ShaderMaterial)
                return true;

        return false;
    }
}