package glmodel; import java.nio.*; import org.lwjgl.opengl.*; /** * Wraps properties for a material. * * To use: * create a new material, * set the material properties (setDiffuse(), setAmbient(), setSpecular(), setShininess()), * call material.apply() in your render function to set the OpenGL current material properties. */ public class GLMaterial { // A sampling of color values public static final float colorClear[] = { 0f, 0f, 0f, 0f}; // alpha is 0 public static final float colorNone[] = { 0f, 0f, 0f, 1f}; // no color = black public static final float colorRed[] = { 1f, 0f, 0f, 1f}; public static final float colorGreen[] = { 0f, 1f, 0f, 1f}; public static final float colorBlue[] = { 0f, 0f, 1f, 1f}; public static final float colorYellow[] = { 1f, 1f, 0f, 1f}; public static final float colorCyan[] = { 0f, 1f, 1f, 1f}; public static final float colorMagenta[] = { 1f, 0f, 1f, 1f}; public static final float colorGrayLight[] = { .8f, .8f, .8f, 1f}; public static final float colorGrayMedium[] = { .5f, .5f, .5f, 1f}; public static final float colorGrayDark[] = { .2f, .2f, .2f, 1f}; public static final float colorWhite[] = { 1f, 1f, 1f, 1f}; public static final float colorBlack[] = { 0f, 0f, 0f, 1f}; public static final float colorBeige[] = { .7f, .7f, .4f, 1f}; public static final float colorDefaultDiffuse[] = { .8f, .8f, .8f, 1f}; // OpenGL default diffuse color public static final float colorDefaultAmbient[] = { .2f, .2f, .2f, 1f}; // OpenGL default ambient color public static final float minShine = 0.0f; public static final float maxShine = 127.0f; // Default material values private static FloatBuffer defaultDiffuse = allocFloats(colorDefaultDiffuse); private static FloatBuffer defaultAmbient = allocFloats(colorDefaultAmbient); private static FloatBuffer defaultSpecular = allocFloats(colorNone); private static FloatBuffer defaultEmission = allocFloats(colorNone); private static FloatBuffer defaultShine = allocFloats(new float[] {minShine,0,0,0}); // LWJGL requires four values, so include three extra zeroes // The color values for this material public FloatBuffer diffuse; // color of the lit surface public FloatBuffer ambient; // color of the shadowed surface public FloatBuffer specular; // reflection color (typically this is a shade of gray) public FloatBuffer emission; // glow color public FloatBuffer shininess; // size of the reflection highlight // hold name and texture values for this material public String mtlname = "noname"; // name of this material in the .mtl and .obj files public String textureFile = null; // texture filename (null if no texture) public int textureHandle; // opengl handle to the texture (0 if no texture) public GLMaterial() { setDefaults(); } public GLMaterial(float[] color) { setDefaults(); setColor(color); } /** * Set the material to OpenGL's default values (gray, with no reflection and no glow) */ public void setDefaults() { setDiffuse(colorDefaultDiffuse); setAmbient(colorDefaultAmbient); setSpecular(colorNone); setEmission(colorNone); setShininess(minShine); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Functions to set the material properties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Set the diffuse material color. This is the color of the material * where it is directly lit. */ public void setDiffuse(float[] color) { diffuse = allocFloats(color); } /** * Set the ambient material color. This is the color of the material * where it is lit by indirect light (light scattered off the environment). * Ie. the shadowed side of an object. */ public void setAmbient(float[] color) { ambient = allocFloats(color); } /** * Set the specular material color. This controls how much light * is reflected off a glossy surface. This color value describes * the brightness of the reflection and is typically a shade of gray. * Pure black means that no light is reflected (ie. a very rough matte * surface). Pure white means that the surface is highly reflective, * * see also: setShininess() */ public void setSpecular(float[] color) { specular = allocFloats(color); } /** * Set the emission material color. This controls the "glow" of the material, * and can be used to make a material that seems to be lit from inside. */ public void setEmission(float[] color) { emission = allocFloats(color); } /** * Set size of the reflection highlight. Must also set the specular color for * shininess to have any effect: * setSpecular(GLMaterial.colorWhite); * * @param howShiny How sharp reflection is: 0 - 127 (127=very sharp pinpoint) */ public void setShininess(float howShiny) { if (howShiny >= minShine && howShiny <= maxShine) { float[] tmp = {howShiny,0,0,0}; shininess = allocFloats(tmp); } } /** * Call glMaterial() to activate these material properties in the OpenGL environment. * These properties will stay in effect until you change them or disable lighting. */ public void apply() { // GL_FRONT: affect only front facing triangles GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, diffuse); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, ambient); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, specular); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_EMISSION, emission); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SHININESS, shininess); } /** * Reset all material settings to the default values. */ public static void clear() { GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, defaultDiffuse); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, defaultAmbient); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, defaultSpecular); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_EMISSION, defaultEmission); GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SHININESS, defaultShine); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The following functions provide a simpler way to use materials * that hides some of the complexity of the OpenGL functions. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Sets the material color to approximate a "real" surface color. * * Use the same color for diffuse and ambient. To create a * shadowed effect you should lower the ambient value for the * light sources and lower the overall ambient light. */ public void setColor(float[] color) { setDiffuse(color); // surface directly lit setAmbient(color); // surface in shadow } /** * Set the reflection properties. Typically the reflection (specular color) * describes the brightness of the reflection, and is a shade of gray. * This function takes two params that describe the intensity * of the reflection, and the size of the highlight. * * intensity - a float from 0-1 (0=no reflectivity, 1=maximum reflectivity) * highlight - a float from 0-1 (0=soft highlight, 1=sharpest highlight) * * example: setReflection(1,1) creates a bright, sharp reflection * setReflection(.5f,.5f) creates a softer, wider reflection */ public void setReflection(float intensity, float highlight) { float[] color = {intensity,intensity,intensity,1}; // create a shade of gray setSpecular(color); setShininess((int)(highlight*127f)); // convert 0-1 to 0-127 } /** * Make material appear to emit light */ public void setGlowColor(float[] color) { emission = allocFloats(color); } /** * alpha value is set in the diffuse material color. Other material * colors (ambient, specular) are not affected by alpha value. * @param alphaVal 0 - 1 */ public void setAlpha(float alphaVal) { diffuse.put(3, alphaVal); } /** * alpha value is stored in the diffuse material color alpha. Other material * colors (ambient, specular) are not affected by alpha value. * @return alphaVal 0 - 1 */ public float getAlpha() { return diffuse.get(3); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * functions to add a texture to this material * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Store a texture filename with the material. */ public void setTextureFile(String s) { textureFile = s; } /** * Assign a texture handle to this material. * @param txtrHandle */ public void setTexture(int txtrHandle) { textureHandle = txtrHandle; } public String getTextureFile() { return textureFile; } public int getTexture() { return textureHandle; } /** * set the material name. This is the name assigned to this texture in the .mtl file. * It is NOT a filename. * @param s */ public void setName(String s) { mtlname = s; } public String getName() { return mtlname; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Native IO buffer functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ public static final int SIZE_FLOAT = 4; // four bytes in a float public static FloatBuffer allocFloats(int howmany) { return ByteBuffer.allocateDirect(howmany * SIZE_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); } public static FloatBuffer allocFloats(float[] floatarray) { FloatBuffer fb = ByteBuffer.allocateDirect(floatarray.length * SIZE_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); fb.put(floatarray).flip(); return fb; } }