loading

My Autodesk Maya student licence expired recently. So I did what anyone would do, build my own 3D CAD software (beware Autodesk).

So I started writing my application in C++ using OpenGL, SDL and in about a week, this was the result.

Some of the (few) features:

1) The big viewport offers a perspective view your 3D realm

2) The bottom two viewports offer front and side view

3) you can undo any mistakes (sort of)

4) the object can be scaled in all the x, y and z coordinates independently or all at the same

5) You can take a screen shot of your masterpiece

As you can see this is a very basic and limited application, in this application I will be explaining my process of building the application and how I used OpenGL to achieve this.

About this instructable: The goal of this instructable is to introduce beginners to the exciting world of Computer Graphics and OpenGL. This instructable is written to provide the quick and simple to follow steps I used to create a very basic CAD application.

I have used no OOPs concepts and I have tried to keep programming as basic as possible, but basic knowledge of C++ is required. But if you have any doubts, please feel free to comment and I will reply with the best of my knowledge and try to solve your problem.

Note this is just a basic intro to OpenGL and SDL, but if you want a more comprehensive and better guide to making apps in OpenGL, I would recommend Anton's Open GL Tutorials, the links open to the amazon site.

My methodology for writing the code is not recommended, instead, I have included hyperlinks at the bottom of each step which will take you to the official OpenGL websites and show the proper way to use the functions.

I had made a personal goal to finish this application in a week, so there still a lot of bugs in the build, but I will be improving my code whenever I get the time to do so.

And of course, I am not responsible for any damage caused by my code to your computer. run my code on your PC at your own risk.

If you find any shortcomings or errors in the code, please reply in the comments and I will fix it.

Step 1: Installing OpenGL, SDL and Stuff (Visual Studio 2013)

If you are new to openGL and SDL, installing the libraries in Visual studio can get a wee bit tricky.

The main Libraries I used to make this application:

1)SDL (main lib to make the application)

2) SOIL ( to import aand use images in my application easier)

3)GLUT ( only some utilities to make life easier )

Q: Why SDL? I thought we were going to use OpenGL...

A: OpenGL is simply a cross-platform standard and API for 2D/3D rendering on the computers monitor.On the other hand SDL is a cross-platform library to provide low level access to Audio, keyboard etc and other peripherals via OpenGL. In other words, it is there to make life easier for us while programming OpenGL apps.

Downloading SDL:

1) Go to https://www.libsdl.org/download-2.0.php and download "SDL2-devel-2.0.3-VC.zip" Visual C++ Development Libraries as shown in (Image 1).

2) unzip the package.

Adding to Visual Studio:

1) Create a new project (Image 2)

2) go to Installed>Other Languages>Visual C++>Win32, Name your project and hit "Ok" (Image 3)

3) A new window will open after some loading, hit Next

4) In the next window, uncheck "Security Development Lifecycle (SDL) checks" and check "Empty Project" button, and hit "Finish"(Image 4)

5) When the project is created, go to "Solution Explorer" > Right click on your project name>Select Properties(Image 5).

6) go to VC++ Directories> Click on Include Directories and a "..." will appear, click on it and a new window will open click on new folder icon and give the path to your downloaded files' "Include" folder (Image 6), eg:

"C:\Users\Arsh pc\Downloads\SDL2-devel-2.0.3-VC\SDL2-2.0.3\include"

Do the same for the Library Directories.

"C:\Users\Arsh pc\Downloads\SDL2-devel-2.0.3-VC\SDL2-2.0.3\lib\x86"

7) Now go to Linker> Input> Additional dependencies, click on the Down Arrow and select "Edit", Add the name of the lib file i.e. type "SDL2.lib; SDL2main.lib; SDL2test.lib;" with the semicolon (Image 7).

8) Now right click on Source Files in Solution Explorer> Add> New Item, select a .cpp file, hit ok.

9) Now run your application, click on "Local Windows Debugger" and run it. If you see any errors, ignore them (Image 8).

10) Now go to the root directory of your project file, this is usually in the Documents folder, and go to the Debug folder

"C:\Users\Arsh pc\Documents\Visual Studio 2013\\Debug"

In this folder, add the SDL2.dll file which should be in the library directory of your SDL

download (lib>x86>SDL2.dll) folder.

Now after all this is done, we can install SOIL. What is SOIL? it is a library with which we can easily load image files into our projects. since we do not want to write our own classes to process different file formats, we can use SOIL which supports many mainstream formats and processes the images for us.

To get SOIL, head over to http://www.lonesock.net/soil.html

The installation process is the same as it was for SDL,

Set the Include directories path to src folder in the SOIL download file,

Set the Libraries Directories path to lib folder.

Now in the lib folder, you might notice there is a single file named "libSOIL.a", now this cannot be processed by visual studio, it must be converted to a SOIL.lib for proper functioning.

To do this go to projects> VC* >Double click SOIL.vcproj file, open it with visual studio, Execute the code, and you should get a SDL.lib in projects> VC* >Debug folder. Add this to your lib directory in the SOIL download file.

I used SDL for the most of the part, but to make things easier I also used some GLUT utilities. GLUT Libraries can be downladed at: http://www.javaforge.com/doc/105278

The process for installing GLUT is pretty much the same.

Step 2: Matrices and Vectors

What is a matrix? Do You need to change something in your scene? for example, move your character forward, you need matrices. It is a grid of numbers which can be used to store or define the state of our 3D world. there are two main matrices in OpenGL, Model view matrix (GL_MODELVIEW) and the Projection matrix (GL_PROJECTION).

A typical matrix-

| 1 2 4 |

| 2 4 6 |

| 8 9 4 |

this is a 3x3 matrix.

More information-http://www.mathsisfun.com/algebra/matrix-introduct...

What is a Vector? vectors are used to represent points in the 3D or 2D space.

Vector in 2d space (x, y) coordinates- (2, 3)

Vector in 3d space (x, y, z) coordinates- (2, 3, 4)

More information-https://www.mathsisfun.com/algebra/vectors.html

So what do we need matrices and vectors for?

Long story short, when we need to move objects in the 3D/2D space, we do that with the help of vectors and matrices. All the operations like moving your character in Super Mario or Call of Duty etc. are done with these two.

Listed below are some of the functions aka matrices in OpenGL for basic transformations

1) Translation (move)- glTranslatef(X, Y, Z);

2) Scale (change the size)- glScalef(X, Y, Z); scaling in different axes or all the axes

3) Rotation-

X axes- glRotatef(, 1, 0, 0);

Y axes- glRotatef(, 0, 1, 0);

Z axes- glRotatef(, 0, 0, 1);

only the parameter will be changed, the location of the 1 determines which coordinate is to be left unchanged, that is when rotating about Y axis, there is no need to modify the Y coordinate because during the actual rotation, we do no change in the Y axis.

Now these functions repersent matrices. The order in which we use these matrices matters, rotation before translation is not the same as translation before rotation.

Two more main matrices you need to know about in OpenGL-

1)Model view matrix: Everything you do with your objects in your current scene is stored in the model view matrix. You can think of it as a chief matrix to which other matrices (like glRotatef, glTranslatef) are multiplied to, to modify the scene. That's right, one matrix to rule them all, or more specifically the current scene.

2) Projection matrix: This matrix will handle the view of our scene i.e. whether the scene in prespective or in orthogonal view, and setup the viewport.

A viewport is basically an area in your application to which your scene will be rendered to.

Step 3: Flow of Control and Matrices

OpenGL is a state machine. When you change something, it stays that way until you explicitly change it again. The same is with matrices. In openGL, before manipulating any matrices, we first need to set the matrix currently being modified, which can only be one at a time.

Suppose we built a simple cube in OpenGL.(for now, I won't be writing the code, But I will explain it later)

START

{---code for moving/rotating the cube---}

{---code for making the cube---}

DRAW

Before we can execute this code we need to tell openGL which matrix to load and modify our current scene. So we give it (OpenGL) the model view matrix because like I said before, it is used define the changes to our current scene. If we don't, OpenGL won't know which matrix to use because after all, OpenGL is all about matrices.

START

{---Load the Matrix (Model View)---}

{---code for moving/rotating the cube---}

{---code for making the cube---}


DRAW

Now we can move our cube.

Similarly, we set the projection matrix.

START

{---Load the Matrix (Projection Matrix)---}

{---code for the projection, viewport etc. setup---}

DRAW

______________________________________________________________________________________________

*Note:- Technicialy there is no camera in OpenGL. That is, everytime you change your position in the scene, you actually change the position of all the objects in the scene or more specifically we modify the model view matrix of the entire scene. The viewport or the "camera" always remains at the same position.

______________________________________________________________________________________________

Step 4: The Headers (so I Don't Have to Write Them Over and Over Again)

#include "SDL.h"

#include "glut.h" // misc utilities and dtypes.

#include "soil.h" // image importing utilities>

#include "stdio.h"

#include "math.h" // for basic mathematic functions

#include "stdlib.h"

#include "string.h"

Step 5: The Build: Making a Window

The Basic code you will need to compile and run is as below. Now, it can be much shorter, but I want to introduce some important concepts in this step, and complete this instructable in a finite amount of time.

code

Let's take a closer look at initialization

code

SDL_Init initializes the sdl to a mode which you want to use. Specifically, there are 8 modes in SDL which include Audio, CD-ROM, File I/O, Joystick Handling, Threading, Event Handling, Timers, Video (the one we are using). Now our need right now is only the SDL_INIT_VIDEO.

The next three lines of code simply create a window for us to use. screen is a variable of type

SDL_Window *screen;

In this variable, we store the return value of SDL_CreateWindow() which returns a window if successful or a NULL if unsuccessful.

in SDL_CreateWindow(),

1) the first argument details the window title,

2) the second and third argument give the default location of the window on the screen on startup

3) the fourth and fifth argument specify the screen size, I have created two variables windowHeight = 1020; and window width = 610; to store this information.

4) the sixth argument is for a flag, which can specify things like whether the window can be resized or whether it should be minimized on startup etc. you can find more flags in the links at the bottom of this step.

The next function SDL_CreateContext() is unique for each window. SDL2 introduced a new system by which you could create multiple windows. but for each window, you must create a context which basically stores all of the state associated with this instance of OpenGL.

As I said before, OpenGL is a state machine. Our application may have multiple windows, so openGL must know which window to render the graphics to, so we use

SDL_GL_MakeCurrent(, )

to tell openGL which window to render to. OpenGL will continue to render to a particular set window until you reuse SDL_GL_Make Current to specify another window.

Next, let's take a look at the while() loop

code Now this is the main loop in which we will be rendering our screen and checking for events. This loop will run until the exit condition is true i.e. we quit the application by pressing the cross button on the top of the window.

I have created a variable done = 0; which the loop will check at each iteration. if done = 1, the program has satisfied exit condition and the loop will terminate and the program will close.

SDL_Event event creates sort of a stack of different events sorted by the precedence of occurrence. At each new iteration, the application state will be updated, and in each iteration of the loop, the user may press keys, click buttons or move the mouse etc.

SDL_PollEvent( &event ); will populate event with the various events occurring in each iteration.

that is, in each iteration of the while loop, the event variable will be repopulated with event data over and over again.

by placing SDL_PollEvent( &event ); in a while loop

while ( SDL_PollEvent( &event ))

{

}

We can evaluate events from the event stack in the event variable until there are no more events in the event variable.

in the nested while loop, we check for SDL_QUIT event which basically tells us the red cross button on the top of the application has been pressed and the user is now quitting the application.

The very last function is SDL_GL_SwapWindow(screen).

Now everything rendered to the screen in OpenGL is stored in a memory area called the frame buffer. when refreshing the screen with a new image at each frame, the frame buffers contents are erased and populated with the new graphics. practically this process takes time and if we run our application this way we would see a lot of flicker as drawing the new image takes time in the frame buffer.

But with the concept of memory swapping, we can prevent this effect. We define two memory areas, the front buffer and the back buffer, the screen points to the front buffer and the image in the front buffer is displayed. The next image to be drawn is loaded into the back buffer while the screen displays the contents of the front buffer, so instead of copying the contents of the back buffer to the front buffer, the screen points to the back buffer instead and the next frame is drawn instantly, and then the front buffer is filled with the next frame and the screen is changed again and so on. In essence, we define to memory locations and load data into them in tandem i.e. the image to be displayed and the next image to be displayed and keep swapping the screen pointer between the two.

Luckily in OpenGL, we don't have to go into that much complexity and just call one function to achieve a nice display and prevent flicker:

SDL_GL_SwapWindow();

The last thing to do is closing the application and disposing of any resources we used.

code

External Links and references for further research:

SDL_Init() - https://www.libsdl.org/release/SDL-1.2.15/docs/htm...

SDL_CreateWindow() - https://wiki.libsdl.org/SDL_CreateWindow

SDL_GL_MakeCurrent() - https://wiki.libsdl.org/SDL_GL_MakeCurrent

SDL_PollEvent() -https://wiki.libsdl.org/SDL_PollEvent

Step 6: The Build: Setting Up the Viewport

code

In this step I will go through the process of setting up a viewport in OpenGL, and adding color to the background!

First lets take a look at Anti-aliasing.

code

SDL_GL_SetAttribute() is used to set different properties for our window. It is to be used before creation of a window therefore it is not to be put in the main loop.

In this case, I used it to turn on Anti-Aliasing by SDL_GL_MULTISAMPLEBUFFERS set to 1 (i.e. ON). And SDL_GL_MULTISAMPLESAMPLES to set the Anti-Aliasing level which can be from 1 (MIN) to 8 (MAX).

Now I have defined two new functions here

code

initGL(

Coordinate X, Coordinate Y

Width, Height

)

to this user defined function, I pass the location of the viewport in my application and the size of my viewport I want to create.

Now we must define the projection for the viewport, so to establishProjectionMatrix() I passed the viewport size. There are two main types of projections

1) Orthographic: this type of projection is used in engineering applications where the object is displayed as it is without any distortion.

2) Perspective: This offers a "real life" view of objects, the way we see things naturally with our eyes. This type of projection is usually used in games and simulations.

So to setup the projection, load the GL_PROJETION matrix or the projection matrix. Like I said before, the properties of the scene in OpenGL are controlled through matrices. Perspective projection modifies the scene by distorting the shape of the objects in the scene. So to store and apply this information to the scene, we use matrices.

Now only one matrix may be loaded to modify in OpenGL at a time. So anytime we want to change something in the scene, we need to use a matrix, every time we want to use a matrix, we need to load it using glMatrixMode()

now just like we initialize a variable to zero at definition

int var = 0;

we need to do so the same with a matrix

glMatrixMode(GL_PROJETION); //Load the matrix into OpenGL

glLoadIdentity(); // Initialize

We initialize this matrix with an identity matrix, then start to modify it.

gluPrespective(, , , );

1) field of view- it takes an angle in degrees, and field of view in the Y axis. for a natural view, I chose 45 degrees.

2) Aspect ratio- Here you pass in the result of height/Width of your viewport.

3) near clipping plane- the minimum distance from the camera to which the 3D world will be created. for example, sometimes when you move your character in 3rd person view, you get too close to his body and you see insides of the character, that's near clipping plane in action, an invisible plane in front of the camera. If any polygons/points cross that plane, they are not rendered in the 3D scene.

4) far clipping plane- The farthest distance from the camera to which the objects in the 3D scene will be loaded/drawn. for example in open world RPG's like Skyrim, at the horizon, you can see the land/city fade into a white smog, that's the far clipping plane. It is useful to reduce CPU load because objects too far away from the camera if drawn, won't even be visible on the screen.

The very first function in establishProjectionMatrix() that is glViewport() is responsible for creation for the actual viewport in our specified region.

code

After establishing the projection matrix, let's move on to other initialization steps,

code

Before we continue, let's take a look at two functions:

glEnable() and glDisable(),

Imagine OpenGL to be a big machine. This machine has a lot of switches to change the way OpenGL behaves and generates output. to flip these switches, we use glEnable and glDisable.

Everything else changes OpenGL behaviour, but the following lines of code are important.

codeglClearColor(R, G, B, A)- Takes in float values ranging from 0.0f to 1.0f and clears the viewport to the specified color.

If you define multiple viewports in your app and try to render an object to one viewport, you won't see anything on other viewports in the app. This is because properties of one viewport are interfering with other viewports.

so we use glScissor() which basically defines an area for the viewport (in this case area where viewport itself is defined) to which the viewport and its effects are limited to.

This lets us create multiple viewports with their own effects and properties.

Now let's take a look at DrawScene()

code

It is placed after initGL() because it will host our code for rendering the cube.

glClear() clears the render are (viewports) with the predefined color and in this case since we are going to be using 3D polygons, I have included the depth buffer as well.

Step 7: The Build: Multiple Viewports

code

Now, the only difference is that I have added three new viewports,

(1) and (2): Compared to one viewport in the previous step, Now I have added 4 new viewports, by simply copy pasting the code from initGL() and establishProjectionMatrix(), and naming them in alphabetical order.

(4) is also just copy paste, the only difference here is though is that I have changed the glClearColor() values for the 4 different viewports.

(3) is where is, see the different viewports have different shape and position, I have controlled that through

InitGL(PosX, PosY, SizeX, SizeY), like I discussed in the previous step. So I simply changed the values for each viewport.

code

I have marked my application different parts according to the different functions controlling them,

(A) is controlled by InitGLA() and drawSceneA()

(B) is controlled by InitGLB() and drawSceneB()

(C) is controlled by InitGLC() and drawSceneC()

(D) is controlled by InitGLD() and drawSceneD()

Now (D) is the same Color as the background but there is a viewport (as indicated by the red dashed lines)


Step 8: The Build: Drawing a Cube

Mechanics of creating a cube in OpenGL (cube in this case):

OpenGL has the following primitive types

primitives

Source: www.glprogramming.com,

Image Source: http://www.glprogramming.com/red/images/Image34.gi... Its a pretty good reference website.

Don't let this scare you, we will only be using GL_QUADS for our super cube.

In games and most applications, these primitives are rarely directly used, instead, models from 3rd party CAD software's like Autodesk Maya, Blender, 3DS Max are imported and used instead (Just imagine building a 1000 poly character by code). This list just describes the OpenGL's standard for primitives.

1) Step 1: Tell OpenGL what you are about to do. use glBegin(GL_QUADS); to specify the start point of your construction and glEnd(); for the end point of construction.

code

In the first (1) line, GL_COLOR_MATERIAL will be required later but not necessary right now,

the second (1) line GL_CULL_FACE if enabled prevents surfaces that are not visible from drawing. This is a good thing as it reduces the load on the CPU and improves applications performance.

the third line (2) marks the beginning for rendering our cube. consider the following snippet

START

glVertex3f(1.0f, 1.0f, -1.0f);

DRAW

this would draw a vertex (point) for the QUAD. but we don't need that, so we draw three other vertices to complete a face

START

glVertex3f(1.0f, 1.0f, -1.0f);

glVertex3f(-1.0f, 1.0f, -1.0f);

glVertex3f(-1.0f, 1.0f, 1.0f);

glVertex3f(1.0f, 1.0f, 1.0f);

DRAW

Now this would give us a flat surface. But with no color, so let's add some color.

We associate a unique color with each vertex and by default, colors from each vertex will blend nicely with each other.

START

glColor3f(0.583f, 0.771f, 0.014f);
glVertex3f(1.0f, 1.0f, -1.0f);

glColor3f(0.609f, 0.115f, 0.436f);
glVertex3f(-1.0f, 1.0f, -1.0f);

glColor3f(0.327f, 0.483f, 0.844f);
glVertex3f(-1.0f, 1.0f, 1.0f);

glColor3f(0.822f, 0.569f, 0.201f);
glVertex3f(1.0f, 1.0f, 1.0f);

DRAW

Below is the full code for the cube

code

The code is very long, but you only have to write this once in your application.

Next call cube() in your drawScene() methods:

code

And execute the code and you should get the following output:

code

What is this?!?! is there something wrong with our code? No.

You see the code is fine, the thing is that the cube is at the center of the X, Y and Z axes and so is our camera or the viewport(s) so we see a zoomed in view of our cube.

In the next step, we will be manipulating the cube.

Step 9: The Build: Rotating the Cube

Note: I updated my windows 10 PC before writing the step, that's why the top bar of my app is green because of my theme color (which is green). So there are no additional changes I made, its just the windows OS doing its thing.

To rotate our cube, we will need two things.

1) First a function to update the rotation when we press our keys.

2) Matrices to rotate our cube.

The following function is responsible for checking the key press events and updating the rotation and scaling variables

code

Firstly I defined a variable

const Uint8 *keys = NULL;

It's similar to the concept of an array, but basically, it is a data structure to store data as a chain of elements.

Next as in (1) I populate key variable with key events occurring in each iteration via SDL_GetKeyBoardState(NULL);

See, super easy. Now in (2) I call the function checkKeys(),

code

Checking which Key is pressed is super easy in SDL, it has inbuilt macros defining what key is pressed.

Like in (1) SDL_SCANCODE_ESCAPE defines the Esc key

Source: www.ComputerHope.com

Image Source: http://cdn.computerhope.com/keyboard/esc.jpg

Similarly in (2) and in (3).

Now in (2) I have defined all the variables (which are float btw) to define the rotation. when the arrow keys are pressed, they are incremented/decremented accordingly.

GLfloat cubeRotateX = 0.0f;
GLfloat cubeRotateY = 0.0f;

In (3) I have defined the variables responsible for scaling.

GLfloat ScaleFactor = 1.0f;

Now the function checkKeys() returns true If the exit condition is successful and false If exit condition is not true yet.

Then accordingly in the if condition in the while loop, the done variable is modified. As you probably know by now, done variable controls the exit condition of the app. if done = 1; the while loop quits and the application is terminated.


Now we have a system in place to get key inputs, and we need a system to actually move the cube.

code

I have made a function updateModelView() which is responsible for moving our model and I called it before drawing my cube at the start of the cube() function.

In updateModelView() :

First we load the matrix we will be modifying - GL_MODELVIEWor the model view matrix. then we load the Identity matrix with the glLoadIdentity() .

first glTranslatef(0, 0, -10.0f); moves the cube away from the origin so that we can see the cube (in negative Z axis).

then I placed the glScalef(scaleFactor, ScaleFactor, ScaleFactor); after that. If the value of ScaleFactor changes the cube's size also changes.

Next, the first glRotatef() is responsible for rotation in the Y axis. The second glRotatef() is responsible for rotation in the X axis.

Step 10: The Build: Adding Buttons, Managing Views

First let's take a look at adding Buttons into our app using SOIL. In my loadButtons() function, I have loaded the PNG's for all the images I will be using, and then called it BEFORE the main loop.

code

(1) I declared unique GLuint variables (minusX, plusX..) for each individual button in the scene.

(2) Give the path to your textures

Second, to display these textures, I bound them to GL_QUADS and displayed them face front. This gives the flexibility to animate them.

I did it in the DrawSceneD() method because as you remember, it was the big viewport on the left of the app.

code

(1) Firstly we use glPushMatrix() and the respective glPopMatrix() functions for each individual GL_QUAD face.

then use glTranslate(x, y, z) to move it to the desired position in our viewport.

(2) We use the variable we used to define each button's texture in the scene.

(3) Then we make the actual QUAD face. we use glTexCoord2d() to specify the UV coordinates for each vertex of the face. Basically, tell openGL how to apply our texture onto the GL_QUAD face, whether want the texture streached, repeated, etc.

I had to repeat the process for each button, as you can see from the comments, I have divided the code into the buttons each segment is responsible for ease of debugging.

Now take a look at the other three DrawScene() methods we defined earlier:

code

(1) DrawSceneC() and DrawSceneA() methods are responsible for the front and the side view of the scene.

glTranslatef(0, 0, -10.0f); here moves the object a bit far away from the viewport for easy incpection.

drawCubes() is a special function I will be discussing in the next step.

Step 11: Finishing Up: Multiple Cubes and Views and Registering Clicks

The algorithm for generating the cubes is the best my brain could cough out, so if you have a better method or find any deficiency in the code, please let me know I will improve my code.

code

currentGeometry and objCount are initialized to

currentGeometry = 1;

objCount = -3;

on each click of generate new cube both are increment.

initialize is an array of static elements used to control the if() statement which holds the variables to store the location and scaling history of the previous objects in the scene.

First Cube

||manipulate the cube||

End

Second Cube

||store the transformations of the previous cube[1]|| //in an array

||manipulate the cube||

||Display cubes from the array||

End

Third Cube

||store the transformations of the previous cube[2]||

||manipulate the cube||

||Display Cubes from the array||

End

and so on....

So long story short, the number of cubes is limited by the size of the array. So you know a better system is needed, maybe I'll figure it out in the next version.

code

Xposition Yposition Zposition store the coordinate location in 3D space and Xsize Ysize Zsize store the scaling. As you can see at the start of each new cube creation, I needed a method to store these values of the previous cube. so I declared a static array initialize[n] which makes this whole code run only once at the start of the creation of a new object, tracked by the objCount variable.

As you can see the creation of cubes is very dodgy and affect the functioning of the program adversely.

Let's take a look at the cube() function:

code

I have removed the code for drawing the cube for the sake of clarity.

the arguments of the function take in the 3D coordinates in which you want to draw the cube, the size of the cube you want to be, and which viewport it is meant to go in.

if I pass value 1, that means I want it in the main viewport (Viewport B)

If I pass value 2 or 3, this means I want the cube in one of the bottom two viewports for the front and the side view.

One thing to be wary of is before using glScalef(x, y, z); be sure to use a new matrix by using glPushMatrix() because scaling operations of the previous cube can be transferred to a newly created cube.

One thing I forgot to mention is creating the button click events itself.

Step1: Place the buttons in the desired positions.

Step2: Draft coordinate space for each individual button on a piece of paper.

code

Step3: Add the code,

code

On each click in the viewport, it will be checked if a button image is clicked.

Step4: Call the function in the main loop, when a click event is registered.

code

If a mouse click is registered, it will check if a button is clicked. In fact, it could be improved by first checking which viewport the click event occurred, if it was the one with the buttons, then check the enormous grid of if() conditions.

Step 12: Saving Your Masterpiece With a Screen Shot & Adding Hotkeys

code

I initialized wantToSave = false; at declaration, then if the user presses the "s" key, wantToSave=true and the SOIL_save_image() executes.

the height and width variable control the size of the screenshot in the application.

Now the image saved will be inverted, so yeah. But think of it as a feature, what if someone wanted an inverted pic? problem solved!

Clicking on the screen is nice, but using buttons is much smoother, so I added some hotkeys, 6 to be exact

T- Move Cube forward

G- Move Cube Back

F- Move Cube Left

H- Move Cube Right

V- Move Cube Up

B- Move Cube Down

code

Step 13: The END!

That's it, folks!

If you have any doubt's, or if there is some error or bad code, please feel free to comment and I will try my best to fix/solve your problem.

<p>Hello, Thanks for making these instructions i made the program up till step 10, after that it became a mess and the instructions could be more clear.</p><p>For example what happens to the updateModelView and I dont fully understand the drawcubes command.</p>
<p>Guys, please don't tell him about Blender, let's see where he manages to get :D</p>
It's a strange motive to code a new cad application but I appreciate your work :)
<p>Thanks, btw it was just for fun :)</p>

About This Instructable

4,392views

21favorites

License:

More by dexLab:Unmanned Ground Vehicle Drone & Control System thereof Beginners Guide to OpenGL,SDL: Build your own CAD software DIY Raspberry pi desktop case 
Add instructable to: