Login  Register

Can't Get Lighting to Work in Ardor3D

Posted by hedgehog on Mar 19, 2014; 10:43am
URL: https://forum.jogamp.org/Can-t-Get-Lighting-to-Work-in-Ardor3D-tp4031971.html

Hi

Pasted below is as close as possible to my actual setup of displaying a grid of triangles. The program should run as-is and just needs to extend from ExampleBase.

Whatever I do I cannot get the scene lighting correct. If you run the code as-is then you will see a dark grey mesh.

However, if I comment out the following line in ExampleBase:

        //_root.setRenderState(_lightState);

then you will see the red mesh, as below:



The colour buffer is filled correctly. I assign a MaterialState to the grid mesh. So, why does the object not get lit as expected?

Thanks.

*****

package viewer3d.sample;

import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;

import com.ardor3d.bounding.BoundingBox;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.Vector3;
import com.ardor3d.renderer.state.MaterialState;
import com.ardor3d.renderer.state.MaterialState.MaterialFace;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.scenegraph.MeshData;
import com.ardor3d.util.ReadOnlyTimer;
import com.ardor3d.util.geom.BufferUtils;
import com.ardor3d.example.ExampleBase;

public class GridExample extends ExampleBase {

  /** Keep a reference to the box to be able to rotate it each frame. */
  private Mesh grid;

  public static void main(final String[] args) {
      start(GridExample.class);
  }

  @Override
  protected void updateExample(final ReadOnlyTimer timer) {
  }

  @Override
  protected void initExample() {
      _canvas.setTitle("Grid Example");

      grid = setupGridMesh(new ColorRGBA(1,0,0,1));
      grid.setModelBound(new BoundingBox());
      grid.setTranslation(new Vector3(0, 0, -5));
      _root.attachChild(grid);
     
      // Add a material to the box, to show both vertex color and lighting/shading.
  final MaterialState materialState = new MaterialState();
  materialState.setEnabled(true);
  materialState.setAmbient(MaterialFace.FrontAndBack, new ColorRGBA(0.1f,0.1f,0.1f,1.0f));
  materialState.setDiffuse(MaterialFace.FrontAndBack, new ColorRGBA(0.9f,0.9f,0.9f,1.0f));
  grid.setRenderState(materialState);          
  }  
 
  private Mesh setupGridMesh(ColorRGBA defaultColour)
  {  
          Vector3 origin = new Vector3(0,0,0);
  double iSpacing = 1.0;
  double jSpacing = 1.0;
  int iSize = 4;
  int jSize = 3;
  Grid3D grid = new Grid3D(origin,iSpacing,jSpacing,iSize,jSize);
  grid.addPoint(0.0,0,0); grid.addPoint(0.0,1,0); grid.addPoint(0.0,2,0); grid.addPoint(0.0,3,0);
  grid.addPoint(1.0,0,1); grid.addPoint(1.0,1,1); grid.addPoint(1.0,2,1); grid.addPoint(1.0,3,1);
  grid.addPoint(4.0,0,2); grid.addPoint(4.0,1,2); grid.addPoint(4.0,2,2); grid.addPoint(4.0,3,2);
   
  Mesh mesh = buildSolidMesh(grid, defaultColour);
  return mesh;
  }
 
  private Mesh buildSolidMesh(Grid3D grid, ColorRGBA defaultColour)
  {
          Mesh mesh = new Mesh();
          MeshData meshData = mesh.getMeshData();
         
  // vertex/colour buffers
  Vector3[]  gridPoints = grid.gridPoints();
  int iSize = grid.miSize;
  int jSize = grid.mjSize;
  int numberPoints = iSize * jSize;
         
      // colours
      float red = defaultColour.getRed(); float green = defaultColour.getGreen(); float blue = defaultColour.getBlue(); float alpha = defaultColour.getAlpha();
     
      meshData.setVertexBuffer(BufferUtils.createVector3Buffer(numberPoints));
      meshData.setColorBuffer(BufferUtils.createColorBuffer(numberPoints));
  for (int index=0; index<numberPoints; index++)
  {
  // vertex
  Vector3 p = gridPoints[index];    
                        meshData.getVertexBuffer().put(p.getXf()).put(p.getYf()).put(p.getZf());
                        meshData.getColorBuffer().put(red).put(green).put(blue).put(alpha); // note *4 indexing into buffer
  }
  meshData.getColorBuffer().rewind();
 
  // vertex normals
  meshData.setNormalBuffer(BufferUtils.createVector3Buffer(numberPoints));    

  // texture
    //... not supported at present
 
  // triangle indices
    ArrayList<TripleInteger> triangleIndices = new ArrayList<>();
  ArrayList<GridTriangle> triangles = grid.triangles();
  int numberTriangles = triangles.size();
  for (int i=0; i<numberTriangles; i++)
  {
  // indices
  GridTriangle triangle = triangles.get(i);
  GridPoint v0gp = triangle.mv0;
  GridPoint v1gp = triangle.mv1;
  GridPoint v2gp = triangle.mv2;
  int v0Index = grid.hashKey(v0gp);
  int v1Index = grid.hashKey(v1gp);
  int v2Index = grid.hashKey(v2gp);
  TripleInteger triple = new TripleInteger(v0Index,v1Index,v2Index);
  triangleIndices.add(triple);
 
  // normals
  Vector3 v0 = gridPoints[v0Index];
  Vector3 v1 = gridPoints[v1Index];
  Vector3 v2 = gridPoints[v2Index];
                        final Vector3 v01 = v1.subtract(v0, null);
                        final Vector3 v02 = v2.subtract(v0, null);
                        final Vector3 cross = v01.cross(v02, null);
                        cross.normalizeLocal();
                final float nx = cross.getXf();
                final float ny = cross.getYf();
                final float nz = cross.getZf();
                meshData.getNormalBuffer().put(v0Index+0,nx).put(v0Index+1,ny).put(v0Index+2,nz);
                meshData.getNormalBuffer().put(v1Index+0,nx).put(v1Index+1,ny).put(v1Index+2,nz);
                meshData.getNormalBuffer().put(v2Index+0,nx).put(v2Index+1,ny).put(v2Index+2,nz);
  }    
      int[] indices = new int[3*triangleIndices.size()];
      for (int i=0; i<triangleIndices.size(); i++)
      {
      TripleInteger triIndices = triangleIndices.get(i);
      indices[3*i+0] = triIndices.mp;
      indices[3*i+1] = triIndices.mq;
      indices[3*i+2] = triIndices.mr;
      }
      final IntBuffer ibuf = BufferUtils.createIntBuffer(indices.length);
      ibuf.put(indices);
      ibuf.rewind();
      meshData.setIndexBuffer(ibuf);
     
      return mesh;
        }
 
} // GridExample

class Grid3D
{
        /** Origin. */
        protected Vector3 mOrigin;
        /** Spacing in i-direction. */
        protected double miSpacing;
        /** Spacing in j-direction. */
        protected double mjSpacing;
        /** Number of points in i-direction. */
        protected int miSize;
        /** Number of points in j-direction. */
        protected int mjSize;
        /** Hash-map of z-values. */
        protected HashMap<GridPoint, Double> mzValues;
       
        public Grid3D(final Vector3 origin, final double iSpacing,
                        final double jSpacing, final int iSize, final int jSize) {
                mOrigin = origin;
                miSpacing = iSpacing;
                mjSpacing = jSpacing;
                miSize = iSize;
                mjSize = jSize;
                mzValues = new HashMap<>();
        }
        public void addPoint(final double zValue, final int i, final int j) {
                        mzValues.put(new GridPoint(i,j), zValue);
        }
        public Vector3[] gridPoints() {
                int numberPoints = miSize*mjSize;
                Vector3[] points = new Vector3[numberPoints];
               
                for (int i = 0; i < miSize; i++) {
                        for (int j = 0; j < mjSize; j++) {
                                int index = hashKey(new GridPoint(i,j));
                                double xValue = x(i,j);
                                double yValue = y(i,j);
                                double zValue;
                                zValue = z(i,j);
                                Vector3 point = new Vector3(xValue,yValue,zValue);
                                points[index] = point;
                        }
                }
               
                return points;
        }
        public int hashKey(GridPoint gp) {
                return gp.mGridj + gp.mGridi * mjSize;
        }
        public double x(int i, int j) {
                return i * miSpacing;
        }
        public double y(int i, int j) {
                return j * mjSpacing;
        }
        public double z(int i, int j) {
                return mzValues.get(new GridPoint(i,j));
        }
        public ArrayList<GridTriangle> triangles() {

                ArrayList<GridTriangle> triangles = new ArrayList<GridTriangle>();

                for (int i = 0; i < miSize; i++) {
                        for (int j = 0; j < mjSize; j++) {
                                ArrayList<GridTriangle> tris = triangles(i, j);
                                for (int t = 0; t < tris.size(); t++) {
                                        GridTriangle tri = tris.get(t);
                                        triangles.add(tri);
                                }
                        }
                }

                return triangles;
        }
        public ArrayList<GridTriangle> triangles(int loweri, int lowerj) {
                // neighbouring quadrilateral points [a(loweri,lowerj), b, c, d in
                // anti-clockwise rotation from a]
                int ai = loweri, aj = lowerj, bi = loweri + 1, bj = lowerj, ci = loweri + 1, cj = lowerj + 1, di = loweri, dj = lowerj + 1;
                GridPoint pa = new GridPoint(ai, aj);
                GridPoint pb = new GridPoint(bi, bj);
                GridPoint pc = new GridPoint(ci, cj);
                GridPoint pd = new GridPoint(di, dj);
                // points and not-a-points
                boolean aIsPoint = false, bIsPoint = false, cIsPoint = false, dIsPoint = false;
                if (isGridPoint(ai, aj)) {
                        aIsPoint = true;
                }
                if (isGridPoint(bi, bj)) {
                        bIsPoint = true;
                }
                if (isGridPoint(ci, cj)) {
                        cIsPoint = true;
                }
                if (isGridPoint(di, dj)) {
                        dIsPoint = true;
                }
                // triangles
                ArrayList<GridTriangle> tris = new ArrayList<>();
                if (aIsPoint && bIsPoint && cIsPoint && dIsPoint) // full quadrilateral
                {
                        GridTriangle t1 = new GridTriangle(pa, pb, pc);
                        GridTriangle t2 = new GridTriangle(pa, pc, pd);
                        tris.add(t1);
                        tris.add(t2);
                        return tris;
                }
                if (aIsPoint && bIsPoint && cIsPoint) {
                        GridTriangle t = new GridTriangle(pa, pb, pc);
                        tris.add(t);
                }
                if (aIsPoint && cIsPoint && dIsPoint) {
                        GridTriangle t = new GridTriangle(pa, pc, pd);
                        tris.add(t);
                        if (tris.size() == 2) // prevent more than 2 triangles being added
                                return tris;
                }
                if (aIsPoint && bIsPoint && dIsPoint) {
                        GridTriangle t = new GridTriangle(pa, pb, pd);
                        tris.add(t);
                        if (tris.size() == 2) // prevent more than 2 triangles being added
                                return tris;
                }
                if (bIsPoint && cIsPoint && dIsPoint) {
                        GridTriangle t = new GridTriangle(pb, pc, pd);
                        tris.add(t);
                }
                return tris;
        }
        public boolean isGridPoint(int i, int j) {
                if (i < 0 || i > miSize - 1 || j < 0 || j > mjSize - 1) {
                        return false;
                }
                return true;
        }
       
} // class Grid3D

class GridPoint
{
        /** Grid-point i index. */
        protected int mGridi;
        /** Grid-point j index. */
        protected int mGridj;
        public GridPoint(final int i, final int j) {
                mGridi = i;
                mGridj = j;
        }
        @Override
        public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + mGridi;
                result = prime * result + mGridj;
                return result;
        }
        @Override
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                GridPoint other = (GridPoint) obj;
                if (mGridi != other.mGridi)
                        return false;
                if (mGridj != other.mGridj)
                        return false;
                return true;
        }
       
} // class GridPoint

class GridTriangle {
        /** Vertex 0. */
        protected GridPoint mv0;
        /** Vertex 1. */
        protected GridPoint mv1;
        /** Vertex 2. */
        protected GridPoint mv2;
        public GridTriangle(GridPoint v0,GridPoint v1,GridPoint v2) {
                mv0 = v0; mv1 = v1; mv2 = v2;
        }
} // class GridTriangle

class TripleInteger {
    /** Triple value p. */
    protected int mp;
    /** Triple value q. */
    protected int mq;
    /** Triple value r. */
    protected int mr;
    public TripleInteger(final int p, final int q, final int r)
    {
        mp = p; mq = q; mr = r;
    }
       
} // class TripleInteger