diff --git a/GL/clip.c b/GL/clip.c new file mode 100644 index 0000000..a5c101d --- /dev/null +++ b/GL/clip.c @@ -0,0 +1,34 @@ +#include +#include "clip.h" + +ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t) { + if(v1[2] < dist && v2[2] < dist) { + // Both behind, no clipping + return CLIP_RESULT_ALL_BEHIND; + } + + if(v1[2] > dist && v2[2] > dist) { + return CLIP_RESULT_ALL_IN_FRONT; + } + + float vec [] = {v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]}; + + /* + * The plane normal will always be pointing down the negative Z so we can simplify the dot products as x and y will always be zero + * the resulting calculation will result in simply -z of the vector + */ + float vecDotP = -vec[2]; + + /* If the dot product is zero there is no intersection */ + if(vecDotP > FLT_MIN || vecDotP < -FLT_MIN) { + *t = (-(dist - v1[2])) / vecDotP; + + vout[0] = v1[0] + (vec[0] * (*t)); + vout[1] = v1[1] + (vec[1] * (*t)); + vout[2] = v1[2] + (vec[2] * (*t)); + + return (v1[2] >= dist) ? CLIP_RESULT_FRONT_TO_BACK : CLIP_RESULT_BACK_TO_FRONT; + } else { + return CLIP_RESULT_ALL_ON_PLANE; + } +} diff --git a/GL/clip.h b/GL/clip.h new file mode 100644 index 0000000..c6a496b --- /dev/null +++ b/GL/clip.h @@ -0,0 +1,22 @@ +#ifndef CLIP_H +#define CLIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + CLIP_RESULT_ALL_IN_FRONT, + CLIP_RESULT_ALL_BEHIND, + CLIP_RESULT_ALL_ON_PLANE, + CLIP_RESULT_FRONT_TO_BACK, + CLIP_RESULT_BACK_TO_FRONT +} ClipResult; + +ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t); + +#ifdef __cplusplus +} +#endif + +#endif // CLIP_H diff --git a/GL/private.h b/GL/private.h index 5f837c1..eac62de 100644 --- a/GL/private.h +++ b/GL/private.h @@ -4,7 +4,7 @@ #include "../include/gl.h" #include "../containers/aligned_vector.h" #include "../containers/named_array.h" - +#include "./clip.h" #define TRACE_ENABLED 0 #define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);} diff --git a/Makefile b/Makefile index 5dc4723..4f25a13 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ TARGET = libGLdc.a OBJS = GL/draw.o GL/flush.o GL/framebuffer.o GL/immediate.o GL/lighting.o GL/state.o GL/texture.o GL/glu.o -OBJS += GL/matrix.o GL/fog.o GL/error.o containers/stack.o containers/named_array.o containers/aligned_vector.o +OBJS += GL/matrix.o GL/fog.o GL/error.o GL/clip.o containers/stack.o containers/named_array.o containers/aligned_vector.o SUBDIRS = diff --git a/samples/Makefile b/samples/Makefile index b9394f1..c3bdd7c 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -12,4 +12,8 @@ all: $(KOS_MAKE) -C nehe03 all $(KOS_MAKE) -C nehe06 all $(KOS_MAKE) -C ortho2d all - $(KOS_MAKE) -C lerabot01 all \ No newline at end of file +<<<<<<< HEAD + $(KOS_MAKE) -C lerabot01 all +======= + $(KOS_MAKE) -C zclip all +>>>>>>> 5b05039dfd461861a8541aa66ea325f59bb9f746 diff --git a/samples/zclip/Makefile b/samples/zclip/Makefile new file mode 100644 index 0000000..8194677 --- /dev/null +++ b/samples/zclip/Makefile @@ -0,0 +1,29 @@ +TARGET = zclip.elf +OBJS = main.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: + -rm -f $(TARGET) $(OBJS) romdisk.* + +rm-elf: + -rm -f $(TARGET) romdisk.* + +$(TARGET): $(OBJS) romdisk.o + $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ + $(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS) + +romdisk.img: + $(KOS_GENROMFS) -f romdisk.img -d romdisk -v + +romdisk.o: romdisk.img + $(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o + +run: $(TARGET) + $(KOS_LOADER) $(TARGET) + +dist: + rm -f $(OBJS) romdisk.o romdisk.img + $(KOS_STRIP) $(TARGET) diff --git a/samples/zclip/main.c b/samples/zclip/main.c new file mode 100644 index 0000000..566ab25 --- /dev/null +++ b/samples/zclip/main.c @@ -0,0 +1,265 @@ +#include +#include +#include + +#include "gl.h" +#include "glu.h" +#include "glkos.h" + +extern uint8 romdisk[]; +KOS_INIT_ROMDISK(romdisk); + + +/* Image type - contains height, width, and data */ +typedef struct // Create A Structure +{ + GLubyte *imageData; // Image Data (Up To 32 Bits) + GLuint bpp; // Image Color Depth In Bits Per Pixel + GLuint width; // Image Width + GLuint height; // Image Height + GLuint texID; // Texture ID Used To Select A Texture +} TextureImage; // Structure Name + + +TextureImage textures[3]; +TextureImage road; + + +GLboolean LoadTGA(TextureImage *texture, const char *filename) // Loads A TGA File Into Memory +{ + GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header + GLubyte TGAcompare[12]; // Used To Compare TGA Header + GLubyte header[6]; // First 6 Useful Bytes From The Header + GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File + GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram + GLuint temp; // Temporary Variable + GLuint type=GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP) + + FILE *file = fopen(filename, "rb"); // Open The TGA File + + if( file==NULL || // Does File Even Exist? + fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) || // Are There 12 Bytes To Read? + memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 || // Does The Header Match What We Want? + fread(header,1,sizeof(header),file)!=sizeof(header)) // If So Read Next 6 Header Bytes + { + if (file == NULL) { // Did The File Even Exist? *Added Jim Strong* + fprintf(stderr, "Missing file\n"); + return GL_FALSE; // Return False + } else + { + fprintf(stderr, "Invalid format\n"); + fclose(file); // If Anything Failed, Close The File + return GL_FALSE; // Return False + } + } + + texture->width = header[1] * 256 + header[0]; // Determine The TGA Width (highbyte*256+lowbyte) + texture->height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte) + + if( texture->width <=0 || // Is The Width Less Than Or Equal To Zero + texture->height <=0 || // Is The Height Less Than Or Equal To Zero + (header[4]!=24 && header[4]!=32)) // Is The TGA 24 or 32 Bit? + { + fprintf(stderr, "Wrong format\n"); + fclose(file); // If Anything Failed, Close The File + return GL_FALSE; // Return False + } + + texture->bpp = header[4]; // Grab The TGA's Bits Per Pixel (24 or 32) + bytesPerPixel = texture->bpp/8; // Divide By 8 To Get The Bytes Per Pixel + imageSize = texture->width*texture->height*bytesPerPixel; // Calculate The Memory Required For The TGA Data + + texture->imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data + + if( texture->imageData==NULL || // Does The Storage Memory Exist? + fread(texture->imageData, 1, imageSize, file)!=imageSize) // Does The Image Size Match The Memory Reserved? + { + if(texture->imageData!=NULL) // Was Image Data Loaded + free(texture->imageData); // If So, Release The Image Data + + fclose(file); // Close The File + return GL_FALSE; // Return False + } + + GLuint i; + for(i = 0; i < (int)imageSize; i += bytesPerPixel) // Loop Through The Image Data + { // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue) + temp=texture->imageData[i]; // Temporarily Store The Value At Image Data 'i' + texture->imageData[i] = texture->imageData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte + texture->imageData[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value) + } + + fclose (file); // Close The File + + // Build A Texture From The Data + glGenTextures(1, &texture[0].texID); // Generate OpenGL texture IDs + + glBindTexture(GL_TEXTURE_2D, texture[0].texID); // Bind Our Texture + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtered + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtered + + if (texture[0].bpp==24) // Was The TGA 24 Bits + { + type=GL_RGB; // If So Set The 'type' To GL_RGB + } + + glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData); + + return GL_TRUE; // Texture Building Went Ok, Return True +} +// Load Bitmaps And Convert To Textures +void LoadGLTextures() { + const char* filenames [] = { + "/rd/facade00.tga", + "/rd/facade01.tga", + "/rd/facade02.tga" + }; + + GLubyte i; + for(i = 0; i < 3; ++i) { + LoadTGA(&textures[i], filenames[i]); + } + + if(!LoadTGA(&road, "/rd/floor.tga")) { + fprintf(stderr, "Error loading road texture"); + } +}; + + +/* A general OpenGL initialization function. Sets all of the initial parameters. */ +void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. +{ + LoadGLTextures(); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black + glClearDepth(1.0); // Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LESS); // The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST); // Enables Depth Testing + glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); // Reset The Projection Matrix + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window + + glMatrixMode(GL_MODELVIEW); +} + +/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ +void ReSizeGLScene(int Width, int Height) +{ + if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small + Height = 1; + + glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); + glMatrixMode(GL_MODELVIEW); +} + + +void RenderTower(counter) { + counter = counter % 3; + float height = (counter + 1) * 5.0f; + float width = 3.5f; + + float v = 1.0f * (counter + 1); + + glBindTexture(GL_TEXTURE_2D, textures[counter].texID); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(-width, 0,-width); + glTexCoord2f(1, 0); + glVertex3f(-width, 0, width); + glTexCoord2f(1, v); + glVertex3f(-width, height, width); + glTexCoord2f(0, v); + glVertex3f(-width, height,-width); + + glTexCoord2f(0, 0); + glVertex3f(-width, 0, width); + glTexCoord2f(1, 0); + glVertex3f( width, 0, width); + glTexCoord2f(1, v); + glVertex3f( width, height, width); + glTexCoord2f(0, v); + glVertex3f(-width, height, width); + + glTexCoord2f(0, 0); + glVertex3f(width, 0,width); + glTexCoord2f(1, 0); + glVertex3f(width, 0,-width); + glTexCoord2f(1, v); + glVertex3f(width, height,-width); + glTexCoord2f(0, v); + glVertex3f(width, height, width); + glEnd(); +} + + +void RenderFloor() { + glBindTexture(GL_TEXTURE_2D, road.texID); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(-100, 0, -0.0); + glTexCoord2f(50.0f, 0.0f); + glVertex3f( 100, 0, -0.0); + glTexCoord2f(50.0f, 100.0f); + glVertex3f( 100, 0, -200.0); + glTexCoord2f(0.0f, 100.0f); + glVertex3f(-100, 0, -200.0); + glEnd(); +} + +/* The main drawing function. */ +void DrawGLScene() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset The View + + GLubyte i = 0; + + glPushMatrix(); + glTranslatef(0.0f, -5.0f, 10.0f); + RenderFloor(); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-8.5f, -5.0f,-16.0f); // Move Left 1.5 Units And Into The Screen 6.0 + + for(i = 0; i < 10; ++i) { + RenderTower(i); + glTranslatef(0, 0, -8.0f); + } + glPopMatrix(); + + glPushMatrix(); + glTranslatef(8.5f, -5.0f,-16.0f); // Move Left 1.5 Units And Into The Screen 6.0 + + for(i = 1; i < 11; ++i) { + RenderTower(i); + glTranslatef(0, 0, -8.0f); + } + glPopMatrix(); + + // swap buffers to display, since we're double buffered. + glKosSwapBuffers(); +} + +int main(int argc, char **argv) +{ + glKosInit(); + + InitGL(640, 480); + ReSizeGLScene(640, 480); + + while(1) { + DrawGLScene(); + } + + return 0; +} diff --git a/samples/zclip/romdisk/PLACEHOLDER b/samples/zclip/romdisk/PLACEHOLDER new file mode 100644 index 0000000..e69de29 diff --git a/samples/zclip/romdisk/facade00.tga b/samples/zclip/romdisk/facade00.tga new file mode 100755 index 0000000..d061c48 Binary files /dev/null and b/samples/zclip/romdisk/facade00.tga differ diff --git a/samples/zclip/romdisk/facade01.tga b/samples/zclip/romdisk/facade01.tga new file mode 100755 index 0000000..fde4039 Binary files /dev/null and b/samples/zclip/romdisk/facade01.tga differ diff --git a/samples/zclip/romdisk/facade02.tga b/samples/zclip/romdisk/facade02.tga new file mode 100755 index 0000000..210393a Binary files /dev/null and b/samples/zclip/romdisk/facade02.tga differ diff --git a/samples/zclip/romdisk/floor.tga b/samples/zclip/romdisk/floor.tga new file mode 100644 index 0000000..1e2799c Binary files /dev/null and b/samples/zclip/romdisk/floor.tga differ