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 + -
显示快捷键?