A Simple CAD program

CS490 Spring 1998

by Hubert Siu
 Design View pic Model View pic

Introduction:

    3D graphics has gained a lot of importance in the past few years, especially in design, modelling, and gaming.  The purpose of this project is to make use of OpenGL libraries and MFC (Microsoft Foundation Class) libraries to create a 3D graphics application--a simple CAD program.  This application allows a user to design a house in a 2D space, while able to view the 3D model on another window at the same time. 

Process:

1. Background:

   Before starting on the project, I went through a few tutorials on MFC and OpenGL.  A good tutorial for starting with MFC is the Scribble tutorial that comes with Visual C++.  This tutorial helped me to understand how to build an application with all the basic requirements: load and save files, controlling the mouse, select from menu and toolbar, create dialog boxes, draw within a window, and more.  OpenGL tutorials could be found online, and I went through the tutorials that can be found at DevCentral.  These tutorials and sample programs gave me a good idea on a lot of essential part of the project: setting up the device context for OpenGL graphics, drawing 3D objects with lighting effects, setting up camera view on the 3D model, etc.  Some other techniques, like texture mapping and optimizing the code for rendering speed, could be found in some reference book. 

2. The Interface: 

    After deciding to use a link list as the data structure for storing information, I started to modify the skeleton code generated by MFC AppWizard. BaseThe first task I planned to achieve was to edit the code so that I can only have a single document open at a time while have 2 different views, with one for designing and one for displaying the 3D model.  I used the project manager to generate a multiple document interface (MDI), but diable the property of opening more than one file; instead, 2 views were created when a file is opened or created instead of 1.  The next thing I had to do was to set up the drawable area (which is the base for the design) with the grid lines in the design view and prepare the rendering context for displaying the 3D object in the model view.  Mouse control was added afterwards so users can rotate the base in the model view. At this point, the camera in the model view is fixed at the origin with the up vector = (0, 1, 0), with viewing angle = 30 degrees.  Basic menu items are inserted, but they do not provide any function at this point. 

3. Room 

    The next step was to enable users to draw their own design.  The first element that was implemented was the room. RoomThe room is derived from a base class called CElement, which is derived from CObject (defined by Microsoft).  The purpose of using CObject as the base class was because its member function Serialize reads and saves the document data upon slight modification.  A draw member function is added to CElement for drawing the object in the design view, and the coordinates are stored in a new element in a pointer array.  The device context object (CDC) provides member functions for drawing, such as LineTo and Rectangle, and these functions were used to draw objects on the design view.  Different kinds of pen can be chosen to color the object.  While dragging, the pen style was set to PS_DOT and was changed to PS_SOLID when an element is created so that dotted lines and solid lines can be drawn depending on the condition.  Once the design frame was capable of drawing rooms, I started to work on the model view.  The coordinates for each rooms are stored under an array inside the document, and the model view loads the values once the user has defined a new room.  8 polygons are used for each room.  Light position was adjust to make shade obviously in all orientation.  Restrictions are applied so that a room cannot overlap another room.  The height of the room is also fixed. 

4. Door

    Door and window are the next two elements that were added.  Their sizes are fixed, because for rendering same objects in OpenGL, displayDoors and Windows lists can be used to improve performance.  Both door and window elements also have CElement as their base class.  2 polygons are used for each element.  The window and door drawing functions for the design view were added, as well as their own Serialize and draw member function.  The pointer array that stores the room element is also used to store new door and window elements.  When creating a door or a window, a small box with dotted line is created when the left mouse buttons is down.  A door or window will not be created if that box does not intersect any of the room element in the link list, nor it will be created if the element intersects with a door/window element in the list.  If the element selected is successfully created in the design view, it should also appear in the model view instantly. 

5. Transparent

    Before addding the roof component, a transparent function for the 3D model was added.  This was done by changing the alpha Transparencycomponent to a value smaller than 1 and enabling blending.  The color of a pixel is the combination of source color based on the alpha value and the destination color based on the value of (1 - alpha value).  Transparency will not show up until the program enables the blending function.  The screen shot on the right was taken when the camera was located on the bottom of the model, below the base.  A button on the tool bar allows the user to toggle between on and off for transparency.  The speed will be decreased when transparency is on, since more calculation has to be performed.  Note that there is a big difference in performance between turning off the blending function and setting the alpha value of 1. 

6. Roof

   The next element that was added to the program was the roof.  Before a roof element was inserted, the program would go through theRoof link list and make sure that a room was located right underneath the current location of the roof.  If the program found a room under its current location, a dialog would pop up and asked the user to pick one of the 12 types of roof.  When creating the roofs in the model view, the normal for the top of the roof are all different, therefore each normal has to be calculated.  This was done by finding the diagonal of the roof, and used this value to normalize the 2 components (x or z, and y) in the normal vector so that it will always have a magnitude of 1 (see below).  This would provide correct lighting and shading for the roofs. 
               normalizex = sqrt(height*height + (0.5*abs(right-left))*(0.5*abs(right-left)) );
               glNormal3d(0.0 , height/normalizex, -0.5*abs(right-left) / normalizex);

7. Delete

   At this point, only the last element inserted into the design could be deleted.  A delete function was implemented so that whenever the user selects an element with the cursor, the element can be deleted.  All elements can be deleted by selecting them and hit the delete button except for the room, which the user has to make sure that there are no other elements, such as doors, windows, or roofs, associated to it. A search on the link list will be performed to ensure that the room is not connected to any of these components. 

8. Viewing Mode 

    Another model viewing mode was added after the implementation of delete, and that is virtual walk-through.  The camera can now be moved Walk-througharound in 3D space, with the up-vector always pointing up.  When the walk-through mode is enabled, user can move forward, backward, turn right, left, up and down.  The restriction is that the user can only move towards the direction that he/she is looking at.  At this point, there is no restriction on where the camera could be.  It can therefore travel through walls and windows, and clipping might occur.  Also, the current viewing angle is set to 30, so a slight fisheye effect exists. 

9. Optimization

    After I was done with the walk-through mode, I started optimizing the code.  A lot of floating point calculations were reduced after optimization, and I used the command glHint to optimized the speed of rendering.  The difference was quite obvious, especially when the window size is large. 

10. Help files 

    Help files were the last part that I worked on.  I experienced problem compiling the help file initially because the help compiler is 16-bit and it has problem reading the afxcore.rtf file.  This problem can be fixed by obtaining a 32 bit compiler or converting the rtf file into 16-bit format.  These programs are available online and could be found on www.shareware.com

Result:

1. Instructions

   The program has been tested and all functions seem to work properly.  Here are some basic instructions for designing a model: 
  • To select an existing element on the design view, click on the  button on the toolbar.  Click on any element within the design view with the left mouse button.
  • To create a room, click on the Toolbar room button on the toolbar.  With the left mouse button down, drag on the grid and release the button when the desired size is achieved. 
  • To create a door, click on the Toolbar door button on the toolbar.  A dotted box would appear when left mouse button is held down.  Drag the box to a place where it intersects with one side of a room; then release the mouse button. 
  • To create a window, click on the Toolbar window button on the toolbar.  Follow the same steps as in creating a door. 
  • To create a roof, click on the Toolbar roof button on the toolbar.  Follow the same instructions as in creating a room, except that the final rectangle must intersect with a room.  A slope dialog would pop up.  Select 1 of the 12 different slope directions:  Selection from the first column gives you roofs of type I; selection from the second column gives you roofs of type II; and selection from the third column gives you type III roofs.
  • Slope dialog Type 1 Type II Type III
    Slope Dialog
    Type I, For side
    Type II, For corner
    Type III, For corner
  • To enable transparency, click on the Toolbar transparent button on the toolbar. 
  • To change to normal mode in the model view, click on the Toolbar normal mode button on the toolbar. 
  • To change to walk-through mode in the model view, click on the Toolbar walk through button on the toolbar. 
  • To rotate the model in normal mode, hold down the left mouse button and move around.
  • To move around the model in the walk-through mode, use 5 for forward, 0 for backward, 4 for left, 6 for right, 8 for up and 2 for down.

2. Performance

    Testing were done on a Dell 300MHz Pentium II with 8Mb video RAM.  With a mid-size model, rotation on the model was very smooth with the viewing area approximately equal to 576 x 432.  The frame rate decreased to approximately 4-5 frames/second when the transparency was turned on.  With the viewing area approximately equal to 288 x 216, turning on the transparency decreased the frame rate by a little, but it was still above 10 frames/sec.  With the whole base filled up with rooms, the frame rate decreased to approximately 7-8 frames/second, with the size of the viewing area equal to 576 x 432.  When transparency was on, the frame rate drops to 1frame/second with the same viewing size. 

3. Bugs and Problems

    The program didn't turn out to have a lot of big problems, though minor problems exist.  One problem with the design view was that when the user needs to draw a room that has a larger size than the viewable area, the screen will not scroll down automatically. 

    Another problem with the design view was that random dots appear on the screen once in a while during dragging operations.  This rarely happens, but it is a little annoying to users.  I was examining my code and tried to find out what I did wrong, but I did not find any major problem with my code.  I then tried to drag rectangles on the desktop and in other windows, and I noticed that the same problem occurs.  My conclusion for this problem was that this might be a bug in windows. 

    The main problem for the model view is clipping when the user is in the walk-through mode.  Some algorithms could be applied to eliminate this problem, but I haven't come up with a good solution at this point. 
 
    Texture mapping was originally added to the program.  Users were allowed to define a wallpaper for the rooms.  The fucntion was taken off after transparent function was added due to the effect on rendering speed.  When both texture mapping and transparency was on, the rendering speed was extremely slow.  Since this is a design program, the ability to see all the rooms seems to have a higher priority then the ability of making nice looking rooms, therefore texture mapping option was taken off. 

4. Improvements

    The program is fully functional, but improvements can be made.  First of all, a resizing function should be added so that the size of the roof and room can be altered.  Another improvement is to allow designs to have multiple stories.  This will include 2 extra elements, at least, which will be stairs and floor.  A better version of walk-through will be only allowing the user to walk from one room to another through a door, instead of going through walls, windows and roofs.  The ability to allow users to define their own door and window size or style would also be a nice feature. 

Program:

A copy of the program with help file and the source code are available here.  A sample file is also included with the program.  Currently, only NT version is available.  Please send all comments and suggestions to hys2@cornell.edu.  Thanks! 
Last modified: May 1998