COMS W4172: 3D User Interface Design—Spring 2013

Prof. Steven Feiner
Date out: February 7, 2013
Date due: February 21, 2013


Assignment 1: Home, Sweet Home

Introduction

This assignment is designed to introduce you to programming in C# with Goblin XNA by having you create a 3D model of a room containing virtual objects with which the user can interact using a mouse and GUI elements on a desktop/laptop. (A little later in the semester, you will port this program to a Windows Phone device.)

Home

For this assignment, you will create a virtual model of a room in which you will place at least one table and at least two different kinds of chairs (each defined by either an .fbx file or a .x file), and at least two different kinds of simple objects on top of the table (see below for the definition of a simple object). The room should have a floor and two side walls. The floor and walls should each be a different color.

Objects

Each simple object on top of the table can be a shape created with GoblinXNA.Graphics.Geometry. (e.g., cube, cylinder, sphere, cone, or torus). Alternatively, you are welcome to create a simple object “from scratch” out of polygons that you define yourself. The table and chairs should be loaded as model objects (.fbx file, or .x file) using the GoblinXNA.Graphics.ModelLoader class. Models of a table and a chair are available for download at our CourseWorks site, although you are welcome to use different models. You can search for the second chair online (links to sites with free 3D models are provided on the TA page).

Each simple object must be a different color (or texture). The table should be placed within the room anywhere that you see fit. The chairs should initially be placed around the table, facing inward towards the table. The simple objects should rest on top of the table. You can use any .fbx or .x files created by you or by someone else (please provide credit). Note that texture mapping is not supported for the simple 3D objects found in GoblinXNA.Graphics.Geometry.

Selection

The user must be able to select any of the objects in the room using the mouse, but not any part of the room itself. (Direct selection using the mouse can be achieved using the NewtonPhysics.PickRayCast method, demonstrated in Goblin XNA Tutorial 4.) Once an object has been selected, you should change it in some way to indicate that visually. For example, the object could change color to a color that indicates selection. (Putting that another way, even though all of the objects are different colors, when each is selected, you could make it turn to a specific color or do something else that indicates that it is the selected object.) Think about which approach would be most effective.

Only one object should be in the selected state at a time. You should also have some way to deselect the currently selected object without selecting another object.

Control Panels

Using the GoblinXNA.UI.UI2D package, create a partially transparent control panel for each object. These panels should be placed in a position of your own choosing. None of the panels should be visible initially. Each panel should become visible only when the object to which it belongs is selected. These panels will contain controls for the parameters of the actions you assign to your objects and a button to trigger those actions (see next section for details).

Object Actions

Each object should have an action associated with it, as described below, which can transform that object when it is selected  Starting the action should be triggered by pressing the button on the control panel for that object. Stopping the action should also be triggered by pressing the same button. Thus, starting and stopping an action is done the same way for all objects. No action should stop until the user has issued the stop trigger.

Figure 1: Table should be able to translate parallel to the main axes of the floor. Figure 2: Each chair should be able to rotate around the table's up-axis. Figure 3: Each chair should be able to rotate around its own up-axis.

Table

The table object should be associated with the following translation transformation: The object must be able to translate parallel to the main axes of the floor (left/right and forward/backward, but not up/down), but should only translate parallel to one of those axes at a time (Figure 1). Using the object's control panel, the user should be able to select the axis to which the translation should be parallel and the translation speed and direction (positive or negative). Selecting a different axis should cause the object to begin translating parallel to that axis with the current speed and direction, starting from the object's position at the time at which the new axis is selected. (That is, the object should not reset to its starting position when a new axis is selected.)  Starting and stopping the action should not reset the object to its initial position, either. However, there should be some way to reset the object to its initial position.

Translating the table should cause the chairs and the simple objects on top of the table to translate by the same amount. In other words, the table must be the parent object of the chairs and the simple objects; consequently, any transformation applied to the table will affect its children.

To avoid losing sight of your table, you are welcome to implement bounds on how far the table can deviate from its original starting position.

Chairs

The chair objects should be associated with the following rotation transformation: Each object must be able to rotate around (a) the table's up-axis (Figure 2) and (b) its own up-axis (Figure 3), but should only rotate about one of those axes at a time. Another way to think about these rotations is: a chair should be able to (a) orbit around the table and (b) rotate in place. Using the object's control panel, the user should be able to select which of the two axes the rotation should be around and the rotational speed and direction (counterclockwise or clockwise). Selecting a different axis should cause the object to begin rotating about that axis with the current speed and direction, starting from the object's orientation around both of the axes at the time at which the new axis is selected. (That is, the object should not reset to its starting orientation when a new axis is selected.)  Starting and stopping the action should not reset the object to its initial orientation, either. However, there should be some way to reset the object to its initial orientation.

Simple objects

The simple objects should be associated with the following scaling transformation: The object must be able to scale along each of a set of three orthogonal axes, but should only scale along one of those axes at a time. Scaling should occur around some point on the table top. Using the object's control panel, the user should be able to select the axis along which scaling should occur and scaling speed and direction (larger or smaller). Selecting a different axis should cause the object to begin scaling along that axis with the current speed and direction, starting from the object's scale at the time at which the new axis is selected. (That is, the object should not reset to its starting scale when a new axis is selected.)  Starting and stopping the action should not reset it to its initial scale, either. However, there should be some way to reset the object to its initial scale.

Which set of axes to use is up to you: they may be those of the table, or those of the object. To avoid having your object get too big or small to see (or inverting, due to a negative scale factor), you are welcome to implement bounds on how large or small the object can be scaled along any axis. Note: This transformation involves anisotropic (i.e., non-uniform) scaling. Please see the comment about this in the Hints.

Camera

Your camera should be controllable by the user at all times. It should be able to translate parallel to the main axes of the floor (Think of the camera as being mounted on a dolly constrained to move left/right and forward/backward, but not up/down). The user should also be able to rotate the camera around an axis perpendicular to the floor, and to change the camera's pitch by rotating it around an axis that is parallel to the floor and perpendicular to the direction in which the camera is pointing. (These two rotational degrees of freedom are typical of what a physical video tripod would support.) The user interface you create for controlling the camera should constrain the range along which it can translate and the amount by which it can pitch, so that it can rotate < 90° up and < 90° down.

Hints

Before starting this assignment, please look at the Goblin XNA Tutorials, which can be found in your <GoblinXNA>/tutorials folder (where <GoblinXNA> is the full installation path for your GoblinXNA installation). Also, please read the user's manual located in the <GoblinXNA>/doc folder, and the documentation for the parts of the Goblin XNA API that you use.

Please pay attention to Jakob Nielsen's 10 Usability Heuristics. Your grade will be based in part on how well your assignment follows them. For example, consider the first heuristic: "Visibility of system status: The system should always keep users informed about what is going on, through appropriate feedback within reasonable time." An example of this would be having your application give appropriate feedback (e.g., a label or changing color) to indicate which object is selected.

A "key" to doing this assignment well is to think carefully about how you structure your scene graph. Which nodes should you use and how should they be arranged relative to each other? How should the transformations that you apply to your objects be composed to achieve the required effects?

Remember that lights are required in the scene graph in order to view your scene.

Objects that are outside the bounds established by the camera’s near and far clipping planes will not be visible. If you can't see an object, check to see whether it has been properly added to the scene graph, whether it's within the camera frustum (taking into accounts the near and far clipping planes), and whether it might be occluded by some other object.

A note about the model files. Some of the model files may have a scale that is larger than you would normally expect. When using the models in your scene graph, you may need to apply a scale transform to bring them down to a more manageable size. Tutorial 2 shows an example of how this is done.

If you find any bugs in Goblin XNA, for a quick response, please contact your TA (mengu@cs.columbia.edu) directly or post your problem on our discussion board in Courseworks.

And now a few (OK, more than a few) words about scaling. Recall that an object's surface normals are important in computing how the object is lit. When an object is rotated, its surface normals need to be rotated the same way.  When an object is uniformly scaled, its surface normals do not need to be scaled, but if they are scaled the same way as the object's vertices, each normal will still point in the correct direction. In contrast, the scaling transformation required for this assignment involves anisotropic (i.e., non-uniform) scale. When an object is scaled anisotropically, its surface normals must also be transformed; however, the necessary transform is not the transform used for the object's vertices.

As a simple example, consider a polygon in the y =x plane, which makes an angle of 45° with the −x axis.  Its surface normal, [1 1 0 0], which is perpendicular to the polygon, makes an angle of 45° with the +x axis. If that object is scaled anisotropically such that Sx = 2 and Sy = Sz = 1, it will be stretched so that it now lies in the y =−2x plane, making an angle of < 45° with the −x axis. However, scaling the surface normal by the same transformation yields [2 1 0 0], which makes an angle of < 45° with the +x axis, and thus is no longer perpendicular to the polygon! That's just plain wrong, and will result in incorrect lighting.

In general, the correct transformation for an object's surface normals turns out to be the inverse transpose of the transformation applied to the object's vertices. Note that in the case of rotation, the inverse transpose of the transformation is equal to the transformation itself. However, for scale, which is expressed along the main diagonal, the inverse transpose is, appropriately, just the inverse. Now, here’s one practical reason why this is worth knowing: while the BasicEffect shader provided in XNA Game Studio 4.0 does this correctly, the Basic Effect shader used up until XNA Game Studio 3.1 did not. In particular, it did not handle anisotropic scaling. While your work in this course, done on top of XNA Game Studio 4.0, will be fine, please note that anything done with Goblin XNA 3.x, will have this problem.

You are welcome to provide additional functionality beyond what is specified in the assignment. But, please get the assignment working to spec first.

What to submit

Your submission should include all of your code, any .x or .fbx files, your Visual Studio project files, and an executable copy of your program. Your submission should also include a README file with the following information:

  1. Your name and uni.
  2. A list of all of the files included in your submission.
  3. A description of your computer's OS type (e.g., Windows 7 32-bit or Windows 8 64-bit).
  4. Instructions for how to use your program, including information on how to start and stop actions, any controls bound to the keyboard, and anything else that isn't obvious from looking at the screen of your running program.
  5. Credit for any models not created by you.
  6. A list of any features not implemented or known bugs in your implementation.
  7. Any list of any bugs you found in Goblin XNA.

How to submit

Please compress all files in your submission into a single archive file named [UNI]_assn1.zip[.tar|.gz|.rar] where UNI is your Columbia UNI. Remember to include all of the items listed above.

Please verify that you can run your executable code by first extracting a copy of this archive to a location on your computer outside the directory tree where you did your development and then running your executable without any references to your development tree.

Submission will be done through CourseWorks. Here are the steps:

  1. Log into CourseWorks.
  2. Select Drop Box from the left hand navigation pane..
  3. You should see a folder with your own name (if you do not, please email the TA). Click that folder to go inside.
  4. From the "Add" drop down menu, select "Upload Files".
  5. Select the archive you prepared following the directions above and press "Upload Files Now".
     

Please try to submit before the deadline, since CourseWorks can sometimes become busy and slow.

Remember, you can only use a single late day on this assignment, so start early! And, have fun!