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

📄 abstractcamera.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
     * @param bound the bound to check for culling
     * @return true if the bound should be culled, false otherwise.
     */
    public Camera.FrustumIntersect contains( BoundingVolume bound ) {
        if ( bound == null ) {
            return FrustumIntersect.Inside;
        }

        int mask;
        FrustumIntersect rVal = FrustumIntersect.Inside;

        for ( int planeCounter = FRUSTUM_PLANES; planeCounter >= 0; planeCounter-- ) {
            if ( planeCounter == bound.getCheckPlane() ) {
                continue; // we have already checked this plane at first iteration
            }
            int planeId = ( planeCounter == FRUSTUM_PLANES ) ? bound.getCheckPlane() : planeCounter;

            mask = 1 << ( planeId );
            if ( ( planeState & mask ) == 0 ) {
                Side side = bound.whichSide( worldPlane[planeId] );

                if (side == Side.NEGATIVE) {
                    //object is outside of frustum
                    bound.setCheckPlane( planeId );
                    return FrustumIntersect.Outside;
                } else if (side == Side.POSITIVE) {
                    //object is visible on *this* plane, so mark this plane
                    //so that we don't check it for sub nodes.
                    planeState |= mask;
                } else {
                    rVal = FrustumIntersect.Intersects;
                }
            }
        }

        return rVal;
    }

    /**
     * <code>onFrustumChange</code> updates the frustum to reflect any changes
     * made to the planes. The new frustum values are kept in a temporary
     * location for use when calculating the new frame. It should be noted that
     * the abstract implementation of this class only updates the data, and does
     * not make any rendering calls. As such, any impelmenting subclass should
     * insure to override this method call it with super and then call the
     * rendering specific code.
     */
    public void onFrustumChange() {
        if ( !isParallelProjection() ) {
            float nearSquared = frustumNear * frustumNear;
            float leftSquared = frustumLeft * frustumLeft;
            float rightSquared = frustumRight * frustumRight;
            float bottomSquared = frustumBottom * frustumBottom;
            float topSquared = frustumTop * frustumTop;

            float inverseLength = FastMath.invSqrt( nearSquared + leftSquared );
            coeffLeft[0] = frustumNear * inverseLength;
            coeffLeft[1] = -frustumLeft * inverseLength;

            inverseLength = FastMath.invSqrt( nearSquared + rightSquared );
            coeffRight[0] = -frustumNear * inverseLength;
            coeffRight[1] = frustumRight * inverseLength;

            inverseLength = FastMath.invSqrt( nearSquared + bottomSquared );
            coeffBottom[0] = frustumNear * inverseLength;
            coeffBottom[1] = -frustumBottom * inverseLength;

            inverseLength = FastMath.invSqrt( nearSquared + topSquared );
            coeffTop[0] = -frustumNear * inverseLength;
            coeffTop[1] = frustumTop * inverseLength;
        }
        else {
            coeffLeft[0] = 1;
            coeffLeft[1] = 0;

            coeffRight[0] = -1;
            coeffRight[1] = 0;

            coeffBottom[0] = 1;
            coeffBottom[1] = 0;

            coeffTop[0] = -1;
            coeffTop[1] = 0;
        }

        updateMatrices = true;
    }

    /**
     * <code>onFrameChange</code> updates the view frame of the camera. It
     * should be noted that the abstract implementation of this class only
     * updates the data, and does not make any rendering calls. As such, any
     * implementing subclass should insure to override this method call it with
     * super and then call the rendering specific code.
     */
    public void onFrameChange() {
        float dirDotLocation = direction.dot( location );

        // left plane
        Vector3f leftPlaneNormal = worldPlane[LEFT_PLANE].normal;
        leftPlaneNormal.x = left.x * coeffLeft[0];
        leftPlaneNormal.y = left.y * coeffLeft[0];
        leftPlaneNormal.z = left.z * coeffLeft[0];
        leftPlaneNormal.addLocal( direction.x * coeffLeft[1], direction.y
                * coeffLeft[1], direction.z * coeffLeft[1] );
        worldPlane[LEFT_PLANE].setConstant( location.dot( leftPlaneNormal ) );

        // right plane
        Vector3f rightPlaneNormal = worldPlane[RIGHT_PLANE].normal;
        rightPlaneNormal.x = left.x * coeffRight[0];
        rightPlaneNormal.y = left.y * coeffRight[0];
        rightPlaneNormal.z = left.z * coeffRight[0];
        rightPlaneNormal.addLocal( direction.x * coeffRight[1], direction.y
                * coeffRight[1], direction.z * coeffRight[1] );
        worldPlane[RIGHT_PLANE].setConstant( location.dot( rightPlaneNormal ) );

        // bottom plane
        Vector3f bottomPlaneNormal = worldPlane[BOTTOM_PLANE].normal;
        bottomPlaneNormal.x = up.x * coeffBottom[0];
        bottomPlaneNormal.y = up.y * coeffBottom[0];
        bottomPlaneNormal.z = up.z * coeffBottom[0];
        bottomPlaneNormal.addLocal( direction.x * coeffBottom[1], direction.y
                * coeffBottom[1], direction.z * coeffBottom[1] );
        worldPlane[BOTTOM_PLANE].setConstant( location.dot( bottomPlaneNormal ) );

        // top plane
        Vector3f topPlaneNormal = worldPlane[TOP_PLANE].normal;
        topPlaneNormal.x = up.x * coeffTop[0];
        topPlaneNormal.y = up.y * coeffTop[0];
        topPlaneNormal.z = up.z * coeffTop[0];
        topPlaneNormal.addLocal( direction.x * coeffTop[1], direction.y
                * coeffTop[1], direction.z * coeffTop[1] );
        worldPlane[TOP_PLANE].setConstant( location.dot( topPlaneNormal ) );

        if ( isParallelProjection() ) {
            worldPlane[LEFT_PLANE].setConstant( worldPlane[LEFT_PLANE].getConstant() + frustumLeft );
            worldPlane[RIGHT_PLANE].setConstant( worldPlane[RIGHT_PLANE].getConstant() - frustumRight );
            worldPlane[TOP_PLANE].setConstant( worldPlane[TOP_PLANE].getConstant() + frustumTop );
            worldPlane[BOTTOM_PLANE].setConstant( worldPlane[BOTTOM_PLANE].getConstant() - frustumBottom );
        }

        // far plane
        worldPlane[FAR_PLANE].normal.set( -direction.x, -direction.y,
                -direction.z );
        worldPlane[FAR_PLANE].setConstant( -( dirDotLocation + frustumFar ) );

        // near plane
        worldPlane[NEAR_PLANE].normal
                .set( direction.x, direction.y, direction.z );
        worldPlane[NEAR_PLANE].setConstant( dirDotLocation + frustumNear );

        updateMatrices = true;
        updateSMatrices = true;
    }

    /**
     * @return true if parallel projection is enable, false if in normal perspective mode
     * @see #setParallelProjection(boolean)
     */
    public boolean isParallelProjection() {
        return this.parallelProjection;
    }

    /**
     * store the value for field parallelProjection
     */
    private boolean parallelProjection;

    /**
     * Enable/disable parallel projection.
     *
     * @param value true to set up this camera for parallel projection is enable, false to enter normal perspective mode
     */
    public void setParallelProjection( final boolean value ) {
        this.parallelProjection = value;
    }

    /* @see Camera#getWorldCoordinates */
    public Vector3f getWorldCoordinates( Vector2f screenPos, float zPos ) {
        return getWorldCoordinates( screenPos, zPos, null );
    }

    protected final Matrix4f _transMatrix = new Matrix4f();
    protected final Matrix4f _modelView = new Matrix4f();
    protected final Matrix4f _projection = new Matrix4f();


    public Matrix4f getProjectionMatrix() {
        if (isParallelProjection()) {
            _projection.loadIdentity();
            _projection.m00 = 2.0f / (frustumRight - frustumLeft);
            _projection.m11 = 2.0f / (frustumBottom - frustumTop);
            _projection.m22 = -2.0f / (frustumFar - frustumNear);
            _projection.m33 = 1f;
            _projection.m30 = -(frustumRight + frustumLeft) / (frustumRight - frustumLeft);
            _projection.m31 = -(frustumBottom + frustumTop) / (frustumBottom - frustumTop);
            _projection.m32 = -(frustumFar + frustumNear) / (frustumFar - frustumNear);
        } else {
            // XXX: Cache results or is this low cost enough to happen every time it is called?
            _projection.loadIdentity();
            _projection.m00 = (2.0f * frustumNear) / (frustumRight - frustumLeft);
            _projection.m11 = (2.0f * frustumNear) / (frustumTop - frustumBottom);
            _projection.m20 = (frustumRight + frustumLeft) / (frustumRight - frustumLeft);
            _projection.m21 = (frustumTop + frustumBottom) / (frustumTop - frustumBottom);
            _projection.m22 = -(frustumFar + frustumNear) / (frustumFar - frustumNear);
            _projection.m32 = -(2.0f * frustumFar * frustumNear) / (frustumFar - frustumNear);
            _projection.m23 = -1.0f;
            _projection.m33 = -0.0f;
        }
        return _projection;
    }

    public Matrix4f getModelViewMatrix() {
        // XXX: Cache results or is this low cost enough to happen every time it is called?
        _modelView.loadIdentity();
        _modelView.m00 = -left.x;
        _modelView.m10 = -left.y;
        _modelView.m20 = -left.z;

        _modelView.m01 = up.x;
        _modelView.m11 = up.y;
        _modelView.m21 = up.z;

        _modelView.m02 = -direction.x;
        _modelView.m12 = -direction.y;
        _modelView.m22 = -direction.z;

        _transMatrix.loadIdentity();
        _transMatrix.m30 = -location.x;
        _transMatrix.m31 = -location.y;
        _transMatrix.m32 = -location.z;

        _transMatrix.multLocal(_modelView);
        _modelView.set(_transMatrix);

        return _modelView;
    }

    private static final Quaternion tmp_quat = new Quaternion();

    private boolean updateMatrices = true;
    private boolean updateSMatrices = true;
    private final Matrix4f modelViewProjectionInverse = new Matrix4f();
    private final Matrix4f modelViewProjection = new Matrix4f();

    private boolean dataOnly;

    /* @see Camera#getWorldCoordinates */
    public Vector3f getWorldCoordinates( Vector2f screenPosition,
                                         float zPos, Vector3f store ) {
        if ( store == null ) {
            store = new Vector3f();
        }
        checkViewProjection();
        if ( updateMatrices ) {
            modelViewProjection.invert( modelViewProjectionInverse );
            updateMatrices = false;
        }
        tmp_quat.set(
                ( screenPosition.x / getWidth() - viewPortLeft ) / ( viewPortRight - viewPortLeft ) * 2 - 1,
                ( screenPosition.y / getHeight() - viewPortBottom ) / ( viewPortTop - viewPortBottom ) * 2 - 1,
                zPos * 2 - 1, 1 );
        modelViewProjectionInverse.mult( tmp_quat, tmp_quat );
        tmp_quat.multLocal( 1.0f / tmp_quat.w );
        store.x = tmp_quat.x;
        store.y = tmp_quat.y;
        store.z = tmp_quat.z;
        return store;
    }

    /* @see Camera#getScreenCoordinates */
    public Vector3f getScreenCoordinates( Vector3f worldPos ) {
        return getScreenCoordinates( worldPos, null );
    }


    /**
     * Implementation contributed by Zbyl.
     *
     * @see Camera#getScreenCoordinates(Vector3f, Vector3f)
     */
    public Vector3f getScreenCoordinates( Vector3f worldPosition, Vector3f store ) {
        if ( store == null ) {
            store = new Vector3f();
        }
        checkViewProjection();
        tmp_quat.set( worldPosition.x, worldPosition.y, worldPosition.z, 1 );
        modelViewProjection.mult( tmp_quat, tmp_quat );
        tmp_quat.multLocal( 1.0f / tmp_quat.w );
        store.x = ( ( tmp_quat.x + 1 ) * ( viewPortRight - viewPortLeft ) / 2 ) * getWidth();
        store.y = ( ( tmp_quat.y + 1 ) * ( viewPortTop - viewPortBottom ) / 2 ) * getHeight();
        store.z = ( tmp_quat.z + 1 ) / 2;

        return store;
    }

    /**
     * update modelViewProjection if necessary.
     */
    private void checkViewProjection() {
        if ( updateSMatrices ) {
            modelViewProjection.set( getModelViewMatrix() ).multLocal( getProjectionMatrix() );
            updateSMatrices = false;
        }
    }

    /**
     * @return the width/resolution of the display.
     */
    public abstract int getHeight();

    /**
     * @return the height/resolution of the display.
     */
    public abstract int getWidth();
    
    public void write(JMEExporter e) throws IOException {
        OutputCapsule capsule = e.getCapsule(this);
        capsule.write(location, "location", Vector3f.ZERO);
        capsule.write(left, "left", Vector3f.UNIT_X);
        capsule.write(up, "up", Vector3f.UNIT_Y);
        capsule.write(direction, "direction", Vector3f.UNIT_Z);
        capsule.write(frustumNear, "frustumNear", 1);
        capsule.write(frustumFar, "frustumFar", 2);
        capsule.write(frustumLeft, "frustumLeft", -0.5f);
        capsule.write(frustumRight, "frustumRight", 0.5f);
        capsule.write(frustumTop, "frustumTop", 0.5f);
        capsule.write(frustumBottom, "frustumBottom", -0.5f);
        capsule.write(coeffLeft, "coeffLeft", new float[2]);
        capsule.write(coeffRight, "coeffRight", new float[2]);
        capsule.write(coeffBottom, "coeffBottom", new float[2]);
        capsule.write(coeffTop, "coeffTop", new float[2]);
        capsule.write(planeQuantity, "planeQuantity", 6);
        capsule.write(viewPortLeft, "viewPortLeft", 0);
        capsule.write(viewPortRight, "viewPortRight", 1);
        capsule.write(viewPortTop, "viewPortTop", 1);
        capsule.write(viewPortBottom, "viewPortBottom", 0);
        capsule.write(width, "width", 0);
        capsule.write(height, "height", 0);
    }

    public void read(JMEImporter e) throws IOException {
        InputCapsule capsule = e.getCapsule(this);
        location = (Vector3f)capsule.readSavable("location", Vector3f.ZERO.clone());
        left = (Vector3f)capsule.readSavable("left", Vector3f.UNIT_X.clone());
        up = (Vector3f)capsule.readSavable("up", Vector3f.UNIT_Y.clone());
        direction = (Vector3f)capsule.readSavable("direction", Vector3f.UNIT_Z.clone());
        frustumNear = capsule.readFloat("frustumNear", 1);
        frustumFar = capsule.readFloat("frustumFar", 2);
        frustumLeft = capsule.readFloat("frustumLeft", -0.5f);
        frustumRight = capsule.readFloat("frustumRight", 0.5f);
        frustumTop = capsule.readFloat("frustumTop", 0.5f);
        frustumBottom = capsule.readFloat("frustumBottom", -0.5f);
        coeffLeft = capsule.readFloatArray("coeffLeft", new float[2]);
        coeffRight = capsule.readFloatArray("coeffRight", new float[2]);
        coeffBottom = capsule.readFloatArray("coeffBottom", new float[2]);
        coeffTop = capsule.readFloatArray("coeffTop", new float[2]);
        planeQuantity = capsule.readInt("planeQuantity", 6);
        viewPortLeft = capsule.readFloat("viewPortLeft", 0);
        viewPortRight = capsule.readFloat("viewPortRight", 1);
        viewPortTop = capsule.readFloat("viewPortTop", 1);
        viewPortBottom = capsule.readFloat("viewPortBottom", 0);
        width = capsule.readInt("width", 0);
        height = capsule.readInt("height", 0);
    }
    
    public Class<AbstractCamera> getClassTag() {
        return AbstractCamera.class;
    }
    
    public void setDataOnly(boolean dataOnly) {
        this.dataOnly = dataOnly;
    }
    
    public boolean isDataOnly() {
        return dataOnly;
    }
}

⌨️ 快捷键说明

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