1. ## Math...

okay lets face it: I SUCK AT MATH...

Im finally starting to get some grip on basic C programming and mad a step forward by starting the OpenGL tutorials @ NeHe (which are in my opinion very clear for someone like me), but i looked on at the chapters and he's even gonna cover bump mapping etc, but I think my math sucks too much for this, does anyone have some tips for me to brush on with my logic and math skills, i really think it would make a difference.
(or am i just spitting BS as usual?)
thanx

2. I wouldn't let your knowledge of math or lack thereof deter you from programming. Personally I did not understand a lot of the math they taught me in school because it was just too abstract. But when you get to physically 'see' what the math is doing you will catch on very quick. Most of the math in 3D programming has already been done for you. Go over to www.gamedev.net and browse their many useful articles concerning matrices and 3D, math, etc. Most of the articles are very straightforward and do not dive into the formulas behind the 3D - though some do.

Most of the math in 3D is based on 2 simple equations called the perspective transform.

int screenx=(viewx*focus)/viewz;
int screeny=(viewy*focus)/viewz;
screenx+=center_screen_x;
screeny+=center_screen_y;

This will convert any 3D coord into 2D screen space. Try it for yourself and you will start to see it all come together. Then when you need more - consult some articles and try to implement them into your code as is. Later on with more knowledge you will be able to modify that code as well to suit your needs.

The focus is simply the distance the viewer is from the screen - or the projection plane to be technical. Basically small numbers are like smashing your face against the screen and large numbers would be like slowly walking away from the screen.

To get you started here is a very simple starfield example - I'm coding this from my head so you might wanna check it for errors.

I'll stick to simple C structures and will not dive into the graphics portion of the code.

Code:
```struct point2D
{
int x;
int y;
};

struct point3D
{
double x;
double y;
double z;
};

struct SimpleVertex
{
point3D Local;
point2D Screen;
};

#define NUMSTARS 100
#define VIEWDIST 320
#define CENTER_X 160
#define CENTER_Y 100
#define WHITE 15

SimpleVertex Stars[NUMSTARS];

void CreateStars(void);
void MoveStars(double speed);
void ProjectStars(void)
void DrawStars(void);

void CreateStars(void);
{
for (int i=0;i<NUMSTARS;i++)
{
Stars[i].Local.x=-320+random(640);
Stars[i].Local.y=-200+random(400);
Stars[i].Local.z=random(100);
}
}

void MoveStars(double speed)
{
for (int i=0;i<NUMSTARS;i++)
{
Stars[i].local.z+=speed;
if (Stars[i].local.z>100)
{
Stars[i].Local.x=-320+random(640);
Stars[i].Local.y=-200+random(400);
Stars[i].Local.z=random(100);
}
}
}

void ProjectStars(void)
{
for (int i=0;i<NUMSTARS;i++)
{
double x=Stars[i].Local.x;
double y=Stars[i].Local.y;
double z=Stars[i].Local.z;

if (z<1.0) z=1.0;
Stars[i].Screen.x=(int)((x*(double)VIEWDIST)/z+(double)CENTER_X);
Stars[i].Screen.y=(int)((y*(double)VIEWDIST)/z+(double)CENTER_Y);
}
}

void DrawStars(void)
{
for (int i=0;i<NUMSTARS;i++)
{
int x=Stars[i].Screen.x;
int y=Stars[i].Screen.y;
if (x>0 && x<320)
{
if (y>0 && y<200)
{
PlotPixel(x,y,WHITE);
}
}
}
}

int main(void)
{
double MySpeed=.5;
CreateStars();
while (!kbhit())
{
//Clear the screen here
MoveStars(MySpeed);
ProjectStars();
DrawStars();
}
return(0);
}```
I did not include the graphics stuff on purpose. PlotPixel() should do just what it says. You might have some data type problems inside of ProjectStars() when converting from double to int. If you do let me know and I'll fix it. Hope it works. Then try to code this on OpenGL or something. Hope you have a DOS platform - much of the problem in graphics now is that you are forced to learn an API which has a much steeper learning curve than just plain old DOS. No I'm not a DOS advocate, but it is simpler at first.

3. ## thanx for the replies

thanx guys tomorrow I'll take a deeper look into it (it's so quiet at work right now)
Code:
```// Pulsing Colors Based On Text Position
glColor3f(1.0f*float(cos(cnt1)),1.0f*float(sin(cnt2)),1.0f-0.5f*float(cos(cnt1+cnt2)));```
these sort of thing just confuse me

Allright.. ive been stdying for this entire day now figuring out, and it isnt as hard as it looks thanx!!

4. Bubba, I am quite a newbe in graphix programming and I am very interested in that stars program you made, so I tried to make it work as much as I could but I am missing the PlotPixel function and I have no idea how to make it, if it is not very complicated and you are willing to make the function and post it here for me to include into the program, I would really appreciate it.
This is youre program with only one error:
Code:
```#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;

#define NUMSTARS 100
#define VIEWDIST 320
#define CENTER_X 160
#define CENTER_Y 100
#define WHITE 15

struct point2D
{
int x;
int y;
};

struct point3D
{
double x;
double y;
double z;
};

struct SimpleVertex
{
point3D Local;
point2D Screen;
};

SimpleVertex Stars[NUMSTARS];

void CreateStars();
void MoveStars(double speed);
void ProjectStars();
void DrawStars();
int Random(int Limit);

void CreateStars()
{
for (int i=0;i<NUMSTARS;i++)
{
Stars[i].Local.x=-320+Random(640);
Stars[i].Local.y=-200+Random(400);
Stars[i].Local.z=Random(100);
}
}

void MoveStars(double speed)
{
for (int i=0;i<NUMSTARS;i++)
{
Stars[i].Local.z+=speed;
if (Stars[i].Local.z>100)
{
Stars[i].Local.x=-320+Random(640);
Stars[i].Local.y=-200+Random(400);
Stars[i].Local.z=Random(100);
}
}
}

void ProjectStars()
{
for (int i=0;i<NUMSTARS;i++)
{
double x=Stars[i].Local.x;
double y=Stars[i].Local.y;
double z=Stars[i].Local.z;

if (z<1.0) z=1.0;
Stars[i].Screen.x=(int)((x*(double)VIEWDIST)/z+(double)CENTER_X);
Stars[i].Screen.y=(int)((y*(double)VIEWDIST)/z+(double)CENTER_Y);
}
}

void DrawStars()
{
for (int i=0;i<NUMSTARS;i++)
{
int x=Stars[i].Screen.x;
int y=Stars[i].Screen.y;
if (x>0 && x<320)
{
if (y>0 && y<200)
{
PlotPixel(x,y,WHITE);
}
}
}
}

int Random(int Limit)
{
return (rand() % Limit + 1);
}

int main()
{
double MySpeed=.5;
CreateStars();

srand(GetTickCount());

while (!kbhit())
{
//Clear the screen here
system("cls");
MoveStars(MySpeed);
ProjectStars();
DrawStars();
}
return(0);
}```

5. Well it looks like you are in console mode which is not going to work. If you could get a small DirectX startup module working you could plot pixels via DirectX and pointers to your double buffer and primary surfaces.

The only way in console mode is to plot periods - which looks dumb and which is reverse of graphics. Text is in row,col which is actually y,x - also the values I used in the starfield program are much too large for text mode.

For DOS users this code will complete the program. Note that I used some assembly - but you do not have to. For flipping the back buffer to the screen you could memcpy() and for clearing the screen use memset(). Please no stupid comments about the code not being portable, only for DOS, blah, blah, blah....
Because this code can be used inside of a DirectX framework as well as D3D - but in D3D would be a bit different. The DirectX version of this code only lacks the back buffer and primary surface code (locking, unlocking, etc)- as well as the startup section.

Code:
```//y*320+x - most compilers should turn this into the following
#define XYTOMEM((y<<8)+(y<<6)+(x))

//BYTE typedef
typedef unsigned char BYTE;

//Real-mode pointers to double buffer and screen
BYTE far *Screen;
BYTE far *Buffer;

//Prototypes
void Init(void);
void CLS(BYTE far *tBuffer,BYTE color);
void Flip(void);
void PlotPixel(int x,int y,BYTE color);

//Init screen mode and pointers
void Init(void)
{
REGS regs;
regs.x.ax=0x0013;
int86(0x10,& regs,& regs);
Screen=(BYTE far *)MK_FP(0xa000,0);
Buffer=new BYTE[64000L];
//Should check for Buffer validity here, but didn't
}

//Clears any 64000 byte buffer to the set color
void CLS(BYTE far *tBuffer,BYTE color)
{
asm {

les       di,[tBuffer]
mov     cx,07D00h   //32000 words
mov     ah,[color]
mov     al,[color]
rep      stosw
}
}

//Copies memory - uses words, not bytes
//Copies back buffer to video memory
void Flip(void)
{
asm {

push      ds
lds         si,[Buffer]
les         di,[Screen]
mov       cx,07D00h
rep        movsw
pop       ds
}
}

//Plots a pixel - do not call this - place this in DrawStars() as is
//Calling this inside of the draw loop slows the program down
void PlotPixel(int x,int y,BYTE color)
{
Buffer[XYTOMEM(x,y)]=color;
}```
Here is the new main:

Code:
```int main(void)
{
double MySpeed=.5;
CreateStars();
while (!kbhit())
{
CLS(Buffer,0);
MoveStars(MySpeed);
ProjectStars();
DrawStars();
Flip();
}
return(0);
}```
Here is the new DrawStars()
Code:
```void DrawStars()
{
for (int i=0;i<NUMSTARS;i++)
{
int x=Stars[i].Screen.x;
int y=Stars[i].Screen.y;
if (x>0 && x<320)
{
if (y>0 && y<200)
{
Buffer[XYTOMEM(x,y)]=WHITE;
}
}
}
}```