?? camera.java
字號:
// Warning: Why test with the contrary plane? clippingPlane = nearPlane; } else { // Not possible: non implemented case! VSDK.reportMessage(this, VSDK.WARNING, "clipLineCohenSutherlandPlanes", "Unusal ray case, check code and data"); } if ( clippingPlane != null ) { if ( !clippingPlane.doIntersection(testRay) ) { VSDK.reportMessage(this, VSDK.WARNING, "clipLineCohenSutherlandPlanes", "Unusal ray assembly, check code and data"); } clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t)); linePasses = true; } //-------------------------------------------------- if ( outcodeout == outcode0 ) { clippedPoint0.x = clippingMidPoint.x; clippedPoint0.y = clippingMidPoint.y; clippedPoint0.z = clippingMidPoint.z; outcode0 = calculateOutcodeBits(clippedPoint0, rightPlane, leftPlane, upPlane, downPlane, nearPlane, farPlane); } else { clippedPoint1.x = clippingMidPoint.x; clippedPoint1.y = clippingMidPoint.y; clippedPoint1.z = clippingMidPoint.z; outcode1 = calculateOutcodeBits(clippedPoint1, rightPlane, leftPlane, upPlane, downPlane, nearPlane, farPlane); } } } while ( !done ); return linePasses; } /** This method implements the Cohen-Sutherland line clipping algorithm with respect to the view volume defined by current camera. Recieves the two line endpoints and return true if any part of this line lies inside the view volume. In the case the line crosses the view volume, the new resulting endpoints are calculated and returned. This algorithm structure follows the one proposed in [FOLE1992].3.12.3, generalizing it to the 3D case, as noted in [FOLE1992].6.5.3. The resulting clipped points are in the canonical volume reference, ready for projection. If 3D clipped points are needed, they must be premultiplied by the inverse of the normalizingTransformation. */ public boolean clipLineCohenSutherlandCanonicVolume( Vector3D point0, Vector3D point1, Vector3D clippedPoint0, Vector3D clippedPoint1) { //- Local variables definition ------------------------------------ int outcode0; // 6bit containment code for point0 int outcode1; // 6bit containment code for point1 int outcodeout; // Selected endpoint code for iteration Vector3D clippingMidPoint; // Selected endpoint clipped for iteration Ray testRay; // Ray use for general line/plane clipping Vector3D dirFromP0ToP1; // Temporary for testRay construction double l; // Length of dirFromP0ToP1 int planeId; // A number from 1 to 6 identifying which // plane intersection is being tested //- Algorithm initial state --------------------------------------- Vector3D pp0, pp1; pp0 = normalizingTransformation.multiply(point0); pp1 = normalizingTransformation.multiply(point1); clippedPoint0.x = pp0.x; clippedPoint0.y = pp0.y; clippedPoint0.z = pp0.z; clippedPoint1.x = pp1.x; clippedPoint1.y = pp1.y; clippedPoint1.z = pp1.z; updateVectors(); clippingMidPoint = new Vector3D(); outcode0 = calculateOutcodeBits(pp0); outcode1 = calculateOutcodeBits(pp1); //- Main Cohen-Sutherland iteration cycle (incremental clipping) -- boolean linePasses = false; // Algorithm return value boolean done = false; // Iteration exit condition do { //- Trivial cases: trivial accept and trivial reject ---------- if ( outcode0 == 0x0 && outcode1 == 0x0 ) { linePasses = true; done = true; } else if ( (outcode0 & outcode1) != 0x0 ) { linePasses = false; done = true; } //- Iterative cases: clipping with each of the 6 planes ------- else { //-------------------------------------------------- dirFromP0ToP1 = clippedPoint1.substract(clippedPoint0); l = dirFromP0ToP1.length(); if ( l < VSDK.EPSILON ) { // continue; return false; } dirFromP0ToP1.x /= l; dirFromP0ToP1.y /= l; dirFromP0ToP1.z /= l; //-------------------------------------------------- if ( outcode0 != 0 ) { outcodeout = outcode0; } else { outcodeout = outcode1; } testRay = new Ray(clippedPoint0, dirFromP0ToP1); //-------------------------------------------------- planeId = 0; if ( (OPCODE_UP & outcodeout) != 0x0 ) { planeId = 1; // up plane; } else if ( (OPCODE_DOWN & outcodeout) != 0x0 ) { planeId = 2; // down plane; } else if ( (OPCODE_LEFT & outcodeout) != 0x0 ) { planeId = 3; // left plane; } else if ( (OPCODE_RIGHT & outcodeout) != 0x0 ) { planeId = 4; // right plane; } else if ( (OPCODE_NEAR & outcodeout) != 0x0 ) { planeId = 5; // near plane } else if ( (OPCODE_FAR & outcodeout) != 0x0 ) { planeId = 6; // far plane; } else { // Not possible: non implemented case! VSDK.reportMessage(this, VSDK.WARNING, "clipLineCohenSutherlandCanonicVolume", "Unusal case, check code and data"); } double de; de = (outcodeout == outcode1) ? -VSDK.EPSILON: VSDK.EPSILON; switch ( planeId ) { case 1: // up plane testRay.t = (l * (1 - clippedPoint0.z - clippedPoint0.y)) / (clippedPoint1.z - clippedPoint0.z + clippedPoint1.y - clippedPoint0.y); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; case 2: // down plane testRay.t = (l * (clippedPoint0.y - clippedPoint0.z +1)) / (clippedPoint1.z - clippedPoint0.z - clippedPoint1.y + clippedPoint0.y); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; case 3: // left plane testRay.t = (l * (clippedPoint0.x - clippedPoint0.z +1)) / (clippedPoint1.z - clippedPoint0.z - clippedPoint1.x + clippedPoint0.x); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; case 4: // right plane testRay.t = (l * (1 - clippedPoint0.z - clippedPoint0.x)) / (clippedPoint1.z - clippedPoint0.z + clippedPoint1.x - clippedPoint0.x); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; case 5: // near plane // Warning: near plane clipping testRay.t = ( /*(1-nearPlaneDistance)*/ -clippedPoint0.z * l) / (clippedPoint1.z - clippedPoint0.z); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; case 6: // far plane testRay.t = (((-fpd()- clippedPoint0.z) * l) / (clippedPoint1.z - clippedPoint0.z)); clippingMidPoint = testRay.origin.add( testRay.direction.multiply(testRay.t+de)); linePasses = true; break; } //-------------------------------------------------- if ( outcodeout == outcode0 ) { clippedPoint0.x = clippingMidPoint.x; clippedPoint0.y = clippingMidPoint.y; clippedPoint0.z = clippingMidPoint.z; outcode0 = calculateOutcodeBits(clippedPoint0); } else { clippedPoint1.x = clippingMidPoint.x; clippedPoint1.y = clippingMidPoint.y; clippedPoint1.z = clippingMidPoint.z; outcode1 = calculateOutcodeBits(clippedPoint1); } } } while ( !done ); return linePasses; } /** Given a point `inPoint` in world coordinates, this method calculates a pixel's coordinate in viewport space (in the form <u, v, 0>). Returns true if the pixel lies inside the viewport, false otherwise. Note that the integer part of the returned `outProjected` point (in its x and y coordinates) can be used as an input to a putPixel type image operation for display, and the same coordinate as double, is usefull as an input for antialiased versions of line rasterizers. This method is fundamental for visualization operations, where some examples includes but are not limited to: - Given two (previously clipped) line endpoints in world space, projected positions can be used for 2D line drawing for wireframe and hidden line rendering algorithms (caligraphic phase prior to 2D rasterizing). - For interaction techniques, 2D feedback over 2D visualization. - As part of complex interaction techniques involving a 3D point image in camera viewport, for example to calculate relative movement in 3D with respect to aparent current view from camera. TODO: Current implementation is suspicious. It should use a simple multiplication of point with projection matrix... but this idea is not working. */ public boolean projectPoint(Vector3D inPoint, Vector3D outProjected) { // 1. Calculate vectors Vector3D upCopy = null; Vector3D rightCopy = null; double fovFactor = 0.0; double scaleFactor = 0.0; fovFactor = viewportXSize/viewportYSize; updateVectors(); // Should be made a prerequisite for efficiency! // 2. Calculate projection plane Vector3D p; Vector3D center; InfinitePlane viewPlane; center = new Vector3D(front); p = getPosition(); center.normalize(); center.multiply(nearPlaneDistance); center = center.add(p); viewPlane = new InfinitePlane(front.multiply(-1), center); // 3. Calculate projected global coordinates XYZ Vector3D projected; if ( projectionMode == PROJECTION_MODE_ORTHOGONAL ) { projected = (viewPlane.projectPoint(inPoint).substract(center)).multiply(orthogonalZoom); } else { // 3.1. Vector calculation for perspective case upCopy = new Vector3D(up); rightCopy = new Vector3D(left.multiply(-1)); scaleFactor = 1.0/Math.tan(Math.toRadians(fov/2)); upCopy.normalize(); upCopy = upCopy.multiply(scaleFactor); rightCopy.normalize(); rightCopy = rightCopy.multiply(scaleFactor).multiply(1/fovFactor); // 3.2. Calculate projector for perspective case Ray r; r = new Ray(p, inPoint.substract(p)); // 3.3. Project point in view plane from perspective eyepoint if ( !viewPlane.doIntersection(r) || r.direction.length() < VSDK.EPSILON ) { return false; } projected = r.origin.add(r.direction.multiply(r.t)).substract(center); // 3.4. Clip projected point in viewport if ( projected.x < -1 || projected.x > 1 || projected.y < -1 || projected.y > 1 ) { return false; } } // 4. Scale point to viewport if ( projectionMode == PROJECTION_MODE_ORTHOGONAL ) { outProjected.x = viewportXSize/2 + (projected.dotProduct(left.multiply(-1)))/(2*fovFactor)*viewportXSize; outProjected.y = (((projected.dotProduct(up)*-1)+1)/2)*viewportYSize; } else { outProjected.x = (projected.dotProduct(rightCopy)/2+0.5)*viewportXSize; outProjected.y = (1-(projected.dotProduct(upCopy)/2+0.5))*viewportYSize; } outProjected.z = 0.0; return true; } /** Return 6 outward pointing planes bounding the view volume / frustum for current camera. PRE: updateVectors method should be called before calling this method. */ public InfinitePlane[] getBoundingPlanes() { InfinitePlane planes[]; planes = new InfinitePlane[6]; planes[0] = calculateUPlane(-0.5); planes[1] = calculateUPlane(0.5); planes[2] = calculateVPlane(-0.5); planes[3] = calculateVPlane(0.5); planes[4] = calculateNearPlane(); planes[5] = calculateFarPlane(); return planes; }}//===========================================================================//= EOF =//===========================================================================
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -