Thursday, May 7, 2020

Adjusting the Apex Angle

Finally, we want to be able to change the aspect ratio on the cones, that is, how their base compares to their height.  We are going to control this by limiting the scroll wheel action of moving backwards and forwards to the area around the origin and allowing the same gesture further away to cause the radius to expand and contract.

Calculating the Ratio 

The first thing I tried was to simply update the radius on the cone but, predictably enough, once you have created the cone it stays created.  I suppose it would be possible to remove the cones and create new ones, but that seemed excessive.  Instead, what we are going to do is to scale the cone but not symmetrically: we are only going to scale it in the x and z directions.  Because scaling is the first operation to be performed in our update sequence, the base of the cone will always be in the xz plane and so scaling in those directions is sufficient.

In order to make this work we need to keep track of the "current intended radius" and express the scaling as a ratio between that and the "actual radius" of the cone.  We hardcoded that to 20 earlier, so our first step is to extract that; at the same time we'll extract the height of the cone which is used in a number of different places in the code.
var rad = 20;
var baserad = 20;
var ht = 50;

Identifying the cases

Then we need to identify whether we want to continue using the current event handling - moving the cones backwards and forwards - or the new apex angle adjustment based on the mouse location.  The mouse events provided are based on the canvas coordinates, but have been adjusted to reflect the origin.  Thus by saying "close to center" we really do mean something like within a 60-pixel radius of (0, 0).  This function uses Pythagoras' theorem to determine that:
function closeToCenter(e) {
  var r = e.x * e.x + e.y * e.y;
  return r < 3600;
}

The Updated Event Handler

Finally, we can implement the updated event handler.  The existing logic to update the depth is now made conditional on the event being sufficiently close to the center.  The new logic that is applied in the other case updates the "current radius" and then scales both the x and z dimensions based on the ratio of the "current radius" to the original "base radius". 
if (closeToCenter(e)) {
  depth -= e.wheel;
} else {
  rad -= e.wheel;
  top.scale.x = rad / baserad;
  top.scale.z = rad / baserad;
  bottom.scale.x = rad / baserad;
  bottom.scale.z = rad / baserad;
}
Either way, the existing code to actually update the object's matrix will be called once the new values have been calculated.

Summary

That finishes up our conic section viewer.  This post is tagged SHOW_CONES_INTERSECT_PLANE.

The viewer is not as slick or perfect as I would like, but it does work.  More importantly, I now feel I have a handle on what it takes to build WebGL applications with PhiloGL.

Since there is a lot more to WebGL than this, I may well be back to try and dig into additional topics such as custom rendering, blending and the like which seem to require a deeper understanding of the WebGLContext, and possibly even some embedded script programming.

No comments:

Post a Comment