Package Hexel.rendering

Source Code of Hexel.rendering.GLChunk

package Hexel.rendering;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import Hexel.Engine;
import Hexel.blocks.types.Block;
import Hexel.blocks.types.BlockEmpty;
import Hexel.blocks.types.BlockTransparent;
import Hexel.chunk.Chunk;
import Hexel.chunk.Chunks;
import Hexel.math.HexGeometry;
import Hexel.math.Vector2d;
import Hexel.math.Vector3i;
import Hexel.util.MutableFloat;
import Hexel.util.ResourcePool;

import com.jogamp.common.nio.Buffers;

public class GLChunk {
  public ArrayList<MutableFloat> vertexData;
  public List<MutableFloat> trimmedVertexData;
  public Vector3i position;
  public GLBuffer buffer;
  public Chunk chunk;
  public Chunks chunks;
  private Engine engine;

  public GLChunk(Engine engine, Chunk chunk, Chunks chunks) {
    this.engine = engine;
    this.chunk = chunk;
    this.chunks = chunks;
  }

  public void initBuffer(GL2 gl) {
    if (this.trimmedVertexData.size() == 0) {
      this.buffer = null;
      vertexDataPool.recycle(this.vertexData);
      this.vertexData = null;
      this.trimmedVertexData = null;
      return;
    }

    int[] bufferId = new int[] { -1 };

    gl.glGenBuffers(1, bufferId, 0);
    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferId[0]);
    gl.glBufferData(GL.GL_ARRAY_BUFFER, this.trimmedVertexData.size()
        * Buffers.SIZEOF_FLOAT, null, GL.GL_DYNAMIC_DRAW);

    ByteBuffer byteBuffer = gl.glMapBuffer(GL.GL_ARRAY_BUFFER,
        GL.GL_WRITE_ONLY);
    FloatBuffer buffer = byteBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
    for (MutableFloat aVertexData : this.trimmedVertexData) {
      buffer.put(aVertexData.val);
    }
    gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);

    this.buffer = new GLBuffer(bufferId, this.trimmedVertexData.size() * Buffers.SIZEOF_FLOAT);


    vertexDataPool.recycle(this.vertexData);
    this.vertexData = null;
    this.trimmedVertexData = null;
  }

  private boolean display(Block b, Block o, Face face) {
    double bfb = b.getFracBottom();
    double bft = b.getFracTop();
    double ofb = o.getFracBottom();
    double oft = o.getFracTop();
    return o instanceof BlockTransparent && o.getClass() != b.getClass()
        || face == Face.TOP && (ofb != 0 || bft != 1)
        || face == Face.BOTTOM && (oft != 1 || bfb != 0)
        || ofb < ofb || bft > oft;
  }

  private static ResourcePool<ArrayList<MutableFloat>> vertexDataPool =
      new ResourcePool<ArrayList<MutableFloat>>((Class<ArrayList<MutableFloat>>) new ArrayList<MutableFloat>().getClass());

  public void genArrayList() {
    this.vertexData = vertexDataPool.aquire();

    Vector2d a = new Vector2d();
    Vector2d b = new Vector2d();
    Vector2d c = new Vector2d();
    Vector2d d = new Vector2d();

    Vector3i tmp = new Vector3i();

    Rect r = new Rect();

    Color color = new Color();

    int index = 0;
    for (int x = 0; x < 32; x++) {
      for (int y = 0; y < 16; y++) {
        for (int z = 0; z < 32; z++) {
          Block block = this.chunk.get(x, y, z);
          if (block instanceof BlockEmpty)
            continue;
          int px = x / 2;
          if (x % 2 == 0) {
            HexGeometry.hexToCartesian(px, y, a);
            HexGeometry.hexToCartesian(px, y + 1, b);
            HexGeometry.hexToCartesian(px + 1, y, c);
            HexGeometry.hexToCartesian(px + 0.5, y + 0.5, d);
          } else {
            HexGeometry.hexToCartesian(px + 1, y + 1, a);
            HexGeometry.hexToCartesian(px, y + 1, b);
            HexGeometry.hexToCartesian(px + 1, y, c);
            HexGeometry.hexToCartesian(px + 0.5, y + 0.5, d);
          }

          Block blockZP = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x, y, z + 1, tmp, chunk);
          boolean displayZP = display(block, blockZP, Face.TOP);

          Block blockZM = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x, y, z - 1, tmp, chunk);
          boolean displayZM = display(block, blockZM, Face.BOTTOM);

          // NOTE faces wrong but it doesn't matter here, see below
          // for correct
          Block blockXP = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x + 1, y, z, tmp, chunk);
          boolean displayXP = display(block, blockXP, Face.SIDEA);

          Block blockXM = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x - 1, y, z, tmp, chunk);
          boolean displayXM = display(block, blockXM, Face.SIDEB);

          Block blockYP = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x - 1, y + 1, z, tmp, chunk);
          boolean displayYP = display(block, blockYP, Face.SIDEC);

          Block blockYM = this.chunks.getBlock(this.chunk.cx, this.chunk.cy,
              this.chunk.cz, x + 1, y - 1, z, tmp, chunk);
          boolean displayYM = display(block, blockYM, Face.SIDEB);

          double fracBottom = block.getFracBottom();
          double fracTop = block.getFracTop();

          double topz = z / 2.0 + .5 * fracTop;
          double bottomz = z / 2.0 + .5 * fracBottom;

          int damageOffset;
          if (block.getMaxHealth() == 0)
            damageOffset = 0;
          else
            damageOffset = 4 * (int) (5 * (1 - block.getHealth()*1.0 / block.getMaxHealth()));

          if (damageOffset < 0)
            damageOffset = 0;
          else if (damageOffset > 4 * 4)
            damageOffset = 4 * 4;

          if (displayZM) {

            getColor(block, blockZM, color, Face.BOTTOM, x);

            getTexRect(damageOffset + block.getBottomTextureIndex(), r);

            index = addVertexData(this.vertexData, index, a.x, a.y, bottomz, r.l, r.t,
                color);
            index = addVertexData(this.vertexData, index, b.x, b.y, bottomz, r.l, r.b,
                color);
            index = addVertexData(this.vertexData, index, d.x, d.y, bottomz, r.r, r.b,
                color);

            index = addVertexData(this.vertexData, index, a.x, a.y, bottomz, r.l, r.t,
                color);
            index = addVertexData(this.vertexData, index, c.x, c.y, bottomz, r.r, r.t,
                color);
            index = addVertexData(this.vertexData, index, d.x, d.y, bottomz, r.r, r.b,
                color);
          }

          {
            getTexRect(damageOffset + block.getSideTextureIndex(), r);

            if (x % 2 == 1 && displayYP
                || x % 2 == 0 && displayXM) {

              if (x % 2 == 1)
                getColor(block, blockYP, color, Face.SIDEA, x);
              else
                getColor(block, blockXM, color, Face.SIDEA, x);

              index = addVertexData(this.vertexData, index, a.x, a.y, bottomz, r.l,
                  r.t, color);
              index = addVertexData(this.vertexData, index, b.x, b.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.b,
                  color);

              index = addVertexData(this.vertexData, index, b.x, b.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.b,
                  color);
              index = addVertexData(this.vertexData, index, b.x, b.y, topz, r.r, r.b,
                  color);
            }

            if (x % 2 == 1 && displayXP
                || x % 2 == 0 && displayYM) {

              if (x % 2 == 1)
                getColor(block, blockXP, color, Face.SIDEB, x);
              else
                getColor(block, blockYM, color, Face.SIDEB, x);

              index = addVertexData(this.vertexData, index, a.x, a.y, bottomz, r.l,
                  r.t, color);
              index = addVertexData(this.vertexData, index, c.x, c.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.b,
                  color);

              index = addVertexData(this.vertexData, index, c.x, c.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.b,
                  color);
              index = addVertexData(this.vertexData, index, c.x, c.y, topz, r.r, r.b,
                  color);
            }

            if (x % 2 == 1 && displayXM
                || x % 2 == 0 && displayXP) {

              if (x % 2 == 1)
                getColor(block, blockXM, color, Face.SIDEC, x);
              else
                getColor(block, blockXP, color, Face.SIDEC, x);

              index = addVertexData(this.vertexData, index, b.x, b.y, bottomz, r.l,
                  r.t, color);
              index = addVertexData(this.vertexData, index, c.x, c.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, b.x, b.y, topz, r.l, r.b,
                  color);

              index = addVertexData(this.vertexData, index, c.x, c.y, bottomz, r.r,
                  r.t, color);
              index = addVertexData(this.vertexData, index, b.x, b.y, topz, r.l, r.b,
                  color);
              index = addVertexData(this.vertexData, index, c.x, c.y, topz, r.r, r.b,
                  color);
            }
          }

          if (displayZP) {

            getColor(block, blockZP, color, Face.TOP, x);

            getTexRect(damageOffset + block.getTopTextureIndex(), r);

            index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.t,
                color);
            index = addVertexData(this.vertexData, index, b.x, b.y, topz, r.l, r.b,
                color);
            index = addVertexData(this.vertexData, index, d.x, d.y, topz, r.r, r.b,
                color);

            index = addVertexData(this.vertexData, index, a.x, a.y, topz, r.l, r.t,
                color);
            index = addVertexData(this.vertexData, index, c.x, c.y, topz, r.r, r.t,
                color);
            index = addVertexData(this.vertexData, index, d.x, d.y, topz, r.r, r.b,
                color);

          }
        }
      }
    }
    this.trimmedVertexData = this.vertexData.subList(0, index);
  }

  private class Rect {
    public double l;
    public double r;
    public double t;
    public double b;
  }

  public void getTexRect(int i, Rect r) {
    double texW = 1.0 / TextureAtlas.HOR;
    double texH = 1.0 / TextureAtlas.VER;
    double texX = i % TextureAtlas.HOR * texW;
    double texY = 1 - (i / TextureAtlas.HOR + 1) * texH;

    r.l = texX;
    r.r = texX + texW;
    r.t = texY;
    r.b = texY + texH;
  }

  public void getColor(Block block, Block neighbor, Color color, Face face,
      int x) {
    color.r = 1;
    color.g = 1;
    color.b = 1;

    if (face == Face.TOP)
      color.alpha = .2;
    else if (face == Face.BOTTOM)
      color.alpha = .0;
    else {
      if (face == Face.SIDEA && x % 2 == 0)
        color.alpha = .15;
      else if (face == Face.SIDEA && x % 2 == 1)
        color.alpha = .12;
      else if (face == Face.SIDEC && x % 2 == 0) {
        color.alpha = .07;
      } else if (face == Face.SIDEB && x % 2 == 1) {
        color.alpha = .03;
      } else if (face == Face.SIDEB && x % 2 == 0) {
        color.alpha = .05;
      } else if (face == Face.SIDEC && x % 2 == 1)
        color.alpha = .1;
    }
    if (neighbor instanceof BlockTransparent){
      double neighborLightLevel = ((BlockTransparent)neighbor).getLightLevel();
      double lightLevel = engine.getAmbientLight() - neighborLightLevel*1.0/BlockTransparent.MAX_LIGHT_LEVEL;
      if (lightLevel < .1)
        lightLevel = .1;
      double lightAlpha = 1-lightLevel;
      double colorAlpha = (1-lightAlpha)*(1-lightAlpha)*(1-lightAlpha);
      color.r = color.r*colorAlpha + 0;
      color.g = color.g*colorAlpha + 0;
      color.b = color.b*colorAlpha + 0;
      color.alpha += (1-color.alpha)*lightAlpha;
    }
  }

  public int addVertexData(ArrayList<MutableFloat> list, int index, double x, double y,
      double z, double tx, double ty, Color c) {
    while (index+9 >= list.size())
      list.add(new MutableFloat());
    list.get(index+0).val = (float)x;
    list.get(index+1).val = (float)y;
    list.get(index+2).val = (float)z;
    list.get(index+3).val = (float)tx;
    list.get(index+4).val = (float)ty;
    list.get(index+5).val = (float)c.r;
    list.get(index+6).val = (float)c.g;
    list.get(index+7).val = (float)c.b;
    list.get(index+8).val = (float)c.alpha;
    return index+9;
  }

}
TOP

Related Classes of Hexel.rendering.GLChunk

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.