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; }