/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is based on code from idx3dIII * Copyright 1999, 2000 Peter Walser * http://www.idx3d.ch/idx3d/idx3d.html * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JAME is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.core.media.g3d; public final class Lightmap { int ambient; java.util.Vector<Light> lights = new java.util.Vector<Light>(); float[] sphere = new float[65536]; int[][] diffuse = new int[2][65536]; int[][] specular = new int[2][65536]; private boolean dirty = false; public Lightmap(final int ambient) { this.ambient = ambient; buildSphereMap(); } public void removeLight(final Light light) { lights.removeElementAt(lights.indexOf(light)); dirty = false; } public void addLight(final Light light) { lights.addElement(light); dirty = false; } public void setAmbient(final int ambient) { this.ambient = ambient; dirty = false; } public void rebuildLightmap() { if (!dirty) { dirty = true; rebuild(); } } public void buildLightmap() { dirty = true; rebuild(); } private void buildSphereMap() { float fnx; float fny; float fnz; for (int ny = -128; ny < 128; ny++) { fny = ny / 128f; for (int nx = -128; nx < 128; nx++) { fnx = nx / 128f; fnz = (float) (1f - java.lang.Math.sqrt((fnx * fnx) + (fny * fny))); sphere[nx + 128 + ((ny + 128) << 8)] = (fnz > 0f) ? fnz : 0f; } } } private void rebuild() { Light light; int phongfact; float spread; float sheen; float fnx; float fny; int lutid; int diffuse; int specular; int cos; int dr; int dg; int db; int sr; int sg; int sb; for (int ny = -128; ny < 128; ny++) { fny = ny / 128f; for (int nx = -128; nx < 128; nx++) { fnx = nx / 128f; lutid = nx + 128 + ((ny + 128) << 8); dr = Color.getRed(ambient); dg = Color.getGreen(ambient); db = Color.getBlue(ambient); sr = sg = sb = 0; for (int i = 0; i < lights.size(); i++) { light = lights.elementAt(i); diffuse = light.diffuse; specular = light.specular; cos = (int) (255f * Vector.cos(light.v, new Vector(fnx, fny, +sphere[lutid]))); cos = (cos > 0) ? cos : 0; dr += ((Color.getRed(diffuse) * cos) >> 8); dg += ((Color.getGreen(diffuse) * cos) >> 8); db += ((Color.getBlue(diffuse) * cos) >> 8); sheen = light.highlightSheen / 255f; spread = light.highlightSpread / 4096f; spread = (spread < 0.01f) ? 0.01f : spread; phongfact = (int) (255f * sheen * (float) java.lang.Math.pow(cos / 255f, 1f / spread)); sr += ((Color.getRed(specular) * phongfact) >> 8); sg += ((Color.getGreen(specular) * phongfact) >> 8); sb += ((Color.getBlue(specular) * phongfact) >> 8); } this.diffuse[0][lutid] = Color.getCropColor(dr, dg, db); this.specular[0][lutid] = Color.getCropColor(sr, sg, sb); } } for (int ny = -128; ny < 128; ny++) { fny = ny / 128f; for (int nx = -128; nx < 128; nx++) { fnx = nx / 128f; lutid = nx + 128 + ((ny + 128) << 8); dr = Color.getRed(ambient); dg = Color.getGreen(ambient); db = Color.getBlue(ambient); sr = sg = sb = 0; for (int i = 0; i < lights.size(); i++) { light = lights.elementAt(i); diffuse = light.diffuse; specular = light.specular; cos = (int) (255f * Vector.cos(light.v, new Vector(fnx, fny, -sphere[lutid]))); cos = (cos > 0) ? cos : 0; dr += ((Color.getRed(diffuse) * cos) >> 8); dg += ((Color.getGreen(diffuse) * cos) >> 8); db += ((Color.getBlue(diffuse) * cos) >> 8); sheen = light.highlightSheen / 255f; spread = light.highlightSpread / 4096f; spread = (spread < 0.01f) ? 0.01f : spread; phongfact = (int) (255f * sheen * (float) java.lang.Math.pow(cos / 255f, 1f / spread)); sr += ((Color.getRed(specular) * phongfact) >> 8); sg += ((Color.getGreen(specular) * phongfact) >> 8); sb += ((Color.getBlue(specular) * phongfact) >> 8); } this.diffuse[1][lutid] = Color.getCropColor(dr, dg, db); this.specular[1][lutid] = Color.getCropColor(sr, sg, sb); } } } }