protected void apply(DrawContext dc) { GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. gl.glEnable(GL2.GL_LIGHTING); applyStandardLightModel(gl); applyStandardShadeModel(gl); gl.glEnable(GL2.GL_LIGHT0); applyStandardLightMaterial(gl, GL2.GL_LIGHT0, this.lightMaterial); applyStandardLightDirection(gl, GL2.GL_LIGHT0, this.lightDirection); }
protected void beginDrawAnnotations(DrawContext dc, OGLStackHandler stackHandler) { GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. int attributeMask = GL2.GL_COLOR_BUFFER_BIT // for alpha test func and ref, blend func | GL2.GL_CURRENT_BIT // for current color | GL2.GL_DEPTH_BUFFER_BIT // for depth test, depth mask, depth func | GL2.GL_ENABLE_BIT // for enable/disable changes | GL2.GL_HINT_BIT // for line smoothing hint | GL2.GL_LINE_BIT // for line width, line stipple | GL2.GL_TRANSFORM_BIT // for matrix mode | GL2.GL_VIEWPORT_BIT; // for viewport, depth range stackHandler.pushAttrib(gl, attributeMask); // Load a parallel projection with dimensions (viewportWidth, viewportHeight) stackHandler.pushProjectionIdentity(gl); gl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView().getViewport().height, -1d, 1d); // Push identity matrices on the texture and modelview matrix stacks. Leave the matrix mode as modelview. stackHandler.pushTextureIdentity(gl); stackHandler.pushModelviewIdentity(gl); // Enable the alpha test. gl.glEnable(GL2.GL_ALPHA_TEST); gl.glAlphaFunc(GL2.GL_GREATER, 0.0f); // Apply the depth buffer but don't change it. if ((!dc.isDeepPickingEnabled())) { gl.glEnable(GL.GL_DEPTH_TEST); } gl.glDepthMask(false); // Disable lighting and backface culling. gl.glDisable(GL2.GL_LIGHTING); gl.glDisable(GL.GL_CULL_FACE); if (!dc.isPickingMode()) { // Enable blending in premultiplied color mode. gl.glEnable(GL.GL_BLEND); OGLUtil.applyBlending(gl, true); } else { this.pickSupport.beginPicking(dc); } }
/** * Causes this SurfaceObject to draw a representation of itself suitable for use during picking. * * @param dc the current DrawContext. */ protected void drawPickRepresentation(DrawContext dc) { // The pick representation is stored as a list of surface tiles. If the list is empty, then this surface object // was not picked. This method might be called when the list is null or empty because of an upstream // exception that prevented creation of the list. if (this.pickTileBuilder == null || this.pickTileBuilder.getTileCount(dc) == 0) { return; } // Draw the pickable representation of this surface object created during preRendering. GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. OGLStackHandler ogsh = new OGLStackHandler(); ogsh.pushAttrib(gl, GL2.GL_POLYGON_BIT); // For cull face enable, cull face, polygon mode. try { gl.glEnable(GL.GL_CULL_FACE); gl.glCullFace(GL.GL_BACK); gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL); dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.pickTileBuilder.getTiles(dc)); } finally { ogsh.pop(gl); // Clear the list of pick tiles to avoid retaining references to them in case we're never picked again. this.pickTileBuilder.clearTiles(dc); } }
// public static void main(String[] args) // { // Box box = new Box(new Vec4[] {new Vec4(1, 0, 0), new Vec4(0, 1, 0), new Vec4(0, 0, 1)}, // -.5, .5, -.5, .5, -.5, .5); // Line line = new Line(new Vec4(-1, 0.5, 0.5), new Vec4(1, 0, 0)); // Intersection[] intersections = box.intersect(line); // if (intersections != null && intersections.Length > 0 && intersections[0] != null) // System.out.println(intersections[0]); // if (intersections != null && intersections.Length > 1 && intersections[1] != null) // System.out.println(intersections[1]); // } // /** {@inheritDoc} */ // public Intersection[] intersect(Line line) // { // return WWMath.polytopeIntersect(line, this.planes); // // Algorithm from "3-D Computer Graphics" by Samuel R. Buss, 2005, Section X.1.4. // // // Determine intersection with each plane and categorize the intersections as "front" if the line intersects // // the front side of the plane (dot product of line direction with plane normal is negative) and "back" if the // // line intersects the back side of the plane (dot product of line direction with plane normal is positive). // // double fMax = -Double.MaxValue; // double bMin = Double.MaxValue; // bool isTangent = false; // // Vec4 u = line.getDirection(); // Vec4 p = line.getOrigin(); // // foreach (Plane plane in this.planes) // { // Vec4 n = plane.getNormal(); // double d = -plane.getDistance(); // // double s = u.dot3(n); // if (s == 0) // line is parallel to plane // { // double pdn = p.dot3(n); // if (pdn > d) // is line in positive halfspace (in front of) of the plane? // return null; // no intersection // else // { // if (pdn == d) // isTangent = true; // line coincident with plane // continue; // line is in negative halfspace; possible intersection; check other planes // } // } // // // Determine whether front or back intersection. // double a = (d - p.dot3(n)) / s; // if (u.dot3(n) < 0) // line intersects front face and therefore entering box // { // if (a > fMax) // { // if (a > bMin) // return null; // fMax = a; // } // } // else // line intersects back face and therefore leaving box // { // if (a < bMin) // { // if (a < 0 || a < fMax) // return null; // bMin = a; // } // } // } // // // Compute the Cartesian intersection points. There will be no more than two. // if (fMax >= 0) // intersects frontface and backface; point origin is outside the box // return new Intersection[] // { // new Intersection(p.add3(u.multiply3(fMax)), isTangent), // new Intersection(p.add3(u.multiply3(bMin)), isTangent) // }; // else // intersects backface only; point origin is within the box // return new Intersection[] {new Intersection(p.add3(u.multiply3(bMin)), isTangent)}; // } /** * Draws a representation of the <code>Box</code>. * * @param dc the <code>DrawContext</code> to be used. */ public void render(DrawContext dc) { if (dc == null) { String message = Logging.getMessage("nullValue.DocumentSourceIsNull"); Logging.logger().severe(message); throw new ArgumentException(message); } if (dc.isPickingMode()) { return; } Vec4 a = this.s.add3(this.t).multiply3(-0.5); Vec4 b = this.s.subtract3(this.t).multiply3(0.5); Vec4 c = this.s.add3(this.t).multiply3(0.5); Vec4 d = this.t.subtract3(this.s).multiply3(0.5); GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. OGLStackHandler ogsh = new OGLStackHandler(); ogsh.pushAttrib(gl, GL2.GL_COLOR_BUFFER_BIT // For alpha enable, blend enable, alpha func, blend func. | GL2.GL_CURRENT_BIT // For current color. | GL2.GL_LINE_BIT // For line width. | GL2.GL_TRANSFORM_BIT // For matrix mode. | GL2.GL_DEPTH_BUFFER_BIT); // For depth test enable, depth func. try { gl.glLineWidth(1f); gl.glEnable(GL.GL_BLEND); OGLUtil.applyBlending(gl, false); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(GL.GL_LEQUAL); gl.glColor4f(1f, 1f, 1f, 0.5f); this.drawBox(dc, a, b, c, d); gl.glDepthFunc(GL.GL_GREATER); gl.glColor4f(1f, 0f, 1f, 0.4f); this.drawBox(dc, a, b, c, d); } finally { ogsh.pop(gl); } }
//**************************************************************// //******************** Diagnostic Support ********************// //**************************************************************// /** * Causes this SurfaceObject to render its bounding sectors to the specified region in geographic coordinates. The * specified viewport denotes the geographic region and its corresponding screen viewport. * <p/> * The bounding sectors are rendered as a 1 pixel wide green outline. * * @param dc the current DrawContext. * @param sdc the context containing a geographic region and screen viewport corresponding to a surface tile. * * @see #getSectors(DrawContext) */ protected void drawBoundingSectors(DrawContext dc, SurfaceTileDrawContext sdc) { List <Sector> sectors = this.getSectors(dc); if (sectors == null) { return; } GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. int attributeMask = GL2.GL_COLOR_BUFFER_BIT // For alpha test enable, blend enable, alpha func, blend func. | GL2.GL_CURRENT_BIT // For current color. | GL2.GL_LINE_BIT; // For line smooth, line width. OGLStackHandler ogsh = new OGLStackHandler(); ogsh.pushAttrib(gl, attributeMask); ogsh.pushModelview(gl); try { gl.glEnable(GL.GL_BLEND); OGLUtil.applyBlending(gl, false); gl.glDisable(GL.GL_LINE_SMOOTH); gl.glLineWidth(1f); gl.glColor4f(1f, 1f, 1f, 0.5f); // Set the model-view matrix to transform from geographic coordinates to viewport coordinates. Matrix matrix = sdc.getModelviewMatrix(); gl.glMultMatrixd(matrix.toArray(new double[16], 0, false), 0); foreach (Sector s in sectors) { LatLon[] corners = s.getCorners(); gl.glBegin(GL2.GL_LINE_LOOP); gl.glVertex2f((float)corners[0].getLongitude().degrees, (float)corners[0].getLatitude().degrees); gl.glVertex2f((float)corners[1].getLongitude().degrees, (float)corners[1].getLatitude().degrees); gl.glVertex2f((float)corners[2].getLongitude().degrees, (float)corners[2].getLatitude().degrees); gl.glVertex2f((float)corners[3].getLongitude().degrees, (float)corners[3].getLatitude().degrees); gl.glEnd(); } } finally { ogsh.pop(gl); } }
/** * Configures the GL attached to the specified DrawContext for rendering a 2D model to a texture. The modelview * matrix is set to the identity, the projection matrix is set to an orthographic projection aligned with the * specified draw rectangle (x, y, width, height), the viewport and scissor boxes are set to the specified draw * rectangle, and the depth test and depth write flags are disabled. Because the viewport and scissor boxes are set * to the draw rectangle, only the texels intersecting the specified drawing rectangle (x, y, width, height) are * affected by GL commands. Once rendering is complete, this should always be followed with a call to {@link * #endRendering(gov.nasa.worldwind.render.DrawContext)}. * * @param dc the current DrawContext. * @param x the x-coordinate of the draw region's lower left corner. * @param y the y-coordinate of the draw region's lower left corner. * @param width the draw region width. * @param height the draw region height. * * @throws ArgumentException if the DrawContext is null. */ public void beginRendering(DrawContext dc, int x, int y, int width, int height) { if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new ArgumentException(message); } GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. this.drawRegion = new java.awt.Rectangle(x, y, width, height); // Note: there is no attribute bit for framebuffer objects. The default framebuffer object state (object ID 0 // is bound as the current fbo) is restored in endRendering(). this.stackHandler.pushAttrib(gl, GL2.GL_COLOR_BUFFER_BIT // For clear color. | GL2.GL_DEPTH_BUFFER_BIT // For depth test and depth mask. | GL2.GL_SCISSOR_BIT // For scissor test and scissor box. | GL2.GL_TRANSFORM_BIT // For matrix mode. | GL2.GL_VIEWPORT_BIT); // For viewport state. this.stackHandler.pushTextureIdentity(gl); this.stackHandler.pushProjectionIdentity(gl); gl.glOrtho(x, x + width, y, y + height, -1, 1); this.stackHandler.pushModelviewIdentity(gl); // Disable the depth test and writing to the depth buffer. This provides consistent render to texture behavior // regardless of whether we are using copy-to-texture or framebuffer objects. For copy-to-texture, the depth // test and depth writing are explicitly disabled. For fbos there is no depth buffer components, so the depth // dest is implicitly disabled. gl.glDisable(GL.GL_DEPTH_TEST); gl.glDepthMask(false); // Enable the scissor test and set both the scissor box and the viewport to the specified region. This enables // the caller to set up rendering to a subset of the texture. Note that the scissor box defines the region // affected by a call to glClear(). gl.glEnable(GL.GL_SCISSOR_TEST); gl.glScissor(x, y, width, height); gl.glViewport(x, y, width, height); if (this.useFramebufferObject(dc)) { this.beginFramebufferObjectRendering(dc); } }
protected void initializeFrame(DrawContext dc) { if (dc.getGLContext() == null) { String message = Logging.getMessage("BasicSceneController.GLContextNullStartRedisplay"); Logging.logger().severe(message); throw new IllegalStateException(message); } GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. gl.glPushAttrib(GL2.GL_VIEWPORT_BIT | GL2.GL_ENABLE_BIT | GL2.GL_TRANSFORM_BIT); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glEnable(GL.GL_DEPTH_TEST); }
/** * Sets the GL blending state according to the specified color mode. If <code>havePremultipliedColors</code> is * true, this applies a blending function appropriate for colors premultiplied by the alpha component. Otherwise, * this applies a blending function appropriate for non-premultiplied colors. * * @param gl the GL context. * @param havePremultipliedColors true to configure blending for colors premultiplied by the alpha components, and * false to configure blending for non-premultiplied colors. * * @throws ArgumentException if the GL is null. */ public static void applyBlending(GL2 gl, bool havePremultipliedColors) { if (gl == null) { String message = Logging.getMessage("nullValue.GLIsNull"); Logging.logger().severe(message); throw new ArgumentException(message); } gl.glEnable(GL2.GL_ALPHA_TEST); gl.glAlphaFunc(GL2.GL_GREATER, 0.0f); if (havePremultipliedColors) { gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); } else { // The separate blend function correctly handles regular (non-premultiplied) colors. We want // Cd = Cs*As + Cf*(1-As) // Ad = As + Af*(1-As) // So we use GL_EXT_blend_func_separate to specify different blending factors for source color and source // alpha. bool haveExtBlendFuncSeparate = gl.isExtensionAvailable(GL_EXT_BLEND_FUNC_SEPARATE); if (haveExtBlendFuncSeparate) { gl.glBlendFuncSeparate( GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, // rgb blending factors GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); // alpha blending factors } else { gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); } } }
protected bool generateTexture(DrawContext dc, int width, int height) { GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. OGLStackHandler ogsh = new OGLStackHandler(); Matrix geoToCartesian = this.computeGeographicToCartesianTransform(this.sector); try { ogsh.pushAttrib(gl, GL2.GL_COLOR_BUFFER_BIT | GL2.GL_ENABLE_BIT | GL2.GL_TRANSFORM_BIT | GL2.GL_VIEWPORT_BIT); // Fill the frame buffer with transparent black. gl.glClearColor(0f, 0f, 0f, 0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT); gl.glDisable(GL.GL_BLEND); gl.glDisable(GL.GL_CULL_FACE); gl.glDisable(GL.GL_DEPTH_TEST); // Setup a viewport with the dimensions of the texture, and a projection matrix of dimension 2.0 (along // each axis) centered at the origin. Using a projection matrix with these dimensions ensures that incoming // vertices are rasterized without any rounding error. ogsh.pushProjectionIdentity(gl); gl.glViewport(0, 0, width, height); gl.glOrtho(-1d, 1d, -1d, 1d, -1d, 1d); ogsh.pushModelviewIdentity(gl); ogsh.pushTextureIdentity(gl); if (this.sourceTexture != null) { try { gl.glEnable(GL.GL_TEXTURE_2D); if (!this.sourceTexture.bind(dc)) { return(false); } this.sourceTexture.applyInternalTransform(dc); // Setup the texture to replace the fragment color at each pixel. gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); int tessellationDensity = this.getTessellationDensity(); this.drawQuad(dc, geoToCartesian, tessellationDensity, tessellationDensity); } finally { gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, OGLUtil.DEFAULT_TEX_ENV_MODE); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); } } } finally { ogsh.pop(gl); } return(true); }
/** * Display the cylinder. * * @param dc the current draw context. * * @throws ArgumentException if the draw context is null. */ public void render(DrawContext dc) { if (dc == null) { String msg = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(msg); throw new ArgumentException(msg); } // Compute a matrix that will transform world coordinates to cylinder coordinates. The negative z-axis // will point from the cylinder's bottomCenter to its topCenter. The y-axis will be a vector that is // perpendicular to the cylinder's axisUnitDirection. Because the cylinder is symmetric, it does not matter // in what direction the y-axis points, as long as it is perpendicular to the z-axis. double tolerance = 1e-6; Vec4 upVector = (this.axisUnitDirection.cross3(Vec4.UNIT_Y).getLength3() <= tolerance) ? Vec4.UNIT_NEGATIVE_Z : Vec4.UNIT_Y; Matrix transformMatrix = Matrix.fromModelLookAt(this.bottomCenter, this.topCenter, upVector); double[] matrixArray = new double[16]; transformMatrix.toArray(matrixArray, 0, false); GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. OGLStackHandler ogsh = new OGLStackHandler(); ogsh.pushAttrib(gl, GL2.GL_CURRENT_BIT | GL2.GL_ENABLE_BIT | GL2.GL_TRANSFORM_BIT | GL2.GL_DEPTH_BUFFER_BIT); try { // The cylinder is drawn with as a wireframe plus a center axis. It's drawn in two passes in order to // visualize the portions of the cylinder above and below an intersecting surface. gl.glEnable(GL.GL_BLEND); OGLUtil.applyBlending(gl, false); gl.glEnable(GL.GL_DEPTH_TEST); // Draw the axis gl.glDepthFunc(GL.GL_LEQUAL); // draw the part that would normally be visible gl.glColor4f(1f, 1f, 1f, 0.4f); gl.glBegin(GL2.GL_LINES); gl.glVertex3d(this.bottomCenter.x, this.bottomCenter.y, this.bottomCenter.z); gl.glVertex3d(this.topCenter.x, this.topCenter.y, this.topCenter.z); gl.glEnd(); gl.glDepthFunc(GL.GL_GREATER); // draw the part that is behind an intersecting surface gl.glColor4f(1f, 0f, 1f, 0.4f); gl.glBegin(GL2.GL_LINES); gl.glVertex3d(this.bottomCenter.x, this.bottomCenter.y, this.bottomCenter.z); gl.glVertex3d(this.topCenter.x, this.topCenter.y, this.topCenter.z); gl.glEnd(); // Draw the exterior wireframe ogsh.pushModelview(gl); gl.glMultMatrixd(matrixArray, 0); GLUquadric quadric = dc.getGLU().gluNewQuadric(); dc.getGLU().gluQuadricDrawStyle(quadric, GLU.GLU_LINE); gl.glDepthFunc(GL.GL_LEQUAL); gl.glColor4f(1f, 1f, 1f, 0.5f); dc.getGLU().gluCylinder(quadric, this.cylinderRadius, this.cylinderRadius, this.cylinderHeight, 30, 30); gl.glDepthFunc(GL.GL_GREATER); gl.glColor4f(1f, 0f, 1f, 0.4f); dc.getGLU().gluCylinder(quadric, this.cylinderRadius, this.cylinderRadius, this.cylinderHeight, 30, 30); dc.getGLU().gluDeleteQuadric(quadric); } finally { ogsh.pop(gl); } }