Introduction
In assignment 1, you developed a 2D editor, DSEdit, that
allowed you to design a top-down view of a scene. Now,
using the saved files from that program, you are going to develop a
program that will allow the user to drive a car through the
scene. Using the mouse, users will be
able to move through the scene and observe the effects of things like
lighting and texture; not to mention daytime and night time. You must
also render a car that can be driven around.
So, what you have to do is go from something like this:
to something like this:
Specification
You are to develop a program, called DSView, that renders scenes
created using DSEdit. In addition to supporting the file format used by
DSEdit, two additional shapes are supported in ds files:
What you get
You get something that includes the solution to assignment 1; but also
has a few additional files and modifications. It implements the
following functionality:
- Rendering of texture-mapped polygons (DSPolygons).
- Rendering of tree trunks.
- Movement of the car in a straight line, but not the turning of
the car.
The files added and/or included are:
- DSView (new file): The actual viewer
that renders the scene and interacts with things. Currently renders
polygons only using ambient light only. This is where you have to fix
things.
- DSShape.java (modified
file): Has a new abstract method, render3D(GL gl, GLDrawable glc) that all derived classes must implement.
- DSShapeList.java (modified
file): Has a new method, render3D(GL gl, GLDrawable glc) that calls render3D() on all the objects in the
list. Also includes some other functions you may find useful.
- DSPolygon.java (modified
file): Has a render3D() method added to it that renders (without
lighting) a polygon.
- Tree.java (modified
file): Has a render3D() method added to it that renders a tree.
- MyCar.java (new
file): Controls the car, and the drawing of the car.
There are other minor modifications here and there; but reading the
source code and understanding it is part of the assignment.
You also might find a few ds files to play with, some
of which may or may not be useful for testing ;-).
Try my solution:
% 3421
% cd /web/cs3421/09s2/assignments/dsview
% ./dsviewsol maps/view.ds
What remains to be implemented
The following things have to be added to the solution (in the order I
think is easiest):
- Modify solution so that you can use 'a' and 's' to control the
direction of the car and the car points in the direction it is
travelling.
- Adding foliage to the tree. The foliage of the tree is a sphere,
centred on the top of the trunk, whose radius is equal to the radius
of the tree.
- Add changing of viewpoints.
- Moving around using the mouse.
- Rendering signs.
- Rendering buildings.
- Rendering roads.
- Add daytime and nighttime settings.
- Enable additional light sources.
- Extensions.
Interaction
Your implementation of DSView should support the following behaviour
to keyboard presses.
- Pressing 1,2,3 and 4 switch the first, second, third, fourth
light on and off. These are toggle switches.
- Pressing the 'c' key switches from the "inside car" view to the
"outside car" view.
- Pressing the 'a' key turns the car left, 's' key turns right.
- Pressing the 'v' key should move to the next viewpoint that is
listed in the DS file. No animation of the move is necessary. The
view should cycle in order, coming back to the first view.
- Pressing 'd' switches from night time to day time driving.
- Pressing 'q' quits the program.
It should react in the following way to mouse movements: If any mouse
button is held down, then if the mouse is moved up, the viewer's
position should move forward in the direction he is facing (note
consequently that the point he is looking at changes). If the mouse is
moved down, the viewer's position should be moved backwards in a direction
opposite to the one he is facing. If the mouse is dragged left or
right, then the direction the viewer is facing should turn to the left
or right.
Appropriate rates of movement and turning should be set. However, the rate
should be independent of the viewer's position in the scene, so that
the behaviour is predictable.
3D shapes
The convention in 3D graphics is that the y axis points up and the
ground plane is y=0. That means that the 2D points in a DSShape
actually give the x and z coordinates in the 3D world.
For example, all DSPolygons lie in the ground plane, so the vertices need to be defined like this.
gl.glVertex3d(p.x, 0, p.y);
Roads should be assumed to be elevated 1 unit or so above the
DSpolygons. This is to ensure that roads appear in front of DSPolygons. The car
may be represented as a simple white rectangular prism.
Signs are rendered as vertical rectangles, the bottom of the sign is
at height 6, while the top is at the height given by the extra number stored in each DSSHape. The post holding up
the sign is a rectangular prism going from 0 to 6.
Trees are rendered as a cylinder (vertical) combined with a
sphere. The height of the trunk is given by the extra number. Code for rendering tree trunks is provided. You will have
to add code for rendering the sphere. The radius of the sphere is the distance between the two control pointws that define the Tree.
Buildings are rendered as four vertical rectangles with the height given by the extra number.
Lights and ViewPoints
Lights and ViewPoints are not visible by themselves, but affect how
the other shapes are drawn. The render3d method for these should do
nothing.
A Light represents a light source and is defined with one control point:
Light <red> <green> <blue> null 1.0 <height> 1 <x> <y>
red, green and blue represent the red green and blue intensities of
the light source, ranging from 0 to 255. null and 1.0 (texture and
texture scale) are ignored. This is a point light source at
[x,height,y,1]. Note that you must always give four numbers
(homogenous coordinates) when you tell OpenGL the position of a light.
There are a maximum of 4 light sources in any one scene.
A ViewPoint is defined by two control points. The first gives the x and z coordinates of the eye position,
while the second is the x and z coordinates of the look position. The extra number is the y coordinate of the eye position, while the y coordinate of the look position is always 10.
The up vector is (0,1,0).
Textures
Textures are to be applied to polygons and roads
as for assignment 1. The scaling factor defined in the DS file is to
be interpreted as follows: A scale factor of n means that there are n
repetitions of the texture in every 100 units along each axis (i.e. a
total of n*n actual repetitions per 100 units).
Textures for signs have a different meaning. A scale of 1 for a
sign means that there is 1 copy of the texture on the whole
sign. A scale of 2 means there are 2x2 = 4 copies of the texture
on the sign. If a sign is defined as (x1,y1)-(x2,y2) and the
scale factor is 1, then the point (x1, y1) has coordinates (0,0) in
texture space, and (x2, y2) has coordinates (1,0) in texture
space. This determines which side of the texture should be rendered on
the billboard. Surfaces are assumed to have the same textures on both
sides.
Textures on buildings are scaled so that they stretch from the
bottom to top. In the horizontal direction they are scaled as
for roads.
Trees don't need to be textured.
See the source code for
rendering polygons for an example of using textures.
Lighting
Lighting is to use the usual illumination model; with no light source
attenuation. All surfaces have no specular
component. Use Gouraud (GL_SMOOTH) shading for the shading model.
Constants
You can assume the following constants:
- The screen should have an aspect ratio of 1 and initial size of
400x400 pixels.
- Your field of view in the y axis should be 60 degrees.
- Daylight means that there is one directional (i.e. not point) light source
above the scene. Its intensity is 0.6 and is white in
colour and its direction is (-1,1,-1).
- The colour of the sky during daylight is: (0.6,0.6,0.9) -
i.e. sky blue.
- The colour of the sky during nighttime is: (0.1,0.1,0.1) - i.e
almost black.
Initial state
Initially, the system should start in the following state:
- It is daytime.
- All lights are on.
- We are in the car.
- The viewpoint is the first viewpoint described in the DS
file. If no viewpoint is defined use height
of 10 at position (10,30) looking at the point (110,130)
- The car is at (0,75) facing direction (1,0).
Command Line
Your program will be called DSView. It should be called from the
command line like:
% java DSView <ds file>
C++ version
You can use C++ if you prefer. There is a zip file of C++ code you can start with.
Marking, Submission, etc
The assignment will be marked out of 20.
Most of the marks are for implementing the various features, but there are six marks for programming style and documentation.
Markers will be allowed
to give up to 4 bonus marks for additional interesting features in the
viewer if a high level of accomplishment in the base assignment is
completed; hence it is theoretically possible (although unlikely) to
get 24/20 for this assignment. Examples of additional features likely
to get bonus marks would include things like :
- Animating transitions from one viewpoint to the next
- Creation of interesting DS files
(especially ones that illustrate your implementation's special
features)
- Creating more interesting trees (especially fractal ones).
- Creating a better car model (e.g. one with wheels, extra bonus
points for wheels that spin proportional to the speed the car is
going).
but you should not limit yourself to these. Use your imagination! Be
sure to document these features and how to use them in a readme.txt
file. You must submit a readme.txt -- if you haven't made any extensions just hand in an empty file. Extensions should not interfere
with the basic specification; if they do, you may lose marks.
If you think your extensions are really cool, submit your readme.txt like this:
% give cs3421 dsviewbonus readme.txt
I will look at all these and in the last lecture I will give a prize for the best one.
This assignment is due 11:59:59 on Sunday 11th October.
Submissions will be allowed up to 5 days late. For each day
late, you will lose 2 marks from your maximum possible base mark
(i.e. bonus marks are not included in late calculations).
If you do change a file, please leave a comment at the top of the
file saying something like: /** THIS FILE HAS CHANGED **/ so it
indicates to the marker that they should take a careful look at
it. Also, within your source, it would make the marker's job easier if
you indicated where you had changed files; again, through marking new
functions with /* NEW FUNCTION*/ or something like it as appropriate.
Submit ALL the files required for your assignment to run DSView
correctly. Do NOT submit any java files that are NOT required for your
assignment to compile and run. They will break the marking system. If
javac *.java does not work, then the assignment marking system will
break and it will delay the marking and return of your assignment.
Hand in the Java classes, your readme.txt file and any other files
related to extensions you have written using give:
% give cs3421 dsview <files>
Please do not hand in textures or ds files that were included in the
distribution.
Hints
- Make use of the code that is given to you in assignment 1. You
can choose to either use your assignment 1 solution or start from the
source code given to you.
- In assignment 1, textures did not to be lit; hence texturing with
GL_REPLACE mode made sense. But for this assignment, GL_MODULATE is
appropriate. This also means that the colour of the material should be
set to white. Have a look at DSPolygon.
- Make sure your surface normals are correctly calculated. This
especially matters when doing lighting. Note that if the normal and
the right-hand rule produce different values, then OpenGL will not
light the polygons directly.
- You need to get things in the right planes and directions. In
Assignment 1, DSPolygons would go in the xy plane. But in the case
of a walk-through, DSPolygons belong in the xz plane. You could
rotate everything, but that gets messy. It's much easier to treat
things as simply using the y value for the z value.
- Two sided lighting is appropriate for this assignment. The OpenGL
command for enabling two-sided lighting is:
gl.glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
But you have to be careful with two sided lighting. Make sure that the
normal points in the correct direction; and more so, that it points in
the direction that using the counterclockwise convention (i.e. using
the right hand rule) predicts. If you do so, only one side of a
polygon will be lighted. This is the correct behaviour. The trick is
to get the right side (the one facing the light source) to be lit.
- It is acceptable for the car's velocity to alter with different
speed computers; hence you can change its position on the basis of the
current frame. You do not have to time it at a particular
rate. Generally, the rendering speed should be 30 fps. This can be accomplished with
Animator animator = new FPSAnimator(glc,30);
animator.start();
The animator will call DSView's display(...)
function over and over again.
- An easy way to find the normal to a polygon is to take the cross
product of the first two edges of the polygon. This works, provided
the user hasn't "double clicked" on a corner, and so one side has
length zero. You do not need to worry about this case.
- Although Lights are DSShape objects they have to be handled differently from other
objects. Light sources must be created and/or enabled before the rest
of the scene is rendered, otherwise they will only illuminate the objects that
appear after them in the file.
- My solution reacts to the button "p", which attempts to output a
Viewpoint for the current view. (This isn't always possible.)
You
can use this to generate Viewpoints, or define them with DSEdit. (Note that it produces ONE
possible position to look at. There are many points that when looked
at produce the same output. What's important is the view
direction -- the direction of the vector from the view position
to the position being looked at. Its length does not matter, only the
directions.
Ambient light should be the OpenGL default of (0.2,0.2,0.2). If your
code doesn't change it explicitly, then it will be this value
anyway. The code you are given has it set to a particular value so
that you can see the scene before you implement lighting. Once you
have implemented lighting, you should modify and/or remove the line.
Getting left and right mouse movement working when the height of
the viewpoint and the height of the point being looked at are
different can be tricky, so you don't have to worry about it -- your
code will only be tested for mouse left/right movement with files for
which the height of the eye and the height of the lookat point are
identical. You can also assume that the lookat point is not directly
beneath the eye. In other words, if the viewpoint line is:
ViewPoint 255 255 255 null 1.0 10.0 2 78.9 85.3 79.8 85.3
Viewpoint 0 0 0 null 1.0 <eyeheight> 2 <eyex> <eyez> <lookx> <lookz>
Then for the purposes of left/right movement (and only for that
purpose, your assignment should work in all other regards in this
situation), you can assume eyeheight=lookheight. Further, you can
always assume that the situation where eyex=lookx AND eyey=looky will
never occur.
More hints can be found in the FAQ.
Please post questions about the assignment to the forum instead of emailing them.
cs3421 @ CSE @ UNSW