#define _POSIX_C_SOURCE 200809L //for fileno and strdup #include #include #include #include #include #include #include #include #include "config.h" #include "common.h" #include "mouse.h" //#include "graphics_cs.h" //this header includes all the functions you'll need to implement if you want to port hackvr to something else #include "graphics_c3.h"//we're defining these functions in this file. #include "graphics_c2.h"//we're using these functions make them. #include "graphics_cs.h"//we'll need generic function that don't give a damn about which dimension it is? //TODO: will have to make some pixmaps get resized when the window does. //for now set them to be as big as you think you'll ever resize the window to. #define SKYRULE 90 #define SKYW (WIDTH*5) #define SKYH (HEIGHT/2) extern struct hvr_global global; struct gra_global gra_global; #ifdef GRAPHICAL /* real distance2(c2_t p1,c2_t p2) { return sqrt(( (p1.x-p2.x)*(p1.x-p2.x) )+( (p1.y-p2.y)*(p1.y-p2.y) )); } */ /* moved to math.c int between_angles(degrees d,real lower,real upper) { //lower may be higher than upper. //because lower is < 0 which wraps to higher. lower is 270, upper is 90. 270-90 is in front. if(lower > upper) { if(d.d > lower) return 1; if(d.d < upper) return 1; } if(upper > lower) { if(d.d > lower && d.d < upper) return 1; } return 0; } */ /* B (x2,y2) |-. c a| '-. | '-. '--------~ C b A (x1,y1) */ //I'll need this for collision I guess. /* //use this for finding a line that intersects with what the camera is pointing at c2_t get_c2_intersection(c2_t p1,real theta,c2_t p2) { real c; c=distance2(p1,p2); theta_a=C A B b = (c/1) * (theta_a + theta_offset) } int get_2D_intersection_X(x1,y1,theta_offset,x2,y2) { int x3a,y3a,x3b,y3b; int a,b,c;//lenght of sides. int theta_a,theta_b,theta_c;//angles opposite of same named sides. //get angle C A B theta_a= // x1,y1,x2,y2 //what are these d1 and d2? if(d1==d2) return global.math_error=1; c=dist(x1,y1,x2,y2); b = (c/1) * (theta_a + theta_offset); a = (c/1) * (theta_b + theta_offset); x3b=sin(theta_a) * b; y3b=cos(theta_a) * b; x3a=sin(theta_a) * a; y3a=cos(theta_a) * a; printf("x: %d %d\nx: %d %d\n",x3a,y3a,x3b,y3b); } int get_2D_intersection_Y(x,y,d,x,z,d) { int x3a,y3a,x3b,y3b; int a,b,c;//lenght of sides. int theta_a,theta_b,theta_c;//angles opposite of same named sides. //get angle from A to B. x1,y1,x2,y2 if(d1==d2) return global.math_error=1; c=dist(x1,y1,x2,y2); b = (c/1) * theta_a; a = (c/1) * theta_b; x3b=sin(a) * b; y3b=cos(a) * b; x3a=sin(a) * a; y3a=cos(a) * a; printf("y: %d %d\ny: %d %d\n",x3a,y3a,x3b,y3b); } */ c3_t c3_subtract(c3_t p1,c3_t p2) { return (c3_t){p1.x-p2.x,p1.y-p2.y,p1.z-p2.z}; } //how is this supposed to work? x is distance? #define MAGIC(x) (1.0l-(1.0l/pow(1.01l,(x)))) //??? might want to have some changables in here //#define MAGIC(x) (1.0l-(1.0l/pow(1.0001l,(x)))) //#define MAGIC(x) (-250.0l / x ) #define TOO_CLOSE (.25l) #define TOO_FAR (15l) //input is distance from camera point. real magic(real x) { return MAGIC(x); } //I need to figure out how far from each eye the view plane is. let's go with 1 unit? c2_t c3_to_c2(c3_group_rel_t eye,c3_t p3) { //DO NOT DRAW STUFF IN HERE c2_t p2; c3_t tmp1; // c3_t tmp2; // c3_t tmp3; c3_t final; //these rotations need to be about the previous axis after the axis itself has been rotated. //this rotation needs to not be applied to objects attached to the camera? tmp1=rotate_c3_yr(p3,eye.p,d2r(eye.r.y));//rotate everything around the camera's location. //now to rotate the shape around it's group's center. //final=rotate_c3_yr(p3,(c3_t){0,0,0},d2r(camera.yr));//rotate everything around the center no matter what. final=rotate_c3_xr(tmp1,eye.p,d2r(eye.r.x)); // final=rotate_c3_zr(tmp2,camera.p,d2r(camera.zr)); real delta_x=(eye.p.x - final.x);//I guess X needs this flippage too. real delta_y=(eye.p.y - final.y);//I dunno. Y is weird. real delta_z=(final.z - eye.p.z);//what are we supposed to do if this is 0? //real d=distance3(eye.p,final); real K=1;//arbitrary... tune this later. real x_prime= delta_x * K / delta_z; real y_prime= delta_y * K / delta_z; p2.x=global.zoom * (delta_x * MAGIC(delta_z) - delta_x); p2.y=global.zoom * (delta_y * MAGIC(delta_z) - delta_y);//this doesn't look right either. //p2.x=2 * (d * MAGIC(d) - delta_x); // this doesn't look quite right //p2.y=2 * (d * MAGIC(d) - delta_y); // dunno if this is better or not. return p2; } void draw_minimap_shape(c3_s_t s) {//this should replace the draw_minimap_line and actually do circles. //hrm... should I have functions for converting c3 points into minimap points? c2_s_t s2; s2.len=s.len; s2.id=s.id; int i=0; if(gra_global.drawminimap == 1) { for(i=0;i TOO_FAR) { //return;// } if(d < TOO_CLOSE) {//how close is too close? //return;//ha. not going to draw a shape that we're too close to. } } //all s2 needs to bet set before this loop. for(i=0;i 1) draw_minimap_line(s2.p[i],s2.p[(i+1)%s2.len]);//we shouldn't draw circles in here. //yeah. we probably should. s3.p[i]=c3_to_c2(eye,s2.p[i]);//we need to convert all points in the shape if we have to draw any parts of it. } draw_minimap_shape(s2); //if(gra_global.draw3d == 1) {//wireframe mode. set_ansi_color(s.attrib.col%16); draw_c2_shape(s3); //} if(gra_global.draw3d == 2) { //set foreground to a gray based on distance //between 0 to 100 // color_based_on_distance();//I don't have the distance in here. :/ //foreground_set(); //how... I want to draw the outline as one color and the fill as another. // foreground is set to color based on distance BEFORE we get here. // we need that function to tell us whether we're going to draw brighter or darker than middle. // then somehow get that information to here so we can pick the draw_mode... // darker is draw_mode_and(); brighter is draw_mode_or(); lol. set some global? XD hackhackhack //the color of this shape is set before it gets drawn. //which is a grey. if(s.attrib.col < 8) { //set_luminosity_color(s.attrib.lum); //draw_c2_filled_shape(s3);//why are we drawing this here? if(s.attrib.lum > 100) { draw_mode_or(); } else { draw_mode_and(); } } if(s.len != 2) {//no need to draw innards for lines. set_ansi_color(s.attrib.col%8); draw_c2_filled_shape(s3); } draw_mode_copy(); draw_c2_shape(s3); } } void draw_graph(real (*fun)(real x)) { c2_t pa; draw_c2_line((c2_t){LEFT,0},(c2_t){RIGHT,0}); draw_c2_line((c2_t){0,TOP},(c2_t){0,BOTTOM}); for(pa.x=LEFT;pa.xid); for(i=0;i< s->len+(s->len==1);i++) { if(gr) { curdist=shitdist2(p,rotate_c3_yr(c3_add(gr->p,s->p[i]),gr->p,d2r(gr->r.y))); } else { curdist=shitdist2(p,s->p[i]);//if there's no gr we're basically just this point. no rotation, not offests. } if(curdist > maxdist) maxdist=curdist; if(curdist < mindist) mindist=curdist; } return mindist; //return maxdist; //averaging it works ok, but I've decided to now use the farthest to say the distance something is. //why the fuck did we get group rotations each... nevermind. this code just sucks. /* real total=0; for(i=0;i< s->len+(s->len==1);i++) { c3_group_rel_t *gr=get_group_relative(s->id); total=total+shitdist2( rotate_c3_yr(//we're rotating the point around the camera... gr? c3_add(gr->p,rotate_c3_yr(s->p[i],gr->p,d2r(gr->r.y)))://after applying the rotation of the group it is in. s->p[i],global.camera.p ,d2r(global.camera.r.y)) ,global.camera.p); }//why the fuck are we rotating this around the camera? that shouldn't make any difference to the distance from the camera... return (total) / (real)(s->len+(s->len==1)); */ } void HatchLines(c2_t p1,c2_t p2,c2_t p3,int density) { real i=0; for(i=1;id) < (b->d)); } /* void draw_c3_point_text(c3_t p,char *text) { char tmp[256]; int direction,ascent,descent; cs_t p2; p2=c3_to_cs(p); snprintf(tmp,sizeof(tmp)-1,"(%f,%f,%f)",p.x,p.y,p.z); XTextExtents(font,text,strlen(text),&direction,&ascent,&descent,&overall); XDrawString(global.dpy,global.backbuffer,global.backgc,p2.x,p2.y+(descent+ascent),tmp,strlen(tmp)); }*/ #endif void draw_screen() { int i; int en=0;//eye number. different from "camera number" because a camera can have multiple eyes... a camera is like a "shape"??? hrm.. //char tmp[256]; zsort_t zs[SHAPES]; clear_backbuffer(); if(gra_global.split_screen > 1) { recalculate_eyes();//still have to redo this even if we only have one eye. } if(gra_global.split_screen == 1) { global.eye[0]=global.camera;//shortcut. } //return 0;//after this for(en=0;en 0 && zs[i-1].s) strcpy(global.selected_object,zs[i-1].s->id); // set_color();//restart each draw with the default color. if(gra_global.red_and_blue) { //set color for left half to red and right half to blue //and draw mode for the gc to GXOr red_and_blue_magic(); gra_global.xoff=0;//we're overlapping our drawing so no offset based on camera. } else { gra_global.xoff=(gra_global.width/gra_global.split_screen)*en; } if(!gra_global.red_and_blue) { set_clipping_rectangle(gra_global.xoff,0,gra_global.width/gra_global.split_screen,gra_global.height);// } if(gra_global.drawminimap == 3) { draw_graph(magic); continue; } if(gra_global.drawsky) { //draw_sky() should be a function in an engine specific file. //draw_sky();//???p? //XCopyArea(global.dpy,skypixmap,global.backbuffer,global.backgc,((camera.yr*5)+SKYW)%SKYW,0,WIDTH,global.height/2,0,0); } //if(gra_global.draw3d) {//wtf? why do I not compensate for camaera rotation along the x and z? //horizon line /* draw_c2_line((c2_t){LEFT, (int)((real)(global.camera.r.x.d) * (real)(BOTTOM+BOTTOM) / (real)90.0)}, (c2_t){RIGHT, (int)((real)(global.camera.r.x.d) * (real)(BOTTOM+BOTTOM) / (real)90.0)}); */ //} ///// shiiiit. I should be applying group rotations to all these shapes before sorting them. //when I do that. I need to make sure to take the group rotation out of draw_c3_shape()'s code. for(i=0;global.shape[i];i++) { zs[i].d=shitdist(zs[i].s,global.eye[en].p); } qsort(&zs,i,sizeof(zs[0]),(int (*)(const void *,const void *))compar);//sort these zs structs based on d. //draw all triangles //i already equals the length of the array. i-=gra_global.maxshapes; if(i<0) i=0; for(;global.shape[i];i++) { //now we pick the color of this triangle! if(gra_global.red_and_blue) {//this can be moved to the draw_c3_shape function and color can be set then. if(en%2==0) { set_color_red(); } else { set_color_blue(); } //tests of blending grayscale with red and blue // draw_c3_triangle(*(zs[i].t)); } else { // if(!strcmp(global.selected_object,zs[i].s->id)) { //XSetForeground(global.dpy,global.backgc,global.green.pixel); // } else { // } zs[i].s->attrib.lum=200-((int)(zs[i].d * 4.0l))%200; } //if(between_angles(points_to_angle((c2_t){zs[i].s->p[0].x,zs[i].s->p[0].z},(c2_t){camera.p.x,camera.p.z}),d2r(camera.yr+45),d2r(camera.yr+135))) { // set_color_based_on_distance(zs[i].d); draw_c3_shape(global.eye[en],*(zs[i].s));//the eye viewing it, and the shape //} } //we check here to see if the mouse button is still down if(gra_global.mousemap[MOUSE_PRIMARY]==-1) { printf("%s action %f %f\n",global.user,gra_global.mouse.x,gra_global.mouse.y); gra_global.mousemap[MOUSE_PRIMARY]=0; } /* if(gra_global.drawminimap == 1) { set_color(); c2_t t1=rotate_c2((c2_t){3*global.mmz,0},(c2_t){0,0},d2r(global.camera.r.y)); c2_t t2=rotate_c2((c2_t){-2*global.mmz,2*global.mmz},(c2_t){0,0},d2r(global.camera.r.y)); c2_t t3=rotate_c2((c2_t){-1*global.mmz,0},(c2_t){0,0},d2r(global.camera.r.y)); c2_t t4=rotate_c2((c2_t){-2*global.mmz,-2*global.mmz},(c2_t){0,0},d2r(global.camera.r.y)); draw_c2_line(t1,t2); draw_c2_line(t2,t3); draw_c2_line(t3,t4); draw_c2_line(t4,t1); }*/ // XSetForeground(global.dpy, global.backgc, global.green.pixel); /* set_color(); draw_c2_line((c2_t){0,0},rotate_c2((c2_t){40,0},(c2_t){0,0},d2r(global.eye[en].r.x))); set_color_red(); draw_c2_line((c2_t){0,0},rotate_c2((c2_t){-40,0},(c2_t){0,0},d2r((degrees){360-global.eye[en].r.y.d}))); set_color_blue(); draw_c2_line((c2_t){0,0},rotate_c2((c2_t){40,0},(c2_t){0,0},d2r(global.eye[en].r.z))); */ /* c3_t mouse_v3 = (c3_t){gra_global.mouse.x,gra_global.mouse.y,0};//dunno about the 'z' for mouse. set_color_red(); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){ 1,0,0}),c3_add(mouse_v3,(c3_t){ 5,0,0})); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){-1,0,0}),c3_add(mouse_v3,(c3_t){-5,0,0})); set_color(); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){0, 1,0}),c3_add(mouse_v3,(c3_t){0, 5,0})); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){0,-1,0}),c3_add(mouse_v3,(c3_t){0,-5,0})); set_color_blue(); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){0,0, 1}),c3_add(mouse_v3,(c3_t){0,0, 5})); draw_c3_line(global.eye[en],c3_add(mouse_v3,(c3_t){0,0,-1}),c3_add(mouse_v3,(c3_t){0,0,-5})); */ } //just draw a line from center to 40 away from the center at the angle of the camera's y-rotation //this should be minimap shit //draw a line from the center to 80 away from the center in the angle of what should point at the mouse. //draw_c2_line((c2_t){0,0},gra_global.mouse); //software mouse cursor /* set_color(); draw_c2_line(c2_add(gra_global.mouse,(c2_t){0,1}) , c2_add(gra_global.mouse,(c2_t){0,5}) ); draw_c2_line(c2_add(gra_global.mouse,(c2_t){0,-1}) , c2_add(gra_global.mouse,(c2_t){0,-5}) ); draw_c2_line(c2_add(gra_global.mouse,(c2_t){1,0}) , c2_add(gra_global.mouse,(c2_t){5,0}) ); draw_c2_line(c2_add(gra_global.mouse,(c2_t){-1,0}) , c2_add(gra_global.mouse,(c2_t){-5,0}) ); */ //if(points_on_same_side_of_line(gra_global.mouse,(c2_t){80,80},(c2_t){0,0},(c2_t){0,80})) { //draw_c2_line((c2_t){0,0},rotate_c2((c2_t){80,0},(c2_t){0,0},points_to_angle((c2_t){0,0},gra_global.mouse))); //} flipscreen(); } void redraw() {//something is requesting a redraw. if(gra_global.redrawplzkthx == 0) { gra_global.redrawplzkthx=1;//this is to prevent drawing way too often. //fprintf(stderr,"# in the redraw() function\n"); write(gra_global.redraw[1],"redrawplzkthx!\n",15); } } void recalculate_eyes() {//should I put the eyes into the global group_rel array so we can move them? int i; radians rad=d2r((degrees){global.camera.r.y.d+90}); //radians tmprad2=d2r((degrees){global.camera.r.y.d+90}); for(i=0;i