The Setup

So here I was, thinking what would be useful for someone trying to learn graphics? A cheat sheet! and I set out to make a blog post about it. But it’s been awhile since I sat down and spent some quality time with openGL and it turns out, if you’re getting back into it like I am or if you’re just starting out, you probably need more of a blueprint. so that’s what we’re going to do first.

Before you even look at writing any C++ code, there’s some setup that needs to happen. My setup is fairly robust, built off a skeleton given out by my professor. I’m going to show you what I have but try to mention where it could be slimmed down.

First things first: file structure. I have a parent directory where all my graphics shenanigans lives called ‘glMathMagic’. That’s not terribly important but all the directories I’m about to talk about live in there. Inside glMathMagic, I have 4 directories and a few miscellaneous files. They go like this:

  • Directories:
    • src: this is where your main program files will go. I like to keep subfolders in here for each separate project so the makefiles don’t get all jumbled up. more on this later.
    • include: header files go in here
    • lib: library cpp files (aka corresponding to header files in include) go in here
    • bin: executables and any data files (.dat) go in here
  • Files
    • graphics.cfg: definitions for a bunch of macros for your makefiles. super important to have these defined somewhere and since there’s 2 makefiles you need, might as well keep this here in your upper directory to be referenced by both. more on this later.
    • template.cpp: I keep a skeleton graphics program that has all the window setup stuff in it to copy into src for new projects. don’t worry about this too much at the moment but I’ll share it later anyway
    • makefile: this is also sort of a skeleton backup in case I lose my other makefiles in a freak accident. not really important.

Let’s talk about makefiles. Maybe you love them. Maybe you’re terrified of them. I am both. This setup is for programming on the linux command line, which is important because makefiles are really just fancy bash scripting. We can get into that on a later date but for now all you need to know is I’m running Ubuntu. So here’s a quick rundown in case you’re super new: when you compile on the command line, you list the files you need. When you have lots of files in lots of folders, that gets really hard to keep track of. A makefile is basically a little script program you keep on hand to run all the necessary commands for you. I keep two of them, one in lib and one with each project in src.

Here’s what I have in the lib makefile:

TOP=..
include $(TOP)/graphics.cfg

SOURCES=\
		sadielib.cpp \
		polyline.cpp

LIBOBJS=\
		$(VPATH)/sadielib.o \
		$(VPATH)/polyline.o

LIBDEP = $(LIBOBJS:.o=.d)
OBJECTS = $(LIBOBJS)

UTILLIB=libGraphicsUtils.a

all: $(UTILLIB)

# $(CXX) -MD creates a .d file and a .o file in the VPATH directory
$(LIBDEP):      $(VPATH)/%.d:   %.cpp
	-mkdir -p $(VPATH)
	$(CXX) -MD $(CXXFLAGS)  -o $(@:.d=.o) $<


$(OBJECTS): $(VPATH)/%.o: %.cpp
	$(CXX) $(CXXFLAGS) -o $@ $<

$(UTILLIB): $(OBJECTS)
	$(AR) $(ARFLAGS) $@ $(OBJECTS)

clean:
	rm -rf $(UTILLIB) $(VPATH)

include $(OBJECTS:.o=.d)

I’m not going to go in-depth with everything but there’s a few things you need to know.

  • stuff like $(VPATH) and $(CXXFLAGS) are defined in graphics.cfg in the parent folder
  • the basic setup of the main commands is
    target : [ dependency ]*
       [ tab  command  endl ]+
  • sadielib is my personal library of functions that are handy but not necessary, things I tend to use repeatedly. For example, the function to be able to press q to exit my graphics program is in there. Leave a comment down below if you’d like to hear more about my personal library. polyline is also a library I wrote but it’s wrappers for point and line classes.

Let’s move on to the makefile in src.

TOP=..
include $(TOP)/graphics.cfg

FILENAME = practice
#TARGET = $(FILENAME)

.PHONY: 

SOURCES = \
$(FILENAME).cpp

# all the .o files need to be listed here.  Leave backslash off last list item
APPOBJS = \
$(VPATH)/$(FILENAME).o 

APPDEP = $(APPOBJS:.o=.d)
OBJECTS = $(APPOBJS)

APP = $(BINDIR)/$(FILENAME)

all: $(APP)

# $(CXX) -MD creates a .d file and a .o file in the VPATH directory
$(APPDEP):      $(VPATH)/%.d:   %.cpp
	-mkdir -p $(VPATH)
	$(CXX) -MD $(CXXFLAGS)  -o $(@:.d=.o) $<

$(OBJECTS): $(VPATH)/%.o: %.cpp
	$(CXX) $(CXXFLAGS) -o $@ $<

$(APP):  $(OBJECTS) $(LIBDIR)/libGraphicsUtils.a
	-mkdir -p $(BINDIR)
	-mkdir -p $(LIBDIR)
	make -C $(LIBDIR)
	$(LD) $(LDFLAGS) -o $@ $(OBJECTS) -l GraphicsUtils $(GLIBS) 

clean:
	rm -rf *.o *.d $(APP) $(VPATH)

# this generates errors on the first pass, but then these .d files
# get created for the second pass.  

include $(OBJECTS .o=.d) 

Ok so this one takes the archive that was built by the first makefile, libGraphicsUtils.a, and uses it to build your project file, FILENAME. In this example I have practice.cpp in src so I put FILENAME = practice.

You always want TOP to refer to that parent folder where graphics.cfg is. When I have subfolders in src and this makefile is in a subfolder, I change TOP = ../.. so it can still find everything.

Last, but not least, and probably most confusing, we’ll take a look at graphics.cfg.

# This is common for all graphics programs
# graphics library names

# first, figure out which OS we are working in (Macos = Darwin)
UNAME = $(shell uname)

ifeq ($(UNAME),Linux)
GL_LIB = GL
GLU_LIB = GLU
GLUT_LIB = glut
GLW_LIB = GLw
GLUI_LIB = glui
OSMESA_LIB = OSMesa
endif

BINDIR = $(TOP)/bin
LIBDIR = $(TOP)/lib
INCLUDES = -I$(TOP)/include

#Compiler information
AR = ar
CC = gcc
CXX = g++
LD = g++
ARFLAGS = qcs
LDFLAGS = -L$(LIBDIR)
SYSLDFLAGS = -rdynamic
SHLDFLAGS = -s -export-dynamic -shared

ifeq ($(UNAME),Linux)
DEFINES += -DLINUX -D_PTHREADS
LIBAS += -ldl
FLAGS += -pthread
endif

CFLAGS = -c -g $(INCLUDES)
CXXFLAGS = -c -g $(INCLUDES)

ifeq ($(UNAME),Linux)
GLIBS = -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm
endif

ifeq ($(UNAME),Darwin)
GLIBS = -framework GLUT -framework Cocoa -framework OpenGL
endif


VPATH = obj

#####################################################################
# Define build rules
#####################################################################

.SUFFIXES:

.SUFFIXES: .o .c .cpp .h

.c.o:
	$(CC) -c $(CFLAGS) -o $(VPATH)/$*.o $*.c

.cpp.o:
	$(CXX) -c $(CXXFLAGS) -o $(VPATH)/$*.o $*.cpp

So that’s all your definitions and shorthand you see up in the previous makefiles. you could put these in the makefiles, but as I mentioned before it’s just more streamlined to have them separately here.

Look at that, we’re all set up now! In my next post I’ll go into how to set up the program itself using C++ and OpenGL.

Happy Coding!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s