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