⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyframecontroller.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                dataCopy.setColorBuffer(dcColors);
            }
            
            dcColors.put(mmColors);
            dcColors.flip();
        }
        if (morphMesh.getVertexBuffer() != null) {
            FloatBuffer dcVerts = dataCopy.getVertexBuffer();
            if (dcVerts != null)
                dcVerts.clear();
            FloatBuffer mmVerts = morphMesh.getVertexBuffer();
            mmVerts.clear();
            if (dcVerts == null || dcVerts.capacity() != mmVerts.capacity()) {
                dcVerts = BufferUtils.createFloatBuffer(mmVerts.capacity());
                dcVerts.clear();
                dataCopy.setVertexBuffer(dcVerts);
            }
            
            dcVerts.put(mmVerts);
            dcVerts.flip();
        }
        if (morphMesh.getNormalBuffer() != null) {
            FloatBuffer dcNorms = dataCopy.getNormalBuffer();
            if (dcNorms != null)
                dcNorms.clear();
            FloatBuffer mmNorms = morphMesh.getNormalBuffer();
            mmNorms.clear();
            if (dcNorms == null || dcNorms.capacity() != mmNorms.capacity()) {
                dcNorms = BufferUtils.createFloatBuffer(mmNorms.capacity());
                dcNorms.clear();
                dataCopy.setNormalBuffer(dcNorms);
            }
            
            dcNorms.put(mmNorms);
            dcNorms.flip();
        }
        if (morphMesh.getIndexBuffer() != null) {
            IntBuffer dcInds = dataCopy.getIndexBuffer();
            if (dcInds != null)
                dcInds.clear();
            IntBuffer mmInds = morphMesh.getIndexBuffer();
            mmInds.clear();
            if (dcInds == null || dcInds.capacity() != mmInds.capacity()) {
                dcInds = BufferUtils.createIntBuffer(mmInds.capacity());
                dcInds.clear();
                dataCopy.setIndexBuffer(dcInds);
            }
            
            dcInds.put(mmInds);
            dcInds.flip();
        }
        if (morphMesh.getTextureCoords(0) != null) {
            FloatBuffer dcTexs = dataCopy.getTextureCoords(0).coords;
            if (dcTexs != null)
                dcTexs.clear();
            FloatBuffer mmTexs = morphMesh.getTextureCoords(0).coords;
            mmTexs.clear();
            if (dcTexs == null || dcTexs.capacity() != mmTexs.capacity()) {
                dcTexs = BufferUtils.createFloatBuffer(mmTexs.capacity());
                dcTexs.clear();
                dataCopy.setTextureCoords(new TexCoords(dcTexs), 0);
            }
            
            dcTexs.put(mmTexs);
            dcTexs.flip();
        }
    }

    /**
     * As defined in Controller
     * 
     * @param time
     *            as defined in Controller
     */
    public void update(float time) {
        if (easyQuit()) return;
        if (movingForward)
            curTime += time * this.getSpeed();
        else
            curTime -= time * this.getSpeed();
        
        findFrame();
        before =  keyframes.get(curFrame);
        // Change this bit so the next frame we're heading towards isn't always going
        // to be one frame ahead since now we coule be animating from the last to first
        // frames.
        //after =  keyframes.get(curFrame + 1));
        after =  keyframes.get(nextFrame);
        
        float delta = (curTime - before.time) / (after.time - before.time);
        
        // If we doing that wrapping bit then delta should be caculated based 
        // on the time before the start of the animation we are. 
        if (nextFrame < curFrame) {
        	delta = blendTime - (getMinTime()-curTime);
        }
        
        TriMesh oldShape = before.newShape;
        TriMesh newShape = after.newShape;
        
        FloatBuffer verts = morphMesh.getVertexBuffer();
        FloatBuffer norms = morphMesh.getNormalBuffer();
        FloatBuffer texts = morphMesh.getTextureCoords(0) != null ? morphMesh.getTextureCoords(0).coords : null;
        FloatBuffer colors = morphMesh.getColorBuffer();

        FloatBuffer oldverts = oldShape.getVertexBuffer();
        FloatBuffer oldnorms = oldShape.getNormalBuffer();
        FloatBuffer oldtexts = oldShape.getTextureCoords(0) != null ? oldShape.getTextureCoords(0).coords : null;
        FloatBuffer oldcolors = oldShape.getColorBuffer();

        FloatBuffer newverts = newShape.getVertexBuffer();
        FloatBuffer newnorms = newShape.getNormalBuffer();
        FloatBuffer newtexts = newShape.getTextureCoords(0) != null ? newShape.getTextureCoords(0).coords : null;
        FloatBuffer newcolors = newShape.getColorBuffer();
        int vertQuantity = verts.capacity() / 3;
        if (verts == null || oldverts == null || newverts == null) return;
        verts.rewind(); oldverts.rewind(); newverts.rewind();

        if (norms != null) norms.rewind(); // reset to start
        if (oldnorms != null) oldnorms.rewind(); // reset to start
        if (newnorms != null) newnorms.rewind(); // reset to start

        if (texts != null) texts.rewind(); // reset to start
        if (oldtexts != null) oldtexts.rewind(); // reset to start
        if (newtexts != null) newtexts.rewind(); // reset to start

        if (colors != null) colors.rewind(); // reset to start
        if (oldcolors != null) oldcolors.rewind(); // reset to start
        if (newcolors != null) newcolors.rewind(); // reset to start
                
        for (int i = 0; i < vertQuantity; i++) {
            for (int x = 0; x < 3; x++) // x, y, and z
                verts.put(i*3+x, (1f-delta)*oldverts.get(i*3 + x) + delta*newverts.get(i*3 + x));

            if (norms != null && oldnorms != null && newnorms != null)
                for (int x = 0; x < 3; x++) // x, y, and z
                    norms.put(i*3+x, (1f-delta)*oldnorms.get(i*3 + x) + delta*newnorms.get(i*3 + x));

            if (texts != null && oldtexts != null && newtexts != null)
                for (int x = 0; x < 2; x++) // x and y
                    texts.put(i*2+x,(1f-delta)*oldtexts.get(i*2 + x) + delta*newtexts.get(i*2 + x));

            if (colors != null && oldcolors != null && newcolors != null)
                for (int x = 0; x < 4; x++) // r, g, b, a
                    colors.put(i*4+x,(1f-delta)*oldcolors.get(i*4 + x) + delta*newcolors.get(i*4 + x));
        }

        if (updatePerFrame) morphMesh.updateModelBound();
    }

    /**
     * If both min and max time are equal and the model is already updated, then
     * it's an easy quit, or if it's on CLAMP and I've exceeded my time it's
     * also an easy quit.
     * 
     * @return true if update doesn't need to be called, false otherwise
     */
    private boolean easyQuit() {
        if (getMaxTime() == getMinTime() && curTime != getMinTime())
            return true;
        else if (getRepeatType() == RT_CLAMP
                && (curTime > getMaxTime() || curTime < getMinTime()))
            return true;
        else if (keyframes.size() < 2) return true;
        return false;
    }

    /**
     * If true, the model's bounding volume will be updated every frame. If
     * false, it will not.
     * 
     * @param update
     *            The new update model volume per frame value.
     */
    public void setModelUpdate(boolean update) {
        updatePerFrame = update;
    }

    /**
     * Returns true if the model's bounding volume is being updated every frame.
     * 
     * @return True if bounding volume is updating.
     */
    public boolean getModelUpdate() {
        return updatePerFrame;
    }

    private float blendTime = 0;
    /**
     * If repeat type <CODE>RT_WRAP</CODE> is set, after reaching the last frame of the currently set
     * animation maxTime (see <CODE>Controller.setMaxTime</CODE>), there will be an additional <CODE>blendTime</CODE>
     * seconds long phase inserted, morphing from the last frame to the first.
     * @param blendTime The blend time to set
     */
    public void setBlendTime(float blendTime){ this.blendTime = blendTime; }

    /**
     * Gets the currently set blending time for smooth animation transitions
     * @return The current blend time
     * @see #setBlendTime(float blendTime)
     */
    public float getBlendTime(){ return blendTime; }
    
    /**
     * This is used by update(float). It calculates PointInTime
     * <code>before</code> and <code>after</code> as well as makes
     * adjustments on what to do when <code>curTime</code> is beyond the
     * MinTime and MaxTime bounds
     */
    private void findFrame() {
    	// If we're in our special wrapping case then just ignore changing
    	// frames. Once we get back into the actual series we'll revert back
    	// to the normal process
    	if ((curTime < getMinTime()) && (nextFrame < curFrame)) {
    		return;
    	}
    	
    	// Update the rest to maintain our new nextFrame marker as one infront
    	// of the curFrame in all cases. The wrap case is where the real work 
    	// is done.
        if (curTime > this.getMaxTime()) {
            if (isSmooth) {
                swapKeyframeSets();
                isSmooth = false;
                curTime = tempNewBeginTime;
                curFrame = 0;
                nextFrame = 1;
                setNewAnimationTimes(tempNewBeginTime, tempNewEndTime);
                return;
            }
            if (this.getRepeatType() == Controller.RT_WRAP) {
            	float delta = blendTime;
                curTime = this.getMinTime() - delta;
                curFrame = Math.min(curFrame + 1, keyframes.size() - 1);
                
                for (nextFrame = 0; nextFrame < keyframes.size() - 1; nextFrame++) {
                    if (getMinTime() <=  keyframes.get(nextFrame).time)
                            break;
                }
                return;
            } else if (this.getRepeatType() == Controller.RT_CLAMP) {
                return;
            } else { // Then assume it's RT_CYCLE
                movingForward = false;
                curTime = this.getMaxTime();
            }
        } else if (curTime < this.getMinTime()) {
            if (this.getRepeatType() == Controller.RT_WRAP) {
                curTime = this.getMaxTime();
                curFrame = 0;
            } else if (this.getRepeatType() == Controller.RT_CLAMP) {
                return;
            } else { // Then assume it's RT_CYCLE
                movingForward = true;
                curTime = this.getMinTime();
            }
        }

    	nextFrame = curFrame+1;
    	
        if (curTime >  keyframes.get(curFrame).time) {
            if (curTime <  keyframes.get(curFrame + 1).time) {
            	nextFrame = curFrame+1;
                return;
            }
            
            for (; curFrame < keyframes.size() - 1; curFrame++) {
                if (curTime <=  keyframes.get(curFrame + 1).time) {
                		nextFrame = curFrame+1;
                        return;
                }
            }
            
            // This -should- be unreachable because of the above
            curTime = this.getMinTime();
            curFrame = 0;
            nextFrame = curFrame+1;
            return;            
        } 
            
        for (; curFrame >= 0; curFrame--) {
            if (curTime >=  keyframes.get(curFrame).time) {
            	nextFrame = curFrame+1;
            	return; 
            }
        }
        
        // This should be unreachable because curTime>=0 and
        // keyframes[0].time=0;
        curFrame = 0;
        nextFrame = curFrame+1;
    }

    /**
     * This class defines a point in time that states <code>morphShape</code>
     * should look like <code>newShape</code> at <code>time</code> seconds
     */
    public static class PointInTime implements Serializable, Savable {

        private static final long serialVersionUID = 1L;

        public TriMesh newShape;

        public float time;

        public PointInTime() {}
        
        public PointInTime(float time, TriMesh shape) {
            this.time = time;
            this.newShape = shape;
        }

		public void read(JMEImporter im) throws IOException {
			InputCapsule cap = im.getCapsule(this);
	    	time = cap.readFloat("time", 0);
	    	newShape = (TriMesh)cap.readSavable("newShape", null);
		}

		public void write(JMEExporter ex) throws IOException {
			OutputCapsule cap = ex.getCapsule(this);
	    	cap.write(time, "time", 0);
	    	cap.write(newShape, "newShape", null);
		}
        
        public Class getClassTag() {
            return this.getClass();
        }
    }

    @SuppressWarnings("unchecked")
	private void readObject(java.io.ObjectInputStream in) throws IOException,
            ClassNotFoundException {
        in.defaultReadObject();
        keyframes = (ArrayList) in.readObject();
        movingForward = true;
    }

    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        if (isSmooth)
            out.writeObject(prevKeyframes);
        else
            out.writeObject(keyframes);
    }

    public TriMesh getMorphMesh() {
        return morphMesh;
    }
    
    @Override
    public void write(JMEExporter ex) throws IOException {
    	super.write(ex);
    	OutputCapsule cap = ex.getCapsule(this);
    	cap.write(updatePerFrame, "updatePerFrame", true);
    	cap.write(morphMesh, "morphMesh", null);
    	cap.writeSavableArrayList(keyframes, "keyframes", new ArrayList<PointInTime>());
    }
    
	@Override
    @SuppressWarnings("unchecked")
    public void read(JMEImporter im) throws IOException {
    	super.read(im);
    	InputCapsule cap = im.getCapsule(this);
    	updatePerFrame = cap.readBoolean("updatePerFrame", true);
    	morphMesh = (TriMesh) cap.readSavable("morphMesh", null);
    	keyframes = cap.readSavableArrayList("keyframes", new ArrayList<PointInTime>());
    	movingForward = true;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -