예제 #1
0
  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;
  }
예제 #2
0
  // TODO -- Need to rethink. Might have to consider charTransform[] in returns pickInfo.
  @Override
  boolean intersect(
      PickShape pickShape,
      PickInfo pickInfo,
      int flags,
      Point3d iPnt,
      GeometryRetained geom,
      int geomIndex) {
    Transform3D tempT3D = new Transform3D();
    GeometryArrayRetained geo = null;
    int sIndex = -1;
    PickShape newPS;
    double minDist = Double.MAX_VALUE;
    double distance = 0.0;
    Point3d closestIPnt = new Point3d();

    for (int i = 0; i < numChars; i++) {
      geo = geometryList[i];
      if (geo != null) {
        tempT3D.invert(charTransforms[i]);
        newPS = pickShape.transform(tempT3D);
        if (geo.intersect(newPS, pickInfo, flags, iPnt, geom, geomIndex)) {
          if (flags == 0) {
            return true;
          }
          distance = newPS.distance(iPnt);
          if (distance < minDist) {
            sIndex = i;
            minDist = distance;
            closestIPnt.set(iPnt);
          }
        }
      }
    }

    if (sIndex >= 0) {
      // We need to transform iPnt to the vworld to compute the actual distance.
      // In this method we'll transform iPnt by its char. offset. Shape3D will
      // do the localToVworld transform.
      iPnt.set(closestIPnt);
      charTransforms[sIndex].transform(iPnt);
      return true;
    }
    return false;
  }
예제 #3
0
  @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);
    }
  }
예제 #4
0
  @Override
  synchronized void computeBoundingBox() {
    Point3d l = new Point3d();
    Point3d u = new Point3d();
    Vector3f location = new Vector3f(this.position);
    int i, k = 0, numTotal = 0;
    double width = 0, height = 0;
    Rectangle2D bounds;

    // Reset bounds data
    l.set(location);
    u.set(location);

    if (numChars != 0) {
      // Set loop counters based on path type
      if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) {
        k = 0;
        numTotal = numChars + 1;
      } else if (path == Text3D.PATH_LEFT || path == Text3D.PATH_DOWN) {
        k = 1;
        numTotal = numChars;
        // Reset bounds to bounding box if first character
        bounds = glyphVecs[0].getVisualBounds();
        u.x += bounds.getWidth();
        u.y += bounds.getHeight();
      }

      for (i = 1; i < numTotal; i++, k++) {
        width = glyphVecs[k].getLogicalBounds().getWidth();
        bounds = glyphVecs[k].getVisualBounds();
        // 'switch' could be outside loop with little hacking,
        width += charSpacing;
        height = bounds.getHeight();

        switch (this.path) {
          case Text3D.PATH_RIGHT:
            u.x += (width);
            if (u.y < (height + location.y)) {
              u.y = location.y + height;
            }
            break;
          case Text3D.PATH_LEFT:
            l.x -= (width);
            if (u.y < (height + location.y)) {
              u.y = location.y + height;
            }
            break;
          case Text3D.PATH_UP:
            u.y += height;
            if (u.x < (bounds.getWidth() + location.x)) {
              u.x = location.x + bounds.getWidth();
            }
            break;
          case Text3D.PATH_DOWN:
            l.y -= height;
            if (u.x < (bounds.getWidth() + location.x)) {
              u.x = location.x + bounds.getWidth();
            }
            break;
        }
      }

      // Handle string alignment. ALIGN_FIRST is handled by default
      if (alignment != Text3D.ALIGN_FIRST) {
        double cx = (u.x - l.x);
        double cy = (u.y - l.y);

        if (alignment == Text3D.ALIGN_CENTER) {
          cx *= .5;
          cy *= .5;
        }
        switch (path) {
          case Text3D.PATH_RIGHT:
            l.x -= cx;
            u.x -= cx;
            break;
          case Text3D.PATH_LEFT:
            l.x += cx;
            u.x += cx;
            break;
          case Text3D.PATH_UP:
            l.y -= cy;
            u.y -= cy;
            break;
          case Text3D.PATH_DOWN:
            l.y += cy;
            u.y += cy;
            break;
        }
      }
    }

    l.z = 0.0f;
    if ((font3D == null) || (font3D.fontExtrusion == null)) {
      u.z = l.z;
    } else {
      u.z = l.z + font3D.fontExtrusion.length;
    }
  }
예제 #5
0
  /**
   * Update per character transform based on Text3D location, per character size and path.
   *
   * <p>WARNING: Caller of this method must make sure SceneGraph is live, else exceptions may be
   * thrown.
   */
  final void updateTransformData() {
    int i, k = 0, numTotal = 0;
    double width = 0, height = 0;
    Vector3f location = new Vector3f(this.position);
    Rectangle2D bounds;

    // Reset bounds data
    lower.set(location);
    upper.set(location);

    charTransforms = new Transform3D[numChars];
    for (i = 0; i < numChars; i++) {
      charTransforms[i] = new Transform3D();
    }

    if (numChars != 0) {
      charTransforms[0].set(location);

      // Set loop counters based on path type
      if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) {
        k = 0;
        numTotal = numChars + 1;
      } else if (path == Text3D.PATH_LEFT || path == Text3D.PATH_DOWN) {
        k = 1;
        numTotal = numChars;
        // Reset bounds to bounding box if first character
        bounds = glyphVecs[0].getVisualBounds();
        upper.x += bounds.getWidth();
        upper.y += bounds.getHeight();
      }

      for (i = 1; i < numTotal; i++, k++) {
        width = glyphVecs[k].getLogicalBounds().getWidth();
        bounds = glyphVecs[k].getVisualBounds();
        // 'switch' could be outside loop with little hacking,
        width += charSpacing;
        height = bounds.getHeight();

        switch (this.path) {
          case Text3D.PATH_RIGHT:
            location.x += width;
            upper.x += (width);
            if (upper.y < (height + location.y)) {
              upper.y = location.y + height;
            }
            break;
          case Text3D.PATH_LEFT:
            location.x -= width;
            lower.x -= (width);
            if (upper.y < (height + location.y)) {
              upper.y = location.y + height;
            }
            break;
          case Text3D.PATH_UP:
            location.y += height;
            upper.y += height;
            if (upper.x < (bounds.getWidth() + location.x)) {
              upper.x = location.x + bounds.getWidth();
            }
            break;
          case Text3D.PATH_DOWN:
            location.y -= height;
            lower.y -= height;
            if (upper.x < (bounds.getWidth() + location.x)) {
              upper.x = location.x + bounds.getWidth();
            }
            break;
        }
        if (i < numChars) {
          charTransforms[i].set(location);
        }
      }

      // Handle string alignment. ALIGN_FIRST is handled by default
      if (alignment != Text3D.ALIGN_FIRST) {
        double cx = (upper.x - lower.x);
        double cy = (upper.y - lower.y);

        if (alignment == Text3D.ALIGN_CENTER) {
          cx *= .5;
          cy *= .5;
        }
        switch (path) {
          case Text3D.PATH_RIGHT:
            for (i = 0; i < numChars; i++) {
              charTransforms[i].mat[3] -= cx;
            }
            lower.x -= cx;
            upper.x -= cx;
            break;
          case Text3D.PATH_LEFT:
            for (i = 0; i < numChars; i++) {
              charTransforms[i].mat[3] += cx;
            }
            lower.x += cx;
            upper.x += cx;
            break;

          case Text3D.PATH_UP:
            for (i = 0; i < numChars; i++) {
              charTransforms[i].mat[7] -= cy;
            }
            lower.y -= cy;
            upper.y -= cy;
            break;
          case Text3D.PATH_DOWN:
            for (i = 0; i < numChars; i++) {
              charTransforms[i].mat[7] += cy;
            }
            lower.y += cy;
            upper.y += cy;
            break;
        }
      }
    }

    lower.z = 0.0f;
    if ((font3D == null) || (font3D.fontExtrusion == null)) {
      upper.z = lower.z;
    } else {
      upper.z = lower.z + font3D.fontExtrusion.length;
    }

    // update geoBounds
    getBoundingBox(geoBounds);
  }