bumpmapcolorcontroller.java
来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 433 行 · 第 1/2 页
JAVA
433 行
package com.jme.util;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.IdentityHashMap;
import com.jme.light.DirectionalLight;
import com.jme.light.Light;
import com.jme.light.PointLight;
import com.jme.light.SpotLight;
import com.jme.math.FastMath;
import com.jme.math.Matrix3f;
import com.jme.math.Quaternion;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import com.jme.scene.SharedMesh;
import com.jme.scene.Spatial;
import com.jme.scene.TriMesh;
import com.jme.scene.state.LightState;
import com.jme.scene.state.RenderState;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.geom.BufferUtils;
public class BumpMapColorController extends Controller {
private static final long serialVersionUID = 1L;
private transient IdentityHashMap<TriMesh, BumpStore> store;
private Spatial attachedTo = null;
private boolean usePerVertex = true;
private boolean invertY = true;
private static Vector3f vert = new Vector3f();
public BumpMapColorController() {
store = new IdentityHashMap<TriMesh, BumpStore>();
}
public BumpMapColorController(Spatial attachedTo) {
this.attachedTo = attachedTo;
store = new IdentityHashMap<TriMesh, BumpStore>();
}
protected void add(TriMesh toManage) {
if (toManage == null)
return;
if (store.get(toManage) == null) {
BumpStore bs = generateBumpStore(toManage);
store.put(toManage, bs);
}
}
protected void updateMeshList() {
if (attachedTo instanceof Node) {
addChildren((Node) attachedTo);
} else if (attachedTo instanceof TriMesh) {
add((TriMesh) attachedTo);
}
}
protected void addChildren(Node parent) {
if (parent == null)
return;
for (int x = parent.getQuantity(); --x >= 0;) {
Spatial child = parent.getChild(x);
if (child instanceof Node) {
addChildren((Node) child);
} else if (child instanceof TriMesh) {
add((TriMesh) child);
}
}
}
public void update(float time) {
updateMeshList(); // XXX: would be nice to do this reactively
for (TriMesh mesh : store.keySet()) {
boolean keepGoing = false;
BumpStore bs = store.get(mesh);
if (bs.verts.length != mesh.getVertexCount()) {
BumpStore newBS = generateBumpStore(mesh);
bs.verts = newBS.verts;
}
if (!bs.oldTrans.equals(mesh.getWorldTranslation())
|| !bs.oldRot.equals(mesh.getWorldRotation())
|| !bs.oldScale.equals(mesh.getWorldScale())) {
keepGoing = true;
bs.oldTrans.set(mesh.getWorldTranslation());
bs.oldRot.set(mesh.getWorldRotation());
bs.oldScale.set(mesh.getWorldScale());
}
// Ok, grab the first light on the mesh:
LightState ls = (LightState) mesh.states[RenderState.StateType.Light.ordinal()];
if (ls == null || ls.getQuantity() < 1 || ls.get(0) == null)
continue;
Light l = ls.get(0);
if (!keepGoing) {
Light oldLight = store.get(mesh).oldLight;
if (oldLight != null && l.getType() == oldLight.getType()) {
switch (l.getType()) {
case Directional:
if (((DirectionalLight) oldLight).getDirection()
.equals(
((DirectionalLight) l)
.getDirection())) {
continue;
}
break;
case Spot:
if (((SpotLight) oldLight).getDirection().equals(
((SpotLight) l).getDirection())
&& ((SpotLight) oldLight).getLocation()
.equals(
((SpotLight) l)
.getLocation())) {
continue;
}
break;
case Point:
if (((PointLight) oldLight).getLocation().equals(
((PointLight) l).getLocation())) {
continue;
}
break;
}
} else {
Light newLight = null;
switch (l.getType()) {
case Directional:
newLight = new DirectionalLight();
((DirectionalLight) newLight).getDirection().set(
((DirectionalLight) l).getDirection());
break;
case Spot:
newLight = new SpotLight();
((SpotLight) newLight).getLocation().set(
((SpotLight) l).getLocation());
((SpotLight) newLight).getDirection().set(
((SpotLight) l).getDirection());
break;
case Point:
newLight = new PointLight();
((PointLight) newLight).getLocation().set(
((PointLight) l).getLocation());
break;
}
store.get(mesh).oldLight = newLight;
}
}
FloatBuffer verts = mesh.getVertexBuffer();
FloatBuffer colors = mesh.getColorBuffer();
if (colors == null) {
if (mesh instanceof SharedMesh)
((SharedMesh) mesh).getTarget().setSolidColor(
ColorRGBA.white.clone());
else
mesh.setSolidColor(ColorRGBA.white.clone());
colors = mesh.getColorBuffer();
}
// now we need to go through each vertex in the mesh and replace
// the color component with the light vector.
Vector3f lVect = null;
switch (l.getType()) {
case Directional:
lVect = new Vector3f(((DirectionalLight) l).getDirection());
lVect.negateLocal();
break;
case Point:
lVect = new Vector3f(((PointLight) l).getLocation());
lVect.subtractLocal(mesh.getWorldTranslation());
break;
case Spot:
lVect = new Vector3f(((SpotLight) l).getLocation());
lVect.subtractLocal(mesh.getWorldTranslation());
break;
}
if (l.getType() != Light.Type.Directional) {
mesh.worldToLocal(lVect, lVect);
} else {
lVect.divideLocal(mesh.getWorldScale());
mesh.getWorldRotation().inverse().mult(lVect, lVect);
}
vert.set(lVect);
for (int y = 0, maxY = mesh.getVertexCount(); y < maxY; y++) {
if (l.getType() != Light.Type.Directional) {
BufferUtils.populateFromBuffer(vert, verts, y);
mesh.localToWorld(vert, vert);
vert.negateLocal();
vert.addLocal(lVect);
} else {
vert.set(lVect);
}
toModelSpace(vert, bs, y);
setWorkingColor(vert);
BufferUtils.setInBuffer(workingColor, colors, y);
}
}
}
private void toModelSpace(Vector3f vertex, BumpStore bs, int y) {
vertex.normalizeLocal();
Matrix3f rot = bs.verts[y].tbnMatrix;
rot.multLocal(vertex);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?