# Are you Math smart? solve this then

You will like this code. plug it in your NETMF emulator and you will have a 3D engine! The problem is that I get divide by zero exception when drawing the very center line. Can you fix this and you will win the challenge?

``````// Original code was found online by an artice done by a university professor over a year ago.
// I searched the web and not finding the original sources to attribute thsi code properly
// If you are teh one who wrote this code, THANK YOU. We owe you a beer!
// porting to C#/NETMF and further improvements are copyright GHI Electronics

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Media;

namespace engine3d
{
public class Program
{
static int w = 320;//width
static int h = 240;//height
const int mapWidth = 24;
const int mapHeight = 24;
static int[] worldMap = new int[mapWidth * mapHeight]{
2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,
1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1,
1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};

static Bitmap LCD = new Bitmap(320, 240);
public static void Main()
{

double posX = 20, posY = 10;  //x and y start position
double dirX = -1, dirY = 0; //initial direction vector
double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane

Color color;

while (true)
{
LCD.Clear();
for (int x = 0; x < w; x++)
{
//calculate ray position and direction
double cameraX = 2 * x / (double)(w) - 1; //x-coordinate in camera space

if (cameraX == 0)////////// REMOVE this to see center line but then your get divide by zero exception
continue;

double rayPosX = posX;
double rayPosY = posY;
double rayDirX = dirX + planeX * cameraX;
double rayDirY = dirY + planeY * cameraX;
//which box of the map we're in
int mapX = (int)rayPosX;
int mapY = (int)rayPosY;

//length of ray from current position to next x or y-side
double sideDistX;
double sideDistY;

//length of ray from one x or y-side to next x or y-side
double deltaDistX = System.Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
double deltaDistY = System.Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
double perpWallDist;

//what direction to step in x or y-direction (either +1 or -1)
int stepX;
int stepY;

int hit = 0; //was there a wall hit?
int side = 0; //was a NS or a EW wall hit?
//calculate step and initial sideDist
if (rayDirX < 0)
{
stepX = -1;
sideDistX = (rayPosX - mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
}
if (rayDirY < 0)
{
stepY = -1;
sideDistY = (rayPosY - mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
}
//perform DDA
while (hit == 0)
{
if (sideDistX < sideDistY)
{
mapX += stepX;
side = 0;
}
else
{
mapY += stepY;
side = 1;
}
//Check if ray has hit a wall
if (worldMap[mapX * mapWidth + mapY] > 0) hit = 1;
}
//Calculate distance projected on camera direction (oblique distance will give fisheye effect!)
if (side == 0)
perpWallDist = System.Math.Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
else
perpWallDist = System.Math.Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);

//Calculate height of line to draw on screen
int lineHeight = System.Math.Abs((int)(h / perpWallDist));

//calculate lowest and highest pixel to fill in current stripe
int drawStart = -lineHeight / 2 + h / 2;
if (drawStart < 0) drawStart = 0;
int drawEnd = lineHeight / 2 + h / 2;
if (drawEnd >= h) drawEnd = h - 1;

//choose wall color
switch (worldMap[mapX * mapWidth + mapY])
{
//select the color
case 1: color = ColorUtility.ColorFromRGB(200, 0, 0); break; //red
case 2: color = ColorUtility.ColorFromRGB(0, 200, 0); break; //green
case 3: color = ColorUtility.ColorFromRGB(0, 0, 200); break; //blue
case 4: color = ColorUtility.ColorFromRGB(200, 200, 200); break; //white
default: color = ColorUtility.ColorFromRGB(200, 200, 0); break; //yellow
}

//give x and y sides different brightness
if (side == 1)
{
color = ColorUtility.ColorFromRGB(
(byte)(ColorUtility.GetRValue(color)/2),
(byte)(ColorUtility.GetGValue(color) / 2),
(byte)(ColorUtility.GetBValue(color) / 2));
}

//draw the pixels of the stripe as a vertical line
LCD.DrawLine(color, 1, x, drawStart, x, drawEnd);//wall
LCD.DrawLine(ColorUtility.ColorFromRGB(200, 200, 40), 1, x, drawEnd, x, h-1);//floor
//LCD.Flush();//add this to see line by line!
}

//move forward till hit a wall
// =========NOTE we will crash at the end but this is okay for now
posX+= -0.1;

//flush
LCD.Flush();

}

}
}
}

``````

By the way, if you plug this on an actual board, let me know how fast it runs please.

@ Gus - This is a very common problem when working with 3D rendeding. The typical solution is to check for 0 and then assign a very small float to the value, this avoids the divide by 0 and generally does not cause much of a visual discrepancy since working with floats/double is already inaccurate. I use this same technique in the ray casting engine that I demo on the Spider.

``````
if (cameraX == 0) cameraX = 0.00001;

``````
1 Like

@ Gus - This is what you are aiming for

http://www.tinyclr.com/forum/topic?id=7045&page=3#msg69378

It runs ok on hydra & ChipworkX; Chrisâ€™ engine is much better for the Hyrda though.

My engine was running on the Spider but I cheated, I did it using RLP.

How did I forget about this! But i aiming to not use textures. Did you share the code?

Iâ€™ve got one Wouter created for me for GameSlate. Havenâ€™t shared the source yet though and itâ€™s RLP.

I was thinking about porting the non textured bit to Cerb with the new RLP PicoMax (now called Lucid Micro).

Which board(s) are you wanting this for?

oh man! I feel dumb I sent you an email

I used Double.Epsilon and float.Epsilon for the same purpose in XNA for a double-precision physics engine.
Appears to be implemented in MF too.

Well, I had forgotten about it until I saw your postâ€¦ Canâ€™t believe it has been nearly a year since I started with FEZ, time flies when you having fun.

I did not share the code, but for no reason other than I did not move much with it after those initial demos. If I get a chance I will clean it up, update it for 4.2 and put on code share.

Definitely an option, I like to use a simple number for debugging purposes. For example, if I have a bug I can easily tell if/when this value might have affected the numbers because the scaling effect is easy to identify. But that might be more psychological than anything else :).

The Gusbot never forgets, there was probably just a power glitch.