Ames Room update. At the beginning of the lecture Mr. Dr. Gunn returned to exercises he gave in class last week. He showed that the projective matrix for the simplified 2D Ames room looks like: \[ \left( \begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 &0 \\ \dfrac{1}{n} & 0 & 1 \end{array} \right)\] where $n$ is the distance in meters to the right of the eye point, which is the image of the ideal point in the x-direction. As a result, Dr. Gunn asserted (shamelessly without proof) that any projectivity can be decomposed as the product of an affine matrix and an “Ames” projectivity — the latter being defined as a matrix, like the one above, which is the identity matrix except in the last row.
Geometry Factories This week we turned to discussing how geometry is represented in jReality. The basic classes PointSet, IndexedLineSet, and IndexedFaceSet were introduced. However, using these classes directly is awkward and time-consuming. Instead, there is a set of geometry factories which do the heavy lifting and allow the user to specify the geometry in a more mathematical way. We concentrate on the factory ParametricSurfaceFactory. This allows the user to specify an immersion of a rectangular domain in $\mathbb{R}^2$ into $\mathbb{R}^3$ or $\mathbf{P}^3$ (depending on whether one uses standard or homogeneous coordinates).
Assignment3 This assignment is designed to provide some practice in using geometry factories. In contrast to Assignment2, where you were asked to create a scene using very simple geometry and many transformations, in this assignment you are forbidden (Verboten!) to use matrices to “create” geometry, you have to use … geometry! Check out the latest version from the teacher git repository (the Tuesday tutorial participants have already made this step.) However, note that even if you were at the Tuesday tutorial, you should still update again since I’ve cleaned up the assignment and focused it more on the actual task at hand — I’ve removed the torus for example and have used the time parameter to rotate the square around — which is forbidden but it’s useful to see how a simple example works.
Update to Assignment3 [15.11]. I’ve updated Assignment3Example based on an example worked out in yesterday’s tutorial, which in turn was suggested in the classroom discussion yesterday. The result is that the example now rolls up the square into a cylinder:
How it’s done: The first step is to set two fields in the setValueAtTime() method: the time and the radius of the cylinder r. The radius depends on the time in such a way that it interpolates between $\infty$ and $\dfrac{1}{\pi}$ as $t$ varies between 0 and 1:
@Override
public void setValueAtTime(double d) {
time = d;
r = (time == 0) ? -1 : 1/(Math.PI*time);
surface.update();
}
Then when the factory is updated, the evaluate() method uses these fields to construct a section of a vertical cylinder with radius $r=\dfrac{1}{\pi}$. The time $t=0$ is handled separately to produce the beginning square. The displayed section of this cylinder is subject to two constraints:
- It subtends a horizontal arc length of 2 (to be consistent with the fact that the beginning square has side length 2), and
- The vertical mid-line of the square remains fixed in space throughout the animation.
Condition 1) implies that the section of the cylinder subtends an angle of $t\pi$ so that it has arc length 2 as desired. Furthermore we choose the $(u,v)$ domain so that it goes from $(-1,-1)$ to $(1,1)$ and the values of $u=0$ corresponding to the vertical mid-line of the square are fixed: the square rolls up while keeping this line fixed. In order for this line to be fixed, we calculate that the axis of the cylinder has to have $xyz$ coordinates $(0, y, r)$. Taken together, this produces the following code for $evaluate()$:
@Override
public void evaluate(double u, double v, double[] xyz, int index) {
double angle = time * u * Math.PI;
xyz[0] = time == 0 ? u : r * Math.sin(angle);
xyz[1] = v;
xyz[2] = time == 0 ? 0 : -r * Math.cos(angle) + r;
xyz[3] = 1.0;
}
To satisfy the assignment, this animation would need to be continued so that at the end $t=1$ the cylinder has unrolled again so that the opposite side faces out.
3D Video Transitions: Practical applications of Assignment3. Due to some very important work I’m doing this week for Matheon, I’m not able to write such detailed blog posts as usual. This movie is a “cross-eyed stereo” movie meaning if you can cross your eyes just the right amount as you watch it, the images should fuse together to produce 3D depth. If you do view this movie, you’ll see that it consists of 3D transitions between still photos — the kind of transition I mentioned in class when I introduced Assignment3! So everything hangs together. In any case, everything you need to know to do Assignment 3 should be contained in the Java classes from the git repository. If not let me know. The assignment is due on Friday November 22, which is, if I’m not mistaken, the 50th anniversary of the assassination of John F. Kennedy, an event which I experienced as a 6th grader.
Assignment2 Update [11.11.2013] I’ve added some points to the discussion of Assignment2, to include how to get the inspector properly configured, and how to store and restore properties. Please take a look at these additions and extend your own code if you need to.
- I’m continuing to enjoy looking at the results of Assignment2. The assignments I’ve looked at look good. I’ve particularly enjoyed the ones with which have implemented the torus setup. Following picture shows a frame from the animation based on a torus. It reminds me of “op art”. They are recognizably cubes, but each looks like it was drawn using a different perspective.
- I’ve added a bit more functionality to Assignment2, so you can play around with the tool in the leaf child, that I demo-ed last Thursday 07.11.13 in class. (Exercise: why is 07.11.13 a special day. Hint: it has to do with prime numbers.). It’s designed so that if you update your repository to my gitorious repository (the one we named “teacher”) your code should continue to function unchanged, but the inspector now contains a button which allows you to activate a translate tool in the leaf component. If however you construct your own inspector w/o using a call to super.getInspector(), this button won’t appear for you.