| CS306 |
Processing Systems and Structures |
Lockwood, Spring 2002 |
Machine Problem 5:
The Maze (Part III: 3D-View)
| Assigned |
Monday, March 25, 2002 |
| Due Date |
Tuesday, April 9, 2002, Midnight |
| Purpose: |
Video Graphics and image algorithms
|
| Points | 50 |
Introduction
In this machine problem you will add a 3-dimensional view of the
MP3/MP4 maze that allows viewing the maze from the point-of-view of the mouse
in the maze. From MP5, you can switch to graphics mode by hitting the 'g' key.
The following image is a screen-dump of the running program:
The internal representation of the maze is the same as it was for MP3.
From MP5, you can switch back to the two-dimensional viewpoint by hitting
the 't' key. The following diagram is a screen-dump of the
corresponding view on the 2-dimensional maze.
The mouse is looking East. Note that there is are two hallways to the right
and one hallways to the left. Also note that the colored decision points
appear in both viewpoints.
Implementation
A 3D perspective can be implemented by placing
a vanishing point in the center of the screen.
Objects at an infinite depth would be located in the center of the screen
and have a height of zero.
Objects at each depth
become larger by scaling their size by a constant.
Rectangular objects can be represented by drawing simple geometric shapes
that follow the diagnonal, horizontal, or vertical guidelines. A back
wall, for example, can be represented by a rectangle. A sidewall can
be represented by a trapezoid.
To avoid time-consuming multiplication, arrays can be defined that
contain pre-calculated positions and sizes of an object
at each depth. Due to the limited resolution of a video screen
these arrays can be small. Once the size of an object is less
than the size of a pixel, there is no purpose in plotting it on the screen.
For this machine problem, we will be using a screen resolution of 320x200
pixels. At this resolution, it is possible to render full-motion
video with hundreds of frames-per-second on a Pentium-III
class computer (such as those in our lab).
Two arrays will be defined at this resolution:
one to hold pixel coordinates and the other to hold object sizes.
The sizes of the arrays are defined by the constant MAXDepth3d.
The array P3d holds the top-left position of a 3D element
at each depth. The array X3d holds the size of a 3D element.
To nearly fill the screen and preserve simple X/Y scaling values; we
will choose an aspect ratio of 2:1. The diagram above shows the
coordinates and size of a back wall and two side walls at a given depth.
The rendering algorithm begins from the most distant point down
the hallway. At this depth, a rectangle is drawn to represent
the back wall. At each decreasing depth level, rectangles and
trapezoids are drawn to represent ceilings, floors, walls,
and hallway openings.
The 3-D routines of MP4 interface to MP3 by a single procedure.
UpdateGRScreen is called instead of UpateTextScreen when
the program is in graphics mode. Maze elements are drawn
by looking down a hallway in the direction that the mouse is facing.
This machine problem is limited to displaying mazes
with hallways that are no more than one unit wide.
You are encouraged to use your MP3 and MP4 routines in MP5.
There is, however, no penalty for using library versions
of the MP3 and MP4 procedures.
Procedures
- DrawBox
- Purpose: Draw a filled rectangular box on the screen.
- Inputs
- DX: Starting Position of box (specified as offset from zero)
- CX: Width of box (number of horizontal pixels)
- BX: Height of box (number of vertical pixels)
- AL: Color
- Outputs: Writes to screen
- Registers: Preserves any that are modified
- Assumptions: The width of the box is a multiple of two.
- Notes: Invoking the main program as 'mazec test' will call
the _TestGeometry routine.
- Description:
This routine draws a filled rectangular box on the screen. The
starting position is determined by DX. DX is specified as
an offset from the starting location of the video page
(i.e., DX=320*y + x). You may optimize your code with the assumption
that the width will always be a multiple of two (i.e., an even number).
- DrawTrap
- Purpose: Draw a filled trapezoid on the screen
- Inputs:
- DX: Starting Position of trapezoid (specified as offset from zero)
- CX: Width of box (number of horizontal pixels)
- BX: Height of box (number of vertical pixels)
- AL: Color
- AH: Direction (0=Left, 1=Right)
- Outputs: Writes to screen
- Registers: Preserves any that are modified
- Assumptions: The width of the trapezoid is a multiple of two.
- Notes: Invoking the main program as 'mazec test' will call
the _TestGeometry routine.
- Description:
There are two types of trapezoids that we need to draw for this
machine problem -- Left-sided and Right-sided. This subroutine should
perform either as determined by the value in AH. The starting position
refers to the top-corner of the object, as shown below. The height
refers to the total height of the object. The slanted lines for this
routine will have a fixed slope of 2:1, i.e., the line advances two
horizontal pixels for each vertical pixel. The sloped line continues
until the object has reached full width.
- DrawBackWall
- Purpose: Draw the solid wall at the end of a hallway.
- Input: SI: Depth of Wall
- Outputs: Writes to screen
- Registers: Preserves any that are modified
- Uses: DrawBox, P3d, X3d
- Constants: GREENBR
- Description:
The back wall is a rectangular box in the center of the screen
that represents the wall at the end of the hallway.
The depth (SI) of the wall refers to the distance between
the position of the mouse and the location of the wall.
As the mouse moves further from a wall, the size of the wall
decreases.
The size and position of the box can be calculated as
a function of the depth (SI), the position array (P3d), and the
size array (X3d).
Note that the back wall is located at one depth greater than the value
of SI. The color of the back wall should be bright green
(as defined by the constant: GREENBR).
- DrawSides
- Purpose: Draw sides of the hallway to represent walls or openings
at a given depth.
- Input: SI: Depth of Wall
- Outputs: Writes to screen
- Registers: Preserves any that are modified
- Uses: DrawBox, DrawTrap, P3d, X3d, Side3d[SI]
- Constants: GREEN, GREENBR, LSW, RSW
- Description:
This routine draws the walls or openings along the left and right
sides of the hallway at a given depth (SI). If there is a wall along
a side, this routine will draw a green trapezoid.
If there is an opening,
the routine will draw a bright-green (GREENBR) rectangle. The presence of
a sidewall can be determined by testing the value of Side3d[SI] with
LSW and RSW.
The sidewalls appear trapezoidal because of the 3D perspective.
The side of wall closer to the mouse appears larger than the side of
the wall that is further. The absolute size and position of the sidewalls
is determined as a function of the position and size arrays
(P3d and X3d).
Recall that
the position of a right-trapezoid is given by the location of its
top-right corner.
Openings appear as narrow rectangles because the
the mouse views them from at a head-on perspective. As with the back wall,
they are colored bright green to indicate direct illumination.
Because hallways are limited to a single-unit width, it is not
necessary to extend the width of an opening to the far side of the screen.
It is safe to assume that the sidewall at the next level (SI-1) will
draw on that region of the screen.
- DrawFloorCeiling
- Purpose: Draw ceiling and floor at a given depth.
- Inputs: SI: Depth
- Outputs: Writes to screen
- Registers: Preserves any that are modified
- Uses: DrawBox, P3d, X3d, View3d[SI]
- Constants: GRAY, BLUE, GREEN, RED, YELLOW
- Description:
The "ceiling" refers to the blue sky above the maze.
The "floor" refers to the gray concrete tile on the ground.
This routine draws two narrow horizontal rectangles to represent
the visable portion of these elements at depth SI.
To represent colored decision points and the endpoint of the maze,
crosshairs may be drawn on the floor. If the value of View3d[SI]
is DECPOS, VISPOS, FINPOS, or ENDPOS, a BLUE, GREEN, RED, or YELLOW
crosshair should be drawn on the screen.
The width of the crosshair should be one-half that of
the width of the floor tile. The height of the crosshair should be
the full hight of the floor tile.
- DrawGRScreen
- Purpose: Draw the graphic screen
- Inputs: SI: Maximum Depth
- Uses: DrawBackWall, DrawFloorCeiling, DrawSides
- Registers: Preserves any that are modified
- Description:
Now that you can draw walls, ceilings, floors, sidewalls, and openings,
it is surprisingly simple the draw the entire graphics screen. Starting
at the depth of the furthest wall (given by SI), this routine first draws
the back wall then draws then calls DrawFloorCeiling and DrawSides for
represent the view at each depth closer to the mouse. Upon finishing
this routine at depth=0, the entire screen should be filled with
the 3d view of a hallway.
For testing purposes, you may wish to test your routines by initializing
View3d and Side3d with sample values, setting SI to the depth of your
hallway, and calling this routine.
- UpdateGRScreen
- Purpose: Interface to existing maze program
- Inputs:
- DI=current position maze
- AL=current direction
- Reads Variables:
- [View3d+offset]
- [Side3d+offset]
- [w3d+offset]
- Calls: DrawGRScreen
- Registers: Preserves any that are modified
- Constants: MAXDepth3d, LSW, RSW
- Description:
This procedure is the 3d-equivalent of UpdateTextScreen.
This single routine is the interface between the existing code in MP3
and the new 3d view created by this machine problem.
As before (with UpdateTextScreen), DI holds the current position in _MAZE
and AL holds the current direction.
By examinging the contents of _MAZE in the direction of AL, this routine
fills in the values of the arrays View3d[] and Side3d[]. This routine
first loads View3d[0] with _MAZE[DI]. For each value of _MAZE in
the direction of AL, View3d is loaded with the value in _MAZE until
hitting a wall or reaching MAXDepth3d (a constant which determines
how far the mouse can see).
For each element in the View3d array, a corresponding byte is stored in
Side3d array. The Side3d array refers to whether or not the element
to the left or right of the maze contains a wall or a opening (a hallway).
Each element of Size3d should be initialized to zero.
If there is a
wall to the left of the current position,
the element in Side3d should be OR'd with the constant
LSW (Left-Side-Wall).
Likewise, if there is a
wall to the right, the element in Side3d should be OR'd with
the constant RSW (Right-Side-Wall).
Now that the views have been initialized, set SI to the depth of
the furthest wall (or MAXDepth3d if you are looking down a really long
hallway) and call UpdateGRScreen to finish your machine problem.
Debugging Process
The program includes procedes to help you incrementally
develop and test your code.
The TestGeometry procedure
is executed when the program first begins.
The procedures renders a box and two trapezoids
on the screen, as shown below.
The source code to TestGeometry, which
calls the DrawBox and DrawTrapezoid procedures,
is given below:
|
TestGeometry:
; Geometry Test Cases
PUSH AX
PUSH BX ; Save Registers
PUSH CX
PUSH DX
GMODE ; Switch to 320x200 Graphics-Mode (MACRO)
; --- Draw a Rectangular Box at the center of screen ---
mov AL,REDBR ; Color=Bright RED
mov dx,160-10 + 320*(100-10)
mov cx,20 ; 20 Pixels Wide
mov bx,20 ; 20 Pixels Tall
call DrawBox ; Width unchanged
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
; --- Draw a Left-Sided Trapezoid at left of screen ----
mov AL,YELLOW ; Color=YELLOW
mov dx,160-32 + 320*(100-20) ; Position
mov bx,40 ; 40 Pixels Tall
mov AH,0 ; Left-Sided trapezoid
call DrawTrap ; Width (CX) unchanged
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
; --- Draw a Right-Sided Trapezoid at right of screen ---
mov AL,BLUEBR ; Color=Bright Blue
add dx,32*2 - 2 ; Position (with -2 correction)
mov AH,1 ; Right-Sided
call DrawTrap ; Width (CX), Height(BX), and Color(AL) Unchanged
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
; --- Wait for a keypress while we look at the screen ---
TMODE ; Switch back to 80x25 Text-Mode (MACRO)
POP DX
POP CX
POP BX ; Restore Registers
POP AX
ret
|
The TestDrawWallsAndSides procedure
is executed next.
This procedures shows how the
DrawBackWall and DrawSideWall routines
operate. Each are given a value for the depth in register SI
and use the [P3d], [X3d], and [w3d] arrays to determine where
the actual box and trapezoids should be drawn on the screen.
The image below shows the back wall at a depth of 6, and all of
the sidewalls at levels: 6, 5, 4, 3, 2, 1, and 0.
The source code to TestWallsAndSides is given below:
|
TestDrawWallsAndSides:
GMODE
MOV SI, 6 ; Set Level to 6 (Wall is far away, appears small)
Call DrawBackWall; ; Draw a back wall at depth of 6
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
; Pre-load the Side3D matrix with sample values.
Mov byte [Side3d+6], LSW | RSW ; Both side walls at depth=6
Call DrawSides ; Draw side walls at depth of 6
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
; Pre-load the Side3D matrix with sample values.
Mov byte [Side3d+5], 0 ; Open walls at depth=5
Mov byte [Side3d+4], LSW | RSW ; Both side walls at depth=4
Mov byte [Side3d+3], RSW ; Rigth side wall at depth=3
Mov byte [Side3d+2], LSW | RSW ; Both side walls at depth=2
Mov byte [Side3d+1], LSW ; Left side wall at depth=1
Mov byte [Side3d+0], RSW ; Rigth side wall at depth=0
; Usually, the values of Side3D are re-generated by reading
; the variables _MAZE, _POS, and DIR
MOV SI,5
TestDrawMore: ; Draw the rest of floors and ceilings
Call DrawSides; ; Draw side walls at a depth of 5
KEYWAIT ; Wait for a key to be pressed, quit if 'q' or 'Q'
DEC SI
CMP SI,0 ; Loop through depths of 5,4,3,2,1,0
JGE TestDrawMore
TMODE
ret
|
Points
You earn points by replacing each subroutine with your own code.
Your score will be proportional to the percentage of the code that
your write yourself. The breakdown in points is given below. Your
routine MUST perform all functions of the subroutine to receive credit.
You are urged to test each routine as you write it. It is nearly
impossible to debug a program if there are errors in the routines
that it calls.
You can earn two points by demonstrating that your program, in graphics mode,
at delay=0 can use AutoSolve to find the solution as fast as or faster than
Lockwood's code (recall that the library code purposefully contains
extraneous code).
You will earn 1 point if your code is no more than 25% slower.
Benchmarks will be done in the lab
using the Pentium computers at the time you demonstrate your MP.
- DrawBox: 7 pts
- DrawTrap: 8 pts
- DrawBackWall: 5 pts
- DrawSides: 7 pts
- DrawFloorCeiling: 8 pts
- DrawGRScreen: 5 pts
- UpdateGRScreen: 8 pts.
- Performance: 2 pts
Starting Files
You will begin MP3 with the following files:
- MP5.EXE: A fully functional executable
program using library routines
- MAZE.DTA: The maze definition file.
- MP5.ASM:
A starting point for the program. You are given
the routines for reading and processing keyboard input, calling
the other functions, and delaying movement.
(Add your routines here and comment out the Library Calls)
- BUILD.BAT: A short batch program which compiles, assembles, and links
the programs.
- LIB306.LIB: The standard ECE291 library routines.
(you can always use these routines freely)
- LIBMP.LIB: Library versions of the six routines that you need to write. Note: The library used for MP5 has been revised.
Do not use the library that was included with MP3.
- MP5.ZIP: Download that contains
all of these files above.
Major Updates to MP5.ASM from MP3.ASM and MP4.ASM
(Full changes appear in mp5.asm, which is included in the
downloadable zip file)
; You Name Here : ____________________________________
; CS306: Machine Problem 5, Spring 2002
; The Maze (Part III : 3D Graphic View)
; Prof. John W. Lockwood
; Washington University, Department of Computer Science
; Ver. 2.1
; ================ Constants / Definitions / MACROs =====================
TEXTMODE EQU 0
GRMODE EQU 1
; Video Memory Segments (Store in ES)
VIDTEXTSEG EQU 0B800h ; Text-mode video (for the maze of mp3/mp4)
VIDGRSEG EQU 0A000h ; Grahphis video (for the 3d maze of mp5)
; New, for MP5: Predefined Palette Colors (default palette in Mode 13h)
RED EQU 4
REDBR EQU 8+4
; Bright RED
GREEN EQU 2
GREENBR EQU 8+2
; Bright GREEN
BLUE EQU 1
BLUEBR EQU 8+1
; Bright Blue
CYAN EQU 3
GRAY EQU 8
; Color for the ground (concrete)
YELLOW EQU 8+6
; Bright RED+GREEN = YELLOW
MAGENTA EQU 5
; RED+BLUE
; Constants for Side3d Array
LSW EQU 10000000b ; Left Side Wall
RSW EQU 01000000b ; Right Side Wall
LRSW EQU 11000000b ; Left & Right Side Wall
; Maximum depth of 3d-view
MAXDepth3d EQU 9
; ================== GLOBAL Variables & Procedures ======================
; Global Variables (available to library code)
GLOBAL Side3d
GLOBAL View3d
;====== Begin Code/Data ===================================================
VidMode db TEXTMODE ; Can be TEXTMODE (default) or GRMODE
; --- New Variables for Mp5 ---
; An array that defines the type of elements at each distance
; while looking forward down a hallway.
; The array is initialized with sample values, but will need
; to be updated for every new view.
View3d db HALL,HALL,HALL,HALL,HALL,HALL,HALL,HALL,HALL,HALL,WALL
; An array that defines the type of side walls at each distance forward
; while looking forward down a hallway.
; Each element can be: 0 (No Left wall, No Right Wall)
; LSW (Left Side Wall)
; RSW (Right Side Wall)
; LRSW (Both Left and Right Side Wall)
; The array is initialized with sample values, but will need
; to be updated for every new view.
Side3d db LRSW,LRSW,LRSW,LRSW,LRSW,LRSW,LRSW,LRSW,LRSW,LRSW,LRSW
; An array that defines the locations of points at various depths
; Each value indicates the starting point for the back wall at each depth.
; For example, the first element of the array has value 0.
P3d dw 0
dw 20+320*10
dw 20+30+320*(10+15)
dw 20+30+24+320*(10+15+12)
dw 20+30+24+20+320*(10+15+12+10)
dw 20+30+24+20+16+320*(10+15+12+10+8)
dw 20+30+24+20+16+14+320*(10+15+12+10+8+7)
dw 20+30+24+20+16+14+12+320*(10+15+12+10+8+7+6)
dw 20+30+24+20+16+14+12+10+320*(10+15+12+10+8+7+6+5)
dw 20+30+24+20+16+14+12+10+8+320*(10+15+12+10+8+7+6+5+4)
dw 20+30+24+20+16+14+12+10+8+4+320*(10+15+12+10+8+7+6+5+4+2)
dw 20+30+24+20+16+14+12+10+8+4+2+320*(10+15+12+10+8+7+6+5+4+2+1)
; See the diagram in the writup.
; Size of a wall for each depth level.
; See the diagram in the writup.
X3d dw 160,140,110, 86, 66, 50, 36, 24, 14, 6, 2
; Width of a sidewall trapezoid at for each depth level.
; Values equals difference between [X3d+index] and [X3d+index+1]
w3d dw 20, 30, 24, 20, 16, 14, 12, 10, 8, 4, 2
; ================= Procedures (Your code goes here) ====================
DrawBox:
Call LibDrawBox ; Replace this with your own code
ret
; ------------------------------------------------------------------------
DrawTrap:
Call LibDrawTrap ; Replace this with your own code
ret
; ------------------------------------------------------------------------
DrawBackWall:
Call LibDrawBackWall ; Replace this with your own code
ret
; ------------------------------------------------------------------------
DrawFloorCeiling:
Call LibDrawFloorCeiling ; Replace this with your own code
ret
; ------------------------------------------------------------------------
DrawSides:
Call LibDrawSides; Replace this with your own code
ret
; ------------------------------------------------------------------------
DrawGrScreen:
Call LibDrawGrScreen ; Replace this with your own code
ret
; ------------------------------------------------------------------------
UpdateGrScreen:
Call LibUpdateGrScreen; Replace this with your own code
ret
; ------------------------------------------------------------------------
UpdateScreen: ; This code is given to you for free
; For MP5 it has been expanded to support both
; Video Modes (Text mode or Graphics Mode)
CMP byte [VidMode], GRMODE
JE UpdateGMode
; TextMode
call UpdateTextScreen
ret
UpdateGMode: call UpdateGrScreen
ret
; ------------------------------------------------------------------------
..start
MOV AX,CS ; Set Code Segment = Data (Default) Segment
MOV DS,AX
MOV AX,VIDTEXTSEG ; Use extra segment for Text mode video
MOV ES,AX
MOV AX, stkseg ; Stack segment
MOV SS, AX
MOV SP, stacktop
; BODY OF MAIN PROGRAM BEGINS HERE!
Call TestGeometry
; Call mpxit ; Uncomment if you need to debug Geometry only.
Call TestDrawWallsAndSides
; Call mpxit ; Uncomment if you need to debug Draw routines only.
Call ReadMazeFile ; Read in the contents of the maze
call MarkDecisionPoints
TMODE ; MACRO to switch to text mode video
Call ShowMaze ; Display original maze and mouse on screen
Call ShowMode ; Display mazemode and mazedelay values on screen
MOV SI, [_POS] ; Store position in register SI
MOV DI, [_POS] ; Store position in register SI
Call _MazeManual
Call mpxit ; no RET opcode needed for this procedure.
; mpxit will terminates the program.