package electrosphere.renderer;

import electrosphere.main.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.renderer.texture.Texture;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;

/**
 *
 * @author satellite
 */
public class ModelUtils {
//    public static Model createTerrainModel(float[][] heightfield, int stride){
//        Model rVal = new Model();
//        rVal.meshes = new ArrayList();
//        Mesh m = new Mesh();
//        int width = heightfield.length;
//        int height = heightfield[0].length;
//        
//        int actualWidth = (int)Math.ceil(1.0 * width / stride);
//        int actualHeight = (int)Math.ceil(1.0 * height / stride);
//        
////        System.out.println(actualWidth + " " + actualHeight);
//        
////        System.out.println((actualWidth - 1) * (actualHeight - 1));
//        
//        FloatBuffer vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
//        FloatBuffer normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
//        IntBuffer faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3);
//        FloatBuffer texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 2);
//        for(int x = 0; x < width; x = x + stride){
//            for(int y = 0; y < height; y = y + stride){
//                //deal with vertex
//                vertices.put(x);
//                vertices.put(heightfield[x][y]);
//                vertices.put(y);
//                //deal with normal
//                if(x / stride < actualWidth - 1){
//                    if(y / stride < actualHeight - 1){
//                        float hL;
//                        if(x > 0){
//                            hL = heightfield[x-1][y];
//                        } else {
//                            hL = heightfield[x][y];
//                        }
//                        float hR = heightfield[x+1][y];
//                        float hD = heightfield[x][y+1];
//                        float hU;
//                        if(y > 0){
//                            hU = heightfield[x][y-1];
//                        } else {
//                            hU = heightfield[x][y];
//                        }
//                        Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
//                        Normal.normalize();
//                        normals.put(Normal.x);
//                        normals.put(Normal.y);
//                        normals.put(Normal.z);
//                    } else {
//                        float hL;
//                        if(x > 0){
//                            hL = heightfield[x-1][y];
//                        } else {
//                            hL = heightfield[x][y];
//                        }
//                        float hR = heightfield[x+1][y];
//                        float hD = heightfield[x][y];
//                        float hU = heightfield[x][y-1];
//                        Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
//                        Normal.normalize();
//                        normals.put(Normal.x);
//                        normals.put(Normal.y);
//                        normals.put(Normal.z);
//                    }
//                } else {
//                    if(y / stride < actualHeight - 1){
//                        float hL = heightfield[x-1][y];
//                        float hR = heightfield[x][y];
//                        float hD = heightfield[x][y+1];
//                        float hU;
//                        if(y > 0){
//                            hU = heightfield[x][y-1];
//                        } else {
//                            hU = heightfield[x][y];
//                        }
//                        Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
//                        Normal.normalize();
//                        normals.put(Normal.x);
//                        normals.put(Normal.y);
//                        normals.put(Normal.z);
//                    } else {
//                        float hL = heightfield[x-1][y];
//                        float hR = heightfield[x][y];
//                        float hD = heightfield[x][y];
//                        float hU = heightfield[x][y-1];
//                        Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
//                        Normal.normalize();
//                        normals.put(Normal.x);
//                        normals.put(Normal.y);
//                        normals.put(Normal.z);
//                    }
//                }
//                //deal with texture coordinates
//                if(x / stride % 2 == 0){
//                    if(y / stride % 2 == 0){
//                        texture_coords.put(0);
//                        texture_coords.put(0);
//                    } else {
//                        texture_coords.put(0);
//                        texture_coords.put(1);
//                    }
//                } else {
//                    if(y / stride % 2 == 0){
//                        texture_coords.put(1);
//                        texture_coords.put(0);
//                    } else {
//                        texture_coords.put(1);
//                        texture_coords.put(1);
//                    }
//                }
//                //deal with faces
//                if(x / stride < actualWidth - 1 && y / stride < actualHeight - 1){
//                    faces.put((x / stride + 0) * actualHeight + (y / stride + 0));
//                    faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
//                    faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
//                    faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
//                    faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
//                    faces.put((x / stride + 1) * actualHeight + (y / stride + 1));
//                }
//            }
//        }
//        vertices.flip();
//        normals.flip();
//        faces.flip();
//        texture_coords.flip();
//        
//        m.vertexArrayObject = glGenVertexArrays();
//        glBindVertexArray(m.vertexArrayObject);
//        //buffer vertices
//        m.buffer_vertices(vertices, 3);
//        //buffer normals
//        m.buffer_normals(normals, 3);
//        //buffer faces
//        m.buffer_faces(faces);
//        //buffer texture coords
//        m.buffer_texture_coords(texture_coords, 2);
//        m.shader = ShaderProgram.loadSpecificShader("/Shaders/terrain/terrain.vs", "/Shaders/terrain/terrain.fs");
//        glBindVertexArray(0);
//        m.parent = rVal;
//        
//        Material groundMat = new Material();
//        Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png");
//        groundMat.set_diffuse("/Textures/Ground/Dirt1.png");
//        groundMat.set_specular("/Textures/Ground/Dirt1.png");
//        m.set_material(groundMat);
//        
//        rVal.meshes.add(m);
//        return rVal;
//    }
    
    public static Model createTerrainModelPrecomputedShader(float[][] heightfield, float[][] texturemap, ShaderProgram program, int stride){
        Model rVal = new Model();
        rVal.meshes = new ArrayList();
        Mesh m = new Mesh();
        int width = heightfield.length;
        int height = heightfield[0].length;
        
        int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride));
        int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride));
        
        
//        System.out.println(actualWidth + " " + actualHeight);
        
//        System.out.println((actualWidth - 1) * (actualHeight - 1));
        
        FloatBuffer vertices;
        FloatBuffer normals;
        IntBuffer faces;
        FloatBuffer texture_coords;
        FloatBuffer textureIndices;
        if(stride * actualWidth > width){
            int drawWidth = actualWidth + 1;
            int drawHeight = actualHeight + 1;
            vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12);
            normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12);
            faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3);
            texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8);
            textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16);
        } else {
            vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12);
            normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12);
            faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3);
            texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8);
            textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16);
        }
        
        int incrementer = 0;
        int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3;
        for(int x = 0; x < width - 1; x = x + stride){
            for(int y = 0; y < height - 1; y = y + stride){
                //deal with vertex
                //0,0
                vertices.put(x);
                vertices.put(heightfield[x][y]);
                vertices.put(y);
                //1,0
                vertices.put(x + stride);
                vertices.put(heightfield[x+stride][y]);
                vertices.put(y);
                //0,1
                vertices.put(x);
                vertices.put(heightfield[x][y+stride]);
                vertices.put(y + stride);
                //1,1
                vertices.put(x + stride);
                vertices.put(heightfield[x+stride][y+stride]);
                vertices.put(y + stride);
                //deal with normal
                Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y);
                normals.put(normal.x);
                normals.put(normal.y);
                normals.put(normal.z);
                normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y);
                normals.put(normal.x);
                normals.put(normal.y);
                normals.put(normal.z);
                normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride);
                normals.put(normal.x);
                normals.put(normal.y);
                normals.put(normal.z);
                normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride);
                normals.put(normal.x);
                normals.put(normal.y);
                normals.put(normal.z);
                //deal with texture coordinates
//                if(x / stride % 2 == 0){
//                    if(y / stride % 2 == 0){
//                        texture_coords.put(0);
//                        texture_coords.put(0);
//                        texture_coords.put(1);
//                        texture_coords.put(0);
//                        texture_coords.put(0);
//                        texture_coords.put(1);
//                        texture_coords.put(1);
//                        texture_coords.put(1);
//                    } else {
//                        texture_coords.put(0);
//                        texture_coords.put(1);
//                    }
//                } else {
//                    if(y / stride % 2 == 0){
//                        texture_coords.put(1);
//                        texture_coords.put(0);
//                    } else {
//                        texture_coords.put(1);
//                        texture_coords.put(1);
//                    }
//                }
                texture_coords.put(0);
                texture_coords.put(0);
                texture_coords.put(1);
                texture_coords.put(0);
                texture_coords.put(0);
                texture_coords.put(1);
                texture_coords.put(1);
                texture_coords.put(1);
                
                if(x + stride < width - 1 && y + stride < height - 1){
//                    texturemap[x+stride][y+stride];
                    for(int i = 0; i < 4 ; i++){
//                        textureIndices.put(1);
//                        textureIndices.put(0);
//                        textureIndices.put(0);
//                        textureIndices.put(0);
                        textureIndices.put(texturemap[x][y]);
                        textureIndices.put(texturemap[x+stride][y]);
                        textureIndices.put(texturemap[x][y+stride]);
                        textureIndices.put(texturemap[x+stride][y+stride]);
                    }
                } else {
                    for(int i = 0; i < 4 ; i++){
                        textureIndices.put(0);
                        textureIndices.put(0);
                        textureIndices.put(0);
                        textureIndices.put(0);
                    }
                }
                
                
                //deal with faces
                if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){
                    faces.put(incrementer * 4 + 0);
                    faces.put(incrementer * 4 + 1);
                    faces.put(incrementer * 4 + 2);
                    faces.put(incrementer * 4 + 1);
                    faces.put(incrementer * 4 + 2);
                    faces.put(incrementer * 4 + 3);
                }
                incrementer++;
            }
        }
        
        vertices.flip();
        normals.flip();
        faces.flip();
        texture_coords.flip();
        textureIndices.flip();
        
        m.vertexArrayObject = glGenVertexArrays();
        glBindVertexArray(m.vertexArrayObject);
        //buffer vertices
        m.buffer_vertices(vertices, 3);
        //buffer normals
        m.buffer_normals(normals, 3);
        //buffer faces
        m.buffer_faces(faces);
        //buffer texture coords
        m.buffer_texture_coords(texture_coords, 2);
        //texture indices
        m.bufferCustomFloatAttribArray(textureIndices, 4, 5);
        m.shader = program;
        glBindVertexArray(0);
        m.parent = rVal;
        
        m.hasBones = false;
        
        Material groundMat = new Material();
        Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png");
        groundMat.set_diffuse("/Textures/Ground/Dirt1.png");
        groundMat.set_specular("/Textures/Ground/Dirt1.png");
        m.setMaterial(groundMat);
        
        rVal.meshes.add(m);
        return rVal;
    }
    
    static Vector3f calculateTerrainNormal(float[][] heightfield, int actualWidth, int actualHeight, int stride, int x, int y){
        Vector3f rVal = new Vector3f();
        if(x / stride < actualWidth - 1){
            if(y / stride < actualHeight - 1){
                float hL;
                if(x > 0){
                    hL = heightfield[x-1][y];
                } else {
                    hL = heightfield[x][y];
                }
                float hR = heightfield[x+1][y];
                float hD = heightfield[x][y+1];
                float hU;
                if(y > 0){
                    hU = heightfield[x][y-1];
                } else {
                    hU = heightfield[x][y];
                }
                rVal = new Vector3f(hL - hR, 2.0f, hD - hU);
                rVal.normalize();
            } else {
                float hL;
                if(x > 0){
                    hL = heightfield[x-1][y];
                } else {
                    hL = heightfield[x][y];
                }
                float hR = heightfield[x+1][y];
                float hD = heightfield[x][y];
                float hU = heightfield[x][y-1];
                rVal = new Vector3f(hL - hR, 2.0f, hD - hU);
                rVal.normalize();
            }
        } else {
            if(y / stride < actualHeight - 1){
                float hL = heightfield[x-1][y];
                float hR = heightfield[x][y];
                float hD = heightfield[x][y+1];
                float hU;
                if(y > 0){
                    hU = heightfield[x][y-1];
                } else {
                    hU = heightfield[x][y];
                }
                rVal = new Vector3f(hL - hR, 2.0f, hD - hU);
                rVal.normalize();
            } else {
                float hL = heightfield[x-1][y];
                float hR = heightfield[x][y];
                float hD = heightfield[x][y];
                float hU = heightfield[x][y-1];
                rVal = new Vector3f(hL - hR, 2.0f, hD - hU);
                rVal.normalize();
            }
        }
        return rVal;
    }
    
    
    public static Model createUnitCube(){
        Model rVal = new Model();
        rVal.meshes = new ArrayList();
        Mesh m = new Mesh();
        
//        System.out.println(actualWidth + " " + actualHeight);
        
//        System.out.println((actualWidth - 1) * (actualHeight - 1));
        
        FloatBuffer vertices = BufferUtils.createFloatBuffer(8 * 3);
        FloatBuffer normals = BufferUtils.createFloatBuffer(8 * 3);
        IntBuffer faces = BufferUtils.createIntBuffer(6 * 2 * 3);
        FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8 * 2);
        
        //vertices
        //0,0,0
        vertices.put(0);
        vertices.put(0);
        vertices.put(0);
        //1,0,0
        vertices.put(1);
        vertices.put(0);
        vertices.put(0);
        //0,1,0
        vertices.put(0);
        vertices.put(1);
        vertices.put(0);
        //1,1,0
        vertices.put(1);
        vertices.put(1);
        vertices.put(0);
        //0,0,1
        vertices.put(0);
        vertices.put(0);
        vertices.put(1);
        //1,0,1
        vertices.put(1);
        vertices.put(0);
        vertices.put(1);
        //0,1,1
        vertices.put(0);
        vertices.put(1);
        vertices.put(1);
        //1,1,1
        vertices.put(1);
        vertices.put(1);
        vertices.put(1);
        
        //normals
        //-1,-1,-1
        normals.put(-1);
        normals.put(-1);
        normals.put(-1);
        // 1,-1,-1
        normals.put( 1);
        normals.put(-1);
        normals.put(-1);
        //-1, 1,-1
        normals.put(-1);
        normals.put( 1);
        normals.put(-1);
        // 1, 1,-1
        normals.put( 1);
        normals.put( 1);
        normals.put(-1);
        //-1,-1, 1
        normals.put(-1);
        normals.put(-1);
        normals.put( 1);
        // 1,-1, 1
        normals.put( 1);
        normals.put(-1);
        normals.put( 1);
        //-1, 1, 1
        normals.put(-1);
        normals.put( 1);
        normals.put( 1);
        // 1, 1, 1
        normals.put( 1);
        normals.put( 1);
        normals.put( 1);
        
        //faces
        //0,1,2
        faces.put(0);
        faces.put(1);
        faces.put(2);
        //1,2,3
        faces.put(1);
        faces.put(2);
        faces.put(3);
        //1,3,5
        faces.put(1);
        faces.put(3);
        faces.put(5);
        //3,5,7
        faces.put(3);
        faces.put(5);
        faces.put(7);
        //0,1,4
        faces.put(0);
        faces.put(1);
        faces.put(4);
        //1,4,5
        faces.put(1);
        faces.put(4);
        faces.put(5);
        //0,2,4
        faces.put(0);
        faces.put(2);
        faces.put(4);
        //2,4,6
        faces.put(2);
        faces.put(4);
        faces.put(6);
        //2,3,6
        faces.put(2);
        faces.put(3);
        faces.put(6);
        //3,6,7
        faces.put(3);
        faces.put(6);
        faces.put(7);
        //4,5,6
        faces.put(4);
        faces.put(5);
        faces.put(6);
        //5,6,7
        faces.put(5);
        faces.put(6);
        faces.put(7);
        
        //texture
        for(int i = 0; i < 8 * 2; i++){
            texture_coords.put(0);
        }
        
        
        vertices.flip();
        normals.flip();
        faces.flip();
        texture_coords.flip();
        
        m.vertexArrayObject = glGenVertexArrays();
        glBindVertexArray(m.vertexArrayObject);
        //buffer vertices
        m.buffer_vertices(vertices, 3);
        //buffer normals
        m.buffer_normals(normals, 3);
        //buffer faces
        m.buffer_faces(faces);
        //buffer texture coords
        m.buffer_texture_coords(texture_coords, 2);
        m.shader = ShaderProgram.smart_assemble_shader(false,true);
        glBindVertexArray(0);
        m.parent = rVal;
        
        Material groundMat = new Material();
        Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png");
        groundMat.set_diffuse("/Textures/Ground/Dirt1.png");
        groundMat.set_specular("/Textures/Ground/Dirt1.png");
        m.setMaterial(groundMat);
        
        rVal.meshes.add(m);
        return rVal;
    }
    
    public static void printModelDimension(Model m){
        float minX = 0;
        float maxX = 0;
        float minY = 0;
        float maxY = 0;
        float minZ = 0;
        float maxZ = 0;
        boolean initiated = false;
        
        for(Mesh currentMesh : m.meshes){
            if(initiated){
                if(currentMesh.vertexMinX < minX){ minX = currentMesh.vertexMinX; }
                if(currentMesh.vertexMaxX > maxX){ maxX = currentMesh.vertexMaxX; }
                if(currentMesh.vertexMinY < minY){ minY = currentMesh.vertexMinY; }
                if(currentMesh.vertexMaxY > maxY){ maxY = currentMesh.vertexMaxY; }
                if(currentMesh.vertexMinZ < minZ){ minZ = currentMesh.vertexMinZ; }
                if(currentMesh.vertexMaxZ > maxZ){ maxZ = currentMesh.vertexMaxZ; }
            } else {
                initiated = true;
                minX = currentMesh.vertexMinX;
                maxX = currentMesh.vertexMaxX;
                minY = currentMesh.vertexMinY;
                maxY = currentMesh.vertexMaxY;
                minZ = currentMesh.vertexMinZ;
                maxZ = currentMesh.vertexMaxZ;
            }
        }
        System.out.println("dimensions: " + (maxX - minX) + "," + (maxY - minY) + "," + (maxZ-minZ));
    }
    
    public static Model createBitmapDisplay(){
        
        Model rVal = new Model();
        rVal.meshes = new ArrayList();
        Mesh m = new Mesh();
        m.vertexArrayObject = glGenVertexArrays();
        glBindVertexArray(m.vertexArrayObject);
        //vertices
        FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(12);
        VertexArrayBufferData.put( 0);
        VertexArrayBufferData.put( 1);
        
        VertexArrayBufferData.put( 0);
        VertexArrayBufferData.put( 0);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put( 0);
        
        VertexArrayBufferData.put( 0);
        VertexArrayBufferData.put( 1);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put( 0);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.flip();
        
        
        IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6);
        faceArrayBufferData.put(0);
        faceArrayBufferData.put(1);
        faceArrayBufferData.put(2);
        
        faceArrayBufferData.put(3);
        faceArrayBufferData.put(4);
        faceArrayBufferData.put(5);
        faceArrayBufferData.flip();
        
        
        
        //texture coords
        FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(12);
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(1);
        
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(1);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.flip();
        
        
        //buffer vertices
        m.buffer_vertices(VertexArrayBufferData, 2);
        //buffer normals
        m.buffer_normals(VertexArrayBufferData, 2);
        //buffer faces
        m.buffer_faces(faceArrayBufferData);
        //buffer texture coords
        m.buffer_texture_coords(TextureArrayBufferData, 2);
        
        
        m.shader = ShaderProgram.loadSpecificShader("/Shaders/font/basicbitmap/basicbitmap.vs", "/Shaders/font/basicbitmap/basicbitmap.fs");
        
        
        glBindVertexArray(0);
        m.parent = rVal;
        m.nodeID = AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME;
        
        Material uiMat = new Material();
        Globals.assetManager.addTexturePathtoQueue("/Textures/Fonts/myfont1-harsher.png");
        uiMat.set_diffuse("/Textures/Fonts/myfont1-harsher.png");
        uiMat.set_specular("/Textures/Fonts/myfont1-harsher.png");
        m.setMaterial(uiMat);
        rVal.materials = new ArrayList();
        rVal.materials.add(uiMat);
        
        rVal.meshes.add(m);
        
        return rVal;
    }
    
    
    
    
    
    
    public static Model createBitmapCharacter(){
        
        Model rVal = new Model();
        rVal.meshes = new ArrayList();
        Mesh m = new Mesh();
        m.vertexArrayObject = glGenVertexArrays();
        glBindVertexArray(m.vertexArrayObject);
        //vertices
        FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(12);
        VertexArrayBufferData.put(-1);
        VertexArrayBufferData.put( 1);
        
        VertexArrayBufferData.put(-1);
        VertexArrayBufferData.put(-1);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put(-1);
        
        VertexArrayBufferData.put(-1);
        VertexArrayBufferData.put( 1);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put(-1);
        
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.put( 1);
        VertexArrayBufferData.flip();
        
        
        IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6);
        faceArrayBufferData.put(0);
        faceArrayBufferData.put(1);
        faceArrayBufferData.put(2);
        
        faceArrayBufferData.put(3);
        faceArrayBufferData.put(4);
        faceArrayBufferData.put(5);
        faceArrayBufferData.flip();
        
        
        
        //texture coords
        FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(12);
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(1);
        
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(0);
        TextureArrayBufferData.put(1);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(0);
        
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.put(1);
        TextureArrayBufferData.flip();
        
        
        //buffer vertices
        m.buffer_vertices(VertexArrayBufferData, 2);
        //buffer normals
        m.buffer_normals(VertexArrayBufferData, 2);
        //buffer faces
        m.buffer_faces(faceArrayBufferData);
        //buffer texture coords
        m.buffer_texture_coords(TextureArrayBufferData, 2);
        
        
        m.shader = ShaderProgram.loadSpecificShader("/Shaders/font/bitmapchar/bitmapchar.vs", "/Shaders/font/bitmapchar/bitmapchar.fs");
        
        
        glBindVertexArray(0);
        m.parent = rVal;
        m.nodeID = AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME;
        
        Material uiMat = new Material();
        Globals.assetManager.addTexturePathtoQueue("/Textures/Fonts/myfont1-harsher.png");
        uiMat.set_diffuse("/Textures/Fonts/myfont1-harsher.png");
        uiMat.set_specular("/Textures/Fonts/myfont1-harsher.png");
        m.setMaterial(uiMat);
        rVal.materials = new ArrayList();
        rVal.materials.add(uiMat);
        
        rVal.meshes.add(m);
        
        return rVal;
    }
    
    
    
    
    
    
    
    
}
