Showing posts with label D Programming. Show all posts
Showing posts with label D Programming. Show all posts

Wednesday, April 18, 2007

NeHe Lesson 12: Display Lists

Ok, didn't get to test this on Windows, but it should work as the lesson doesn't contain platform specific code.

First off there's an example on how to initialize a static multi-dimensional array:
(In case you didn't know already how to do it.)
/// Array For Box Colors
GLfloat boxcol[5][3] =
[
// Bright: Red, Orange, Yellow, Green, Blue
[1.0f, 0.0f, 0.0f], [1.0f, 0.5f, 0.0f], [1.0f, 1.0f, 0.0f], [0.0f, 1.0f, 0.0f], [0.0f, 1.0f, 1.0f]
];

In the module constructor we have something new.
// Enable key repeating
if ((SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL)))
{
throw new Exception("Failed to set key repeat: " ~ getSDLError());
}
Here we enable SDL to repeat key presses if you keep a key down. I've used SDL's default values for the arguments.

There isn't really anything special about the rest of the code, so grab a cola and go read what NeHe has written on the subject, here.

Here's the link to the source.

Thursday, March 1, 2007

NeHe Lesson 10: Loading And Moving Through A 3D World

The 10th lesson is finally converted and polished. This lesson shows you how to load world data from a text file and then how to display it. And actually it's pretty simple code. The original lesson can be read here. I'll go over couple things here that are more specific to D and Tango.

First I've imported the world data at compile time into the final executable. This is a cool feature and I think very useful for static data like this. You can of course use it to import texture data or something totally different.

setupWorld(import("world.txt"));
You need at least the version 1.005 of DMD for this to work. I have no idea if GDC even supports this yet. With 1.005 you need to add the relative path to the world.txt to the string above. With 1.006 and later you don't need to change the code, but you must use the -J switch to define the search path for the compiler where it can find the file.

The setupWorld function is pretty simple. With the use of Tango's LineIterator, reading through the world data is a breeze.

Now go play with it, lesson10.d and world.txt.

Monday, February 26, 2007

NeHe Lesson 09: Moving Bitmaps In 3D Space

The 9th lesson covers more ground on moving things around and applying color to black and white textures. The lesson can be read here.

This is the first time in these tutorials where we see a nice little example on how to use the D's foreach loop. It is used to initialize all the stars in the array. It is very clean looking and easy to follow. The only thing to remember in a situation like this, is to use the 'inout' modifier on the star variable so that the changes stick.

foreach (i, inout star ; stars)
{
star.angle = 0.0f;
star.dist = cast(float)i / stars.length * 5.0f;
star.r = rand.next() % 256;
star.g = rand.next() % 256;
star.b = rand.next() % 256;
}

The foreach loop is used in the drawing function also. There too the 'inout' modifier must be used because we update the values in the star at the end.

The rest of the code can be read here.

Friday, February 23, 2007

NeHe Lesson 07: Texture Filters, Lighting & Keyboard Control

The 7th lesson adds some lights and 2 more ways to make textures. Keyboard input is added to move and rotate the box. There shouldn't be anything too difficult about the lesson. Check out the new parameters to glTexParameteri and how the lights are defined. The original lesson can be read here.

The D version is here.

All the images and other data used in these lessons can be found here.

NeHe Lesson 06: Texture Mapping

So, it's been a while. I've been very busy with other stuff lately, but I haven't forgotten this blog.

The next lesson is about texture mapping. Go read it here. There's couple things I'd like to mention about SDL and OpenGL concerning this tutorial.

First of SDL has its own image loading functions, mainly SDL_LoadBMP, which loads BMP images. In a bigger project you might want to look at SDL_image for other image types.

The other thing is that you will need to flip and rotate your textures when using SDL. The following lines of code will setup OpenGL to do that for you.

glMatrixMode(GL_TEXTURE);
glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
glScalef(-1.0f, 1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);

The full code listing can be found here.

Monday, February 19, 2007

Update: Lessons 1-5 use Tango now

I've updated the lessons 1-5 to use the Tango runtime. Only the to and from char* functions needed to be changed.

So from now on I'll publish code only compatible with Tango.

Friday, February 2, 2007

Let's dance to the Tango 0.95 beta 1

So Tango's first beta has been released. So the first thing I did, was to go and ask when and if Derelict will support it. "In the very near future."

I will be using Tango exclusively from now on because as far as I'm concerned it's far better than Phobos. That might be my Java background talking too.

I'll start of by converting the existing lessons to Tango. That shouldn't take too long, as they don't have many dependencies to Phobos. But first I have to wait for Mr. Parker to add the support to Derelict.

Friday, January 26, 2007

NeHe Lesson 04: Rotation

The fourth NeHe lesson is about using the glRotate*() functions. Go read what he has to say about them here. The lesson builds on the previous one. I'll show the parts the have changed here.

First of we need to declare two need variables for the rotation.

/// Angle For The Triangle
GLfloat rtri = 0.0f;
/// Angle For The Quad
GLfloat rquad = 0.0f;

Here you must be careful with how D initializes floating point variables. For example if we had declared them like this: (Like the C-version)

/// Angle For The Triangle
GLfloat rtri;
/// Angle For The Quad
GLfloat rquad;

Then the variables would have been initialized to NaN and the triangle and the quad would not have shown on the screen at all. I've fallen for this many times, especially with these tutorials.

The drawGLScene function is the same except the calls to glRotatef and the glLoadIdentity in the middle. Try to leave it out and see what happens.

Having the variables rtri and rquad initialized to 0.0f wont do us much good if we don't change them, so there is at the end we change them slightly to archive the moving rotation effect.

/**
* The drawing function. Here we will draw the triangle and the quad.
* Now with color and rotation.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Rotate The Triangle On The Y axis
glRotatef(rtri, 0.0f, 1.0f, 0.0f);

// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Set The Color To Red
glColor3f(1.0f, 0.0f, 0.0f);
// Top
glVertex3f(0.0f, 1.0f, 0.0f);

// Set The Color To Green
glColor3f(0.0f, 1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);

// Set The Color To Blue
glColor3f(0.0f, 0.0f, 1.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Finished Drawing The Triangle
glEnd();

// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Right 1.5 Units And Into The Screen 6.0
glTranslatef(1.5f, 0.0f, -6.0f);

// Rotate The Quad On The X axis
glRotatef(rquad, 1.0f, 0.0f, 0.0f);

// Set The Color To Blue One Time Only
glColor3f(0.5f, 0.5f, 1.0f);

// Draw A Quad
glBegin(GL_QUADS);
// Top Left
glVertex3f(-1.0f, 1.0f, 0.0f);
// Top Right
glVertex3f(1.0f, 1.0f, 0.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);
// Done Drawing The Quad
glEnd();

// Increase The Rotation Variable For The Triangle
rtri += 0.2f;
// Decrease The Rotation Variable For The Quad
rquad -= 0.15f;
}


You can download the code from here.

NeHe Lesson 02: Your First Polygon

The NeHe lesson 2 is here. There's not much new code, but the GL functions used are maybe the most important you'll ever learn when doing OpenGL coding. So I suggest if you passed the link at the beginning then don't miss is it this time. Read the tutorial. NeHe explains things so much better than I ever could. Afterwards you can marvel how similar the D version looks like. Isn't it great. :)

The only difference between the first lesson and this one is the drawing function. I'll post only it as you can go and get the first one from here and just replace the drawGLScene function.

/**
* The drawing function. Here we will draw the triangle and the quad.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Drawing Using Triangles
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
// Finished Drawing The Triangle
glEnd();

// Move Right 3 Units
glTranslatef(3.0f, 0.0f, 0.0f);

// Draw A Quad
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
// Done Drawing The Quad
glEnd();
}

Don't forget to change the title of the window to "NeHe's First Polygon Tutorial (D version)". Or to something else if you feel like it.

You can download the code from here.

Thursday, January 25, 2007

A few words

I wanted to say a few words about the requirements for building the lessons from my blog. First of all I'm working on a Windows box and wont be doing very much testing on the other platforms. The code is mostly cross-platform so it should compile and run just fine on Linux or Mac OS X. I'll try to point out places where I've used platform specific code.

Next you will need the D compiler. There are two choices at the moment, the DMD from DigitalMars and GDC a GCC based compiler from here.

You also need the shared library for your platform from the SDL website.

I use Derelict for OpenGL and SDL bindings. You can grab them from there or do as I do and use DSSS, the D Shared Software System.

After that you should be ready to go.

Please note, that I'm not going to go over how you can compile a D program or the basic usage of the SDL library. For those problems there are already very good documentation on the net. Google is your friend.

NeHe Lesson 01: Setting up an OpenGL window

Hi, and welcome to the NeHe lesson 01 done in the D programming language.

This code snippet shows you how to set up SDL to display an OpenGL window, How to use Derelict to load shared libraries and a basic loop for reading input and then drawing the screen.

I'm trying to use documenting comments in the code as specified by Ddoc.


/**
* The first lesson in the NeHe tutorial series.
* Originally written by Jeff Molofee.
*
* Authors: Jeff Molofee
* Olli Aalto
*/
module lesson01;

import derelict.opengl.gl;
import derelict.opengl.glu;
import derelict.sdl.sdl;

import tango.stdc.stringz;

/// The window title
const char[] WINDOW_TITLE = "NeHe's OpenGL Lesson 01 (D version)";

/// The main loop flag
bool running;

/**
* Module constructor. Here we load the GL, GLU and SDL shared libraries,
* and the initialize SDL.
*/
static this()
{
DerelictGL.load();
DerelictGLU.load();
DerelictSDL.load();

if (SDL_Init(SDL_INIT_VIDEO) < args =" the" fullscreen =" false;"> 1)
{
fullScreen = args[1] == "-fullscreen";
}

createGLWindow(WINDOW_TITLE, 640, 480, 16, fullScreen);
initGL();

running = true;
while (running)
{
processEvents();

drawGLScene();

SDL_GL_SwapBuffers();
SDL_Delay(10);
}
}

/**
* Process all the pending events.
*/
void processEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYUP:
keyReleased(event.key.keysym.sym);
break;
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
}

/**
* Process a key released event.
*/
void keyReleased(int key)
{
switch (key)
{
case SDLK_ESCAPE:
running = false;
break;
default:
break;
}
}

/**
* Resize and initialize the OpenGL window.
*/
void resizeGLScene(GLsizei width, GLsizei height)
{
if (height == 0)
{
height = 1;
}

// Reset The Current Viewport
glViewport(0, 0, width, height);

// Select The Projection Matrix
glMatrixMode(GL_PROJECTION);

// Reset The Projection Matrix
glLoadIdentity();

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f, cast(GLfloat)width / cast(GLfloat)height,
0.1f, 100.0f);

// Select The Modelview Matrix
glMatrixMode(GL_MODELVIEW);

// Reset The Modelview Matrix
glLoadIdentity();
}

/**
* Initialize OpenGL.
*/
void initGL()
{
// Enables Smooth Shading
glShadeModel(GL_SMOOTH);

// Black Background
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

// Depth Buffer Setup
glClearDepth(1.0f);

// Enables Depth Testing
glEnable(GL_DEPTH_TEST);

// The Type Of Depth Test To Do
glDepthFunc(GL_LEQUAL);

// Really Nice Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

/**
* The drawing function. Now we only clear the color and depht buffers, so that
* the window stays black.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Reset The Current Modelview Matrix
glLoadIdentity();
}

/**
* Initializes and opens the SDL window.
*/
void createGLWindow(char[] title, int width, int height, int bits,
bool fullScreen)
{
// Set the OpenGL attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

// Set the window title
SDL_WM_SetCaption(toUtf8z(title), null);

// Note the SDL_DOUBLEBUF flag is not required to enable double
// buffering when setting an OpenGL video mode.
// Double buffering is enabled or disabled using the
// SDL_GL_DOUBLEBUFFER attribute. (See above.)
int mode = SDL_OPENGL;
if (fullScreen)
{
mode |= SDL_FULLSCREEN;
}

// Now open a SDL OpenGL window with the given parameters
if (SDL_SetVideoMode(width, height, bits, mode) is null)
{
throw new Exception("Failed to open OpenGL window: " ~ getSDLError());
}

resizeGLScene(width, height);
}

/**
* Get the SDL error as a D string.
*
* Returns: A D string containing the current SDL error.
*/
char[] getSDLError()
{
return fromUtf8z(SDL_GetError());
}

You can download the code from here.