Package javax.media.j3d

Source Code of javax.media.j3d.RasterRetained

/*
* Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/

package javax.media.j3d;

import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;

import javax.vecmath.Point2d;
import javax.vecmath.Point2i;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Point4d;

/**
* A Retained Raster.
*/

class RasterRetained extends GeometryRetained {

    /**
     * Raster type
     */
    int type = Raster.RASTER_COLOR;

    private int clipMode = Raster.CLIP_POSITION;
    private Point3f position = new Point3f();
    private int xSrcOffset = 0;
    private int ySrcOffset = 0;
    private int width = 0;
    private int height = 0;
    private int xDstOffset = 0;
    private int yDstOffset = 0;
    ImageComponent2DRetained image = null;
    Texture2DRetained texture = null;
    DepthComponentRetained depthComponent = null;

    RasterRetained() {
      this.geoType = GEO_TYPE_RASTER;
    }

    /**
     * Set the Raster position
     * @param position new raster position
     */
    final void setPosition(Point3f pos) {
  geomLock.getLock();
  position.x = pos.x;
  position.y = pos.y;
  position.z = pos.z;
  geomLock.unLock();
        sendChangedMessage(J3dThread.UPDATE_GEOMETRY, null, null);
    }

    /**
     * Retrieves the Raster's position
     * @param position the variable to receive the position vector
     */
    final void getPosition(Point3f pos) {
  pos.x = position.x;
  pos.y = position.y;
  pos.z = position.z;
    }

    /**
     * Sets the type of this raster object to one of: RASTER_COLOR,
     * RASTER_DEPTH, or RASTER_COLOR_DEPTH.
     * @param type the new type of this raster
     */
    final void setType(int type) {
  geomLock.getLock();
        this.type = type;
  geomLock.unLock();
    }


    /**
     * Retrieves the current type of this raster object, one of: RASTER_COLOR,
     * RASTER_DEPTH, or RASTER_COLOR_DEPTH.
     * @return type the type of this raster
     */
    final int getType() {
        return type;
    }

    /**
     * Sets the clipping mode of this raster object.
     * @param clipMode the new clipping mode of this raster,
     * one of: CLIP_POSITION or CLIP_IMAGE.  The default mode
     * is CLIP_POSITION.
     */
    final void setClipMode(int clipMode) {

  geomLock.getLock();
  this.clipMode = clipMode;
  geomLock.unLock();
  computeBoundingBox();
  if(source.isLive()) {
      //update the Shape3Ds that refer to this Raster
      int un = userLists.size();
      Shape3DRetained ms, shape;
      int sn;
      for(int i = 0; i < un; i++) {
      ArrayList<Shape3DRetained> shapeList = userLists.get(i);
    sn = shapeList.size();
    for(int j = 0; j < sn; j++) {
        ms = shapeList.get(j);
        shape = (Shape3DRetained)ms.sourceNode;
        shape.setBoundsAutoCompute(false);
        shape.setBounds(geoBounds);
    }
      }
  }

    }


    /**
     * Retrieves the current clipping mode of this raster object.
     * @return clipMode the clipping mode of this raster,
     * one of: CLIP_POSITION or CLIP_IMAGE.
     */
    final int getClipMode() {
        return clipMode;
    }

    /**
     * Sets the offset within the source array of pixels at which
     * to start copying.
     * @param xSrcOffset the x offset within the source array of pixels
     * at which to start copying
     * @param ySrcOffset the y offset within the source array of pixels
     * at which to start copying
     */
    final void setSrcOffset(int xSrcOffset, int ySrcOffset) {
  geomLock.getLock();
  this.xSrcOffset = xSrcOffset;
  this.ySrcOffset = ySrcOffset;
  geomLock.unLock();
    }

    /**
     * Retrieves the current source pixel offset.
     * @param srcOffset the object that will receive the source offset
     */
    final void getSrcOffset(Point srcOffset) {
  srcOffset.setLocation(xSrcOffset, ySrcOffset);
    }

    /**
     * Sets the number of pixels to be copied from the pixel array.
     * @param width the number of columns in the array of pixels to copy
     * @param height the number of rows in the array of pixels to copy
     */
    final void setSize(int width, int height) {
  geomLock.getLock();
  this.width = width;
  this.height = height;
  geomLock.unLock();
    }

    /**
     * Gets the size of the array of pixels to be copied.
     * @param size the new size
     */
    final void getSize(Dimension size) {
  size.setSize(width, height);
    }

    /**
     * Sets the destination pixel offset of the upper-left
     * corner of the rendered image relative to the transformed position.
     * @param xDstOffset the x coordinate of the new offset
     * @param yDstOffset the y coordinate of the new offset
     */
    final void setDstOffset(int xDstOffset, int yDstOffset) {
  geomLock.getLock();
  this.xDstOffset = xDstOffset;
  this.yDstOffset = yDstOffset;
  geomLock.unLock();
    }

    /**
     * Retrieves the current destination pixel offset.
     * @param dstOffset the object that will receive the destination offset
     */
    final void getDstOffset(Point dstOffset) {
  dstOffset.setLocation(xDstOffset, yDstOffset);
    }


    /**
     * Initializes the raster image to the specified image.
     * @param image new ImageCompoent2D object used as the raster image
     */
    final void initImage(ImageComponent2D img) {

        int texFormat;

        if(img == null) {
            image = null;
            texture = null;
            return;
        }

        image = (ImageComponent2DRetained) img.retained;
        image.setEnforceNonPowerOfTwoSupport(true);
        switch(image.getNumberOfComponents()) {
            case 1:
                texFormat = Texture.INTENSITY;
                break;
            case 2:
                texFormat = Texture.LUMINANCE_ALPHA;
                break;
            case 3:
                texFormat = Texture.RGB;
                break;
            case 4:
                texFormat = Texture.RGBA;
                break;
            default:
                assert false;
                return;
        }

        Texture2D tex2D = new Texture2D(Texture.BASE_LEVEL, texFormat,
                img.getWidth(), img.getHeight());
        texture = (Texture2DRetained) tex2D.retained;
        texture.setUseAsRaster(true);
        // Fix to issue 372 : ImageComponent.set(BufferedImage) ignored when used by Raster
        image.addUser(texture);
        texture.initImage(0,img);

    }

    /**
     * Sets the pixel array used to copy pixels to/from a Canvas3D.
     * This is used when the type is RASTER_COLOR or RASTER_COLOR_DEPTH.
     * @param image the ImageComponent2D object containing the
     * color data
     */
    final void setImage(ImageComponent2D img) {

        if((img != null) &&
                (img.getImageClass() == ImageComponent.ImageClass.NIO_IMAGE_BUFFER)) {
            throw new IllegalArgumentException(J3dI18N.getString("Background14"));
        }

        TextureRetained oldTex = this.texture;
        if (source.isLive()) {
            if (this.texture != null) {
                this.texture.clearLive(refCount);
            }
        }

        // Issue 370: only hold the geomLock while calling initImage
        // (cannot hold it while sending a message).
        geomLock.getLock();
        initImage(img);
        geomLock.unLock();

        if (source.isLive()) {
            if (texture != null) {
                texture.setLive(inBackgroundGroup, refCount);
            }

            sendChangedMessage((J3dThread.UPDATE_RENDER|J3dThread.UPDATE_RENDERING_ATTRIBUTES),
                    oldTex, this.texture);
        }
    }

    /**
     * Retrieves the current pixel array object.
     * @return image the ImageComponent2D object containing the
     * color data
     */
    final ImageComponent2D getImage() {
  return (image == null ? null : (ImageComponent2D)image.source);
    }

    /**
     * Sets the depth image used to copy pixels to/from a Canvas3D.
     * This is used when the type is RASTER_DEPTH or RASTER_COLOR_DEPTH.
     * @param depthImage the DepthComponent object containing the
     * depth (z-buffer) data
     */
    final void setDepthComponent(DepthComponent depthComponent) {
  geomLock.getLock();
        if (this.source.isLive()) {
      if (this.depthComponent != null) {
    this.depthComponent.clearLive(refCount);
      }
      if (depthComponent != null) {
    ((DepthComponentRetained)depthComponent.retained).setLive(inBackgroundGroup, refCount);
      }
  }

  if (depthComponent == null) {
            this.depthComponent = null;
  } else {
            this.depthComponent =
    (DepthComponentRetained)depthComponent.retained;
  }
  geomLock.unLock();
    }

    /**
     * Retrieves the current depth image object.
     * @return depthImage DepthComponent containing the
     * depth (z-buffer) data
     */
    final DepthComponent getDepthComponent() {
  return (depthComponent == null ? null :
    (DepthComponent)depthComponent.source);
    }

    @Override
    void setLive(boolean inBackgroundGroup, int refCount) {
        super.doSetLive(inBackgroundGroup, refCount);
  if (texture != null) {
      texture.setLive(inBackgroundGroup, refCount);
  }
  if (depthComponent != null) {
      depthComponent.setLive(inBackgroundGroup, refCount);
  }
        isEditable = source.getCapability(Raster.ALLOW_OFFSET_WRITE) ||
      source.getCapability(Raster.ALLOW_POSITION_WRITE) ||
      ((type & Raster.RASTER_COLOR) != 0 &&
       source.getCapability(Raster.ALLOW_IMAGE_WRITE)) ||
      ((type & Raster.RASTER_DEPTH) != 0 &&
       source.getCapability(
             Raster.ALLOW_DEPTH_COMPONENT_WRITE)) ||
      source.getCapability( Raster.ALLOW_SIZE_WRITE);

  super.markAsLive();
    }

    @Override
    void clearLive(int refCount) {
  super.clearLive(refCount);
  if (texture != null)
      texture.clearLive(refCount);
  if (depthComponent != null)
      depthComponent.clearLive(refCount);
    }
    /*
    // Simply pass along to the NodeComponents
    void compile(CompileState compState) {
  setCompiled();

  if (image != null)
      image.compile(compState);

  if (depthComponent != null)
      depthComponent.compile(compState);
    }
    */

    @Override
    void computeBoundingBox() {
  if(clipMode == Raster.CLIP_IMAGE) {
      // Disable view frustum culling by setting the raster's bounds to
      // infinity.
          Point3d minBounds = new Point3d(Double.NEGATIVE_INFINITY,
        Double.NEGATIVE_INFINITY,
        Double.NEGATIVE_INFINITY);
      Point3d maxBounds = new Point3d(Double.POSITIVE_INFINITY,
        Double.POSITIVE_INFINITY,
        Double.POSITIVE_INFINITY);
      geoBounds.setUpper(maxBounds);
      geoBounds.setLower(minBounds);
  } else {
      Point3d center = new Point3d();
      center.x = position.x;
      center.y = position.y;
      center.z = position.z;
      geoBounds.setUpper(center);
      geoBounds.setLower(center);
  }
    }

    @Override
    void update() {
  computeBoundingBox();
    }

    private void sendChangedMessage(int threads, Object arg1, Object arg2) {

  synchronized(liveStateLock) {
      if (source.isLive()) {
    synchronized (universeList) {
        int numMessages = universeList.size();
        J3dMessage[] m = new J3dMessage[numMessages];
        for (int i=0; i<numMessages; i++) {
      m[i] = new J3dMessage();
      m[i].type = J3dMessage.GEOMETRY_CHANGED;
      m[i].threads = threads;
      m[i].args[0] = Shape3DRetained.getGeomAtomsArray(userLists.get(i));
      m[i].args[1] = this;
      Object[] obj = new Object[2];
      obj[0] = arg1;
      obj[1] = arg2;
      m[i].args[2] = obj;
      m[i].args[3] = new Integer(changedFrequent);
      m[i].universe = universeList.get(i);
        }
        VirtualUniverse.mc.processMessage(m);
    }
      }
  }
    }


    @Override
    void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
            boolean updateAlpha, float alpha,
            int screen, boolean ignoreVertexColors) {

        // Compute the offset position of the raster
        // This has to be done at render time because we need access
        // to the Canvas3D info

        // Check if adjusted position needs to be computed
        Point3d adjPos = new Point3d();    // Position of the Raster after adjusting for dstOffset
        adjPos.set(position);

        Point2d winCoord = new Point2d()// Position of Raster in window coordinates
        Transform3D localToImagePlate = new Transform3D()// Local to Image plate transform

        Point3d clipCoord = computeWinCoord(cv, ra, winCoord, adjPos, localToImagePlate);

        // Test raster for out of bounds in Z.
        if (clipCoord == null) {
            return;
        }

        if(clipMode == Raster.CLIP_POSITION) {
            // Do trivial reject test on Raster position.
            if(!isRasterClipPositionInside(clipCoord)) {
                return;
            }
        }

        // Add the destination offset to the Raster position in window coordinates
        winCoord.x += xDstOffset;
        winCoord.y += yDstOffset;

        // System.err.println("Step 2 : adjPos " + adjPos + " winCoord " + winCoord);


        if((type == Raster.RASTER_COLOR) || (type == Raster.RASTER_COLOR_DEPTH)) {
            float devCoordZ = (float) (clipCoord.z * 0.5 - 0.5);
            // Do textfill stuffs
            if (texture != null) {
                // setup Texture pipe.
                cv.updateTextureForRaster(texture);

      cv.textureFill(this, winCoord, devCoordZ, alpha);

                // Restore texture pipe.
                cv.restoreTextureBin();
            }

        }

        if((type == Raster.RASTER_DEPTH) || (type == Raster.RASTER_COLOR_DEPTH)) {

            Point2i srcOffset = new Point2i(xSrcOffset, ySrcOffset);

            if (clipMode == Raster.CLIP_IMAGE) {
                clipImage(cv, ra, winCoord, srcOffset);
            }

            computeObjCoord(cv, winCoord, adjPos, localToImagePlate);

            cv.executeRasterDepth(cv.ctx,
                    (float) adjPos.x,
                    (float) adjPos.y,
                    (float) adjPos.z,
                    srcOffset.x,
                    srcOffset.y,
                    width,
                    height,
                    depthComponent.width,
                    depthComponent.height,
                    depthComponent.type,
                    ((DepthComponentIntRetained) depthComponent).depthData);

        }
    }


    /**
     * Clips the image against the window.  This method simulates
     * clipping the image by determining the subimage that will be
     * drawn and adjusting the xOffset and yOffset accordingly.  Only
     * clipping against the left and top edges needs to be handled,
     * clipping against the right and bottom edges will be handled by
     * the underlying graphics library automatically.
     */
    private void clipImage(Canvas3D canvas, RenderAtom ra, Point2d winCoord, Point2i srcOffset) {

        if ((winCoord.x > 0) && (winCoord.y > 0)) {
            return;
        }

  // Check if the Raster point will be culled
  // Note that w use 1 instead of 0, because when hardware
  // tranform the coordinate back to winCoord it may get
  // a small negative value due to numerically inaccurancy.
  // This clip the Raster away and cause flickering
  // (see bug 4732965)
  if(winCoord.x < 1) {
      // Negate the window position and use this as the offset
      srcOffset.x = (int)-winCoord.x+1;
      winCoord.x = 1;
  }

  if(winCoord.y < 1) {
      // Negate the window position and use this as the offset
      srcOffset.y = (int)-winCoord.y+1;
      winCoord.y = 1;
  }

  //check if user-specified subimage is smaller than the clipped image
  if (srcOffset.x < xSrcOffset)
      srcOffset.x = xSrcOffset;
  if(srcOffset.y < ySrcOffset)
      srcOffset.y = ySrcOffset;

    }


    private boolean isRasterClipPositionInside(Point3d clipCoord) {
        return (clipCoord.x >= -1.0) && (clipCoord.x <= 1.0) &&
                (clipCoord.y >= -1.0) && (clipCoord.y <= 1.0);
    }

    private void computeObjCoord(Canvas3D canvas, Point2d winCoord, Point3d objCoord,
                                Transform3D localToImagePlate) {
  // Back transform this pt. from window to object coordinates
  // Assumes this method is ALWAYS called after computeWinCoord has been
  // called. computeWinCoord calculates the Vworld to Image Plate Xform.
  // This method simply uses it without recomputing it.

  canvas.getPixelLocationInImagePlate(winCoord.x, winCoord.y, objCoord.z,
              objCoord);
  // Get image plate to object coord transform
  // inv(P x M)
  localToImagePlate.invert();
  localToImagePlate.transform(objCoord);
    }

    private Point3d computeWinCoord(Canvas3D canvas, RenderAtom ra,
        Point2d winCoord, Point3d objCoord,
                                Transform3D localToImagePlate) {
  // Get local to Vworld transform
  RenderMolecule rm = ra.renderMolecule;

  if (rm == null) {
      // removeRenderAtom() may set ra.renderMolecule to null
      // in RenderBin before this renderer thread run.
      return null;
        }

        // MT safe issue: We can't reference ra.renderMolecule below since
        // RenderBin thread may set it to null anytime. Use rm instead.

  Transform3D lvw = rm.localToVworld[rm.localToVworldIndex[
         NodeRetained.LAST_LOCAL_TO_VWORLD]];


        Point3d clipCoord3 = new Point3d();
        clipCoord3.set(objCoord);
        Point4d clipCoord4 = new Point4d();

        // Transform point from local coord. to clipping coord.
        lvw.transform(clipCoord3);
        canvas.vworldToEc.transform(clipCoord3);
        canvas.projTrans.transform(clipCoord3, clipCoord4);

        // clip check in Z
        if((clipCoord4.w <= 0.0) ||
                (clipCoord4.z > clipCoord4.w) || (-clipCoord4.z > clipCoord4.w)) {

            return null;
        }
        double invW = 1.0 / clipCoord4.w;

        clipCoord3.x = clipCoord4.x * invW;
        clipCoord3.y = clipCoord4.y * invW;
        clipCoord3.z = clipCoord4.z * invW;

  // Get Vworld to image plate Xform
  canvas.getLastVworldToImagePlate(localToImagePlate);

  // v' = vwip x lvw x v
  //     where v' = transformed vertex,
  //         lvw = local to Vworld Xform
  //        vwip = Vworld to Image plate Xform
  //        v = vertex

  // Compute composite local to image plate Xform
  localToImagePlate.mul(lvw);

  // Transform the Raster's position from object to world coordinates
  localToImagePlate.transform(objCoord);


  // Get the window coordinates of this point
  canvas.getPixelLocationFromImagePlate(objCoord, winCoord);

        return clipCoord3;
    }

    @Override
    int getClassType() {
  return RASTER_TYPE;
    }

    // notifies the Raster mirror object that the image data in a referenced
    // ImageComponent object is changed.
    // Currently we are not making use of this information.

    void notifyImageComponentImageChanged(ImageComponentRetained image,
                                        ImageComponentUpdateInfo value) {
    }

    @Override
    boolean intersect(PickShape pickShape, PickInfo pickInfo, int flags, Point3d iPnt,
                      GeometryRetained geom, int geomIndex) {
         return false;
     }

    @Override
    boolean intersect(Bounds targetBound) {
  return false;
    }

    @Override
    boolean intersect(Point3d[] pnts) {
  return false;
    }
    @Override
    boolean intersect(Transform3D thisToOtherVworld, GeometryRetained
          geom) {
  return false;
    }
    @Override
    boolean intersect(Transform3D thisLocalToVworld,
           Transform3D otherLocalToVworld,
           GeometryRetained geom) {
  return false;
    }

    @Override
    boolean intersect(Transform3D thisLocalToVworld, Bounds targetBound) {
  return false;
    }
    @Override
    void handleFrequencyChange(int bit) {
  if (bit == Raster.ALLOW_IMAGE_WRITE)
      setFrequencyChangeMask(bit, 0x1);

    }

}
TOP

Related Classes of javax.media.j3d.RasterRetained

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.