#define _POSIX_C_SOURCE 200809L //for fileno and strdup #define _BSD_SOURCE #include #include #include #include #include #include #include //#include //code to use select instead of non-blocking is commented out. might decide to use it later. #include #include #include #include //for size hints #include #define __USE_GNU //for longer math constants #include int oldtime=0; int oldfps=0; int fps=0; //TODO: optimizations //TODO: store caches of cs_t, c2_t, and c3_t numbers. //TODO: don't forget to remake gophervr with this. //TODO: XSegment or line structs to store some shit? //TODO: line and triangle intersection for finding what object was clicked on //if I don't do hiliting I only need to calculate that upon click. #define WALK_SPEED 1 #define SPLIT_SCREEN 2 #define CAMERA_SEPARATION 4 #define RED_AND_BLUE 1 #define SHAPES 16386 #define MAX_SIDES 8 #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) typedef double long real; //think this conflicts? //typedef float real; //think this conflicts? typedef struct { real x; real y; real z; } c3_t; typedef struct { real x; real y; } c2_t; typedef struct { //same as XPoint, just use that? nah... short x; short y; } cs_t; //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 WIDTH 1024 #define HEIGHT 768 #define SKYRULE 90 #define SKYW (WIDTH*5) #define SKYH (HEIGHT/2) Pixmap skypixmap; char sky[SKYH][SKYW]; struct object_1 { int type; unsigned char x; unsigned char y; unsigned char z; }; struct object_2 { int type; unsigned short x; unsigned short y; unsigned short z; }; struct object_4 { int type; unsigned int x; unsigned int y; unsigned int z; }; struct camera { c3_t p; int xr;//rotations int yr; int zr; real zoom; } camera; struct c3_line { char *id; c3_t p1; c3_t p2; }; struct c3_shape {//use array or linked list? char *id; unsigned char len; c3_t p[MAX_SIDES]; }; struct mainwin { int x; int y; unsigned int depth; int mousex; int mousey; int rmousex; int rmousey; int buttonpressed; unsigned int width; unsigned int height; unsigned int border_width; XColor colors[256]; int xoff; int math_error; int mapxoff; int mapyoff; int split_screen; int split_flip;//1 or -1 char *user; char greyscale; char drawminimap;//flag char draw3d;//flag char debug;//flag char drawsky;//flag char zsort; char red_and_blue; char force_redraw; char selected_object[256];//meh real mmz; XColor green; XColor red; XColor blue; XColor redblue[2]; Colormap color_map; Display *dpy; Window w; Pixmap backbuffer; Pixmap cleanbackbuffer; GC gc; GC backgc; struct c3_shape *shape[SHAPES]; int shapes; int derp; int root_window; real split; } global; //used to figure out what c2 values are associated with each edge of the window. //#define TOP 160.0 //#define BOTTOM -160.0 #define TOP 240.0 #define BOTTOM -240.0 #define RIGHT 320.0 #define LEFT -320.0 int c2sX(long double x) { return (global.width/(global.split_screen / (global.red_and_blue ? global.split_screen: 1))) * ((x + RIGHT) / (RIGHT *2)) + global.xoff; } int s2cX(long double x) { return (x/(global.width/(global.split_screen / (global.red_and_blue?global.split_screen :1))))*(RIGHT*2)-RIGHT; } int c2sY(long double y) { return global.height * ((TOP-y) / (TOP*2)); } int s2cY(long double y) { return -((y/global.height) * (TOP*2) - TOP); } cs_t c2_to_cs(c2_t p) { return (cs_t){c2sX(p.x),c2sY(p.y)}; } c2_t cs_to_c2(cs_t p) { return (c2_t){s2cX(p.x),s2cY(p.y)}; } long double distance2(c2_t p1,c2_t p2) { return sqrtl(( (p1.x-p2.x)*(p1.x-p2.x) )+( (p1.y-p2.y)*(p1.y-p2.y) )); } long double distance3(c3_t p1,c3_t p2) { return sqrtl(( (p1.x-p2.x)*(p1.x-p2.x) )+( (p1.y-p2.y)*(p1.y-p2.y) )+( (p1.z-p2.z)*(p1.z-p2.z) )); } long double points_to_angle(c2_t p1,c2_t p2) { long double a=atan2l(p2.y-p1.y,p2.x-p1.x); return a>=0?a:M_PIl+M_PIl+a; } long double d2r(int d) { while(d<0) d+=360; return (long double)(d%360) / (long double)180 * M_PIl; } int r2d(real r) { return r / M_PIl * 180; } int between_angles(real angle,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(angle > lower) return 1; if(angle < upper) return 1; } if(upper > lower) { if(angle > lower && angle < 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); } */ void draw_cs_line(cs_t p1,cs_t p2) { XDrawLine(global.dpy,global.backbuffer,global.backgc,p1.x,p1.y,p2.x,p2.y); } void draw_c2_line(c2_t p1,c2_t p2) { draw_cs_line(c2_to_cs(p1),c2_to_cs(p2)); } #define MAGIC(x) (1.0l-(1.0l/powl(1.01l,(x)))) //??? might want to have some changables in here real magic(real x) { return MAGIC(x); } 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.xlen;i++) s->p[0]=rotate_c3_yr(s->p[0],camera.p,camera.yr); } c2_t c3_to_c2(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. final=rotate_c3_yr(p3,camera.p,d2r(camera.yr));//rotate everything around the camera's location. // final=rotate_c3_yr(p3,(c3_t){0,0,0},d2r(camera.yr));//rotate everything around the center no matter what. // tmp2=rotate_c3_xr(tmp1,camera.p,d2r(camera.xr)); // final=rotate_c3_zr(tmp2,camera.p,d2r(camera.zr)); real delta_x=(camera.p.x - final.x); real delta_y=(camera.p.y - final.y); real delta_z=(camera.p.z - final.z); // real d=distance3(camera.p,final); p2.y=camera.zoom * (delta_y * MAGIC(delta_z) - delta_y); p2.x=camera.zoom * (delta_x * MAGIC(delta_z) - delta_x); return p2; } void draw_c3_line(c3_t p1,c3_t p2) { // if(!between_angles(points_to_angle((c2_t){camera.p.x,camera.p.z},(c2_t){p1.x,p1.z}),0,90) || // !between_angles(points_to_angle((c2_t){camera.p.x,camera.p.z},(c2_t){p2.x,p2.z}),0,90)) return; if(global.drawminimap == 1) { draw_c2_line((c2_t){(camera.p.x-2)*global.mmz,(camera.p.z+2)*global.mmz},(c2_t){(camera.p.x+2)*global.mmz,(camera.p.z-2)*global.mmz}); draw_c2_line((c2_t){(camera.p.x+2)*global.mmz,(camera.p.z+2)*global.mmz},(c2_t){(camera.p.x-2)*global.mmz,(camera.p.z-2)*global.mmz}); draw_c2_line((c2_t){p1.x*global.mmz,p1.z*global.mmz},(c2_t){p2.x*global.mmz,p2.z*global.mmz}); } if(global.drawminimap == 2) {//map rotates. c3_t t1=rotate_c3_yr(p1,camera.p,d2r(camera.yr)); c3_t t2=rotate_c3_yr(p2,camera.p,d2r(camera.yr)); draw_c2_line((c2_t){t1.x*global.mmz,t1.z*global.mmz},(c2_t){t2.x*global.mmz,t2.z*global.mmz}); } if(global.draw3d != 0) draw_c2_line(c3_to_c2(p1),c3_to_c2(p2)); if(global.debug) { } } cs_t c3_to_cs(c3_t p) { return c2_to_cs(c3_to_c2(p)); } real shitdist2(c3_t p1,c3_t p2) { return sqrtl(((p1.x - p2.x) * (p1.x - p2.x)) + ((p1.y - p2.y) * (p1.y - p2.y)) + ((p1.z - p2.z) * (p1.z - p2.z))); } real shitdist(struct c3_shape s,c3_t p) { // apply rotation then find distance? int i; struct c3_shape s_; real total; s_=s; rotate_shape_yr(&s_); for(i=0;id) > (b->d)); } /* void draw_c3_point_text(c3_t p,char *text) { char coords[256]; int direction,ascent,descent; cs_t p2; p2=c3_to_cs(p); snprintf(coords,sizeof(coords)-1,"(%Lf,%Lf,%Lf)",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),coords,strlen(coords)); }*/ void draw_screen(Display *dpy,Window w,GC gc) { int i; int colori=100; int cn=0;//camera number. XFontStruct *font=XLoadQueryFont(global.dpy,"fixed"); XCharStruct overall; int direction,ascent,descent; char coords[256]; XGCValues gcval; zsort_t zs[SHAPES]; XCopyArea(global.dpy,global.cleanbackbuffer,global.backbuffer,gc,0,0,global.width,global.height,0,0);//clear the backbuffer. // XCopyPlane(global.dpy,global.cleanbackbuffer,global.backbuffer,gc,0,0,global.width,global.height,0,0,1);//clear the backbuffer. XRectangle cliprect; cliprect.x=0; cliprect.y=0; cliprect.width=global.width/global.split_screen; cliprect.height=global.height; real oldx=camera.p.x; real oldz=camera.p.z; if(global.split_screen > 1) { camera.p.z-=(global.split_flip)*((global.split/global.split_screen)*cosl(d2r(camera.yr+180))); camera.p.x-=(global.split_flip)*((global.split/global.split_screen)*sinl(d2r(camera.yr+180))); } for(cn=0;cnid); } for(i=0;global.shape[i];i++) { //now we pick the color of this triangle! if(global.red_and_blue) { if(cn==0) { XSetForeground(global.dpy,global.backgc,global.red.pixel); } else { XSetForeground(global.dpy,global.backgc,global.blue.pixel); } //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 { if(global.greyscale) { if(zs[i].d > 0) { if(zs[i].d < 10) { colori=zs[i].d; } } XSetForeground(global.dpy,global.backgc,global.colors[(int)(100.0-(colori * 10.0))].pixel); } } } draw_c3_shape(*(zs[i].s)); } XSetForeground(global.dpy, global.backgc, global.green.pixel); if(global.debug) { snprintf(coords,sizeof(coords)-1,"selected object: %s",global.selected_object); XTextExtents(font,coords,strlen(coords),&direction,&ascent,&descent,&overall); XDrawString(global.dpy,global.backbuffer,global.backgc,global.xoff,global.height/2+(descent+0+ascent)*5,coords,strlen(coords)); } camera.p.z+=(global.split_flip)*(global.split*cosl(d2r(camera.yr+180))); camera.p.x+=(global.split_flip)*(global.split*sinl(d2r(camera.yr+180))); } //TODO: figure out what all this shit is and either update or remove. //DONT USE WIDTH for shit. /* x1=nextX(WIDTH/2,HEIGHT/2,d2r(camera.yr),40); y1=nextY(WIDTH/2,HEIGHT/2,d2r(camera.yr),40); x2=nextX(WIDTH/2,HEIGHT/2,d2r(camera.yr+180),80); y2=nextY(WIDTH/2,HEIGHT/2,d2r(camera.yr+180),80); XDrawLine(global.dpy,w,gc,WIDTH/2,HEIGHT/2,x1,y1); XDrawLine(global.dpy,w,gc,WIDTH/2,HEIGHT/2,x2,y2); XDrawLine(global.dpy,w,gc,0,HEIGHT/2,WIDTH,HEIGHT/2); x1=global.mousex; y1=global.mousey; real a=points_to_angle((c2_t){0,0},cs_to_c2((cs_t){x1,y1})); snprintf(coords,sizeof(coords)-1,"%llf",a); XTextExtents(font,coords,strlen(coords),&direction,&ascent,&descent,&overall); XDrawString(global.dpy,w,gc,global.xoff,(descent+0+ascent)*6,coords,strlen(coords)); snprintf(coords,sizeof(coords)-1,"%llf",points_to_angle(cs_to_c2((cs_t){global.mousex,global.mousey}),(c2_t){0,0})+(M_PIl/2)); XTextExtents(font,coords,strlen(coords),&direction,&ascent,&descent,&overall); XDrawString(global.dpy,w,gc,global.xoff,(descent+0+ascent)*7,coords,strlen(coords)); XDrawLine(global.dpy,w,gc,global.mousex,global.mousey,global.width/2,global.height/2); real c=cosl(d2r(camera.yr) - a) * distance((c2_t){x1,y1},(c2_t){WIDTH/2,HEIGHT/2}); x2=nextX(x1,y1,d2r(camera.yr-90),c); y2=nextY(x1,y1,d2r(camera.yr-90),c); XDrawLine(global.dpy,w,gc,x1,y1,x2,y2); */ camera.p.x = oldx; camera.p.z = oldz; //-= cn*CAMERA_SEPARATION; // XClearWindow(global.dpy, w); XCopyArea(global.dpy,global.backbuffer,w,gc,0,0,global.width,global.height,0,0);//move backbuffer to window // XCopyPlane(global.dpy,global.backbuffer,w,gc,0,0,global.width,global.height,0,0,0x000100);//move backbuffer to window } /* does not return the newline. */ char *read_line_hack(FILE *fp,int len) { short in; char *t; switch(in=fgetc(fp)) { case '\n': t=malloc(len+1); t[len]=0; return t; case -1: return 0; default: if((t=read_line_hack(fp,len+1))) t[len]=in; break; } return t; } //warning: clobbers input //skips leading and trailing space. //compresses multiple spaces to one. //return length of array char **line_splitter(char *line,int *rlen) { char **a; int len,i=0; len=1;//we're just counting how much we'll need the first loop through. for(i=0;line[i] && line[i] == ' ';i++);//skip leading space for(;line[i];len++) { for(;line[i] && line[i] != ' ';i++);//skip rest of data for(;line[i] && line[i] == ' ';i++);//skip rest of space } a=malloc(sizeof(char *) * len+1); a[len]=0; len=0;//reuse! for(i=0;line[i] && line[i] == ' ';i++);//skip leading space a[len]=line+i; for(;;) { for(;line[i] && line[i] != ' ';i++);//skip rest of data if(!line[i]) break; line[i++]=0; for(;line[i] && line[i] == ' ';i++);//skip rest of space if(!line[i]) break; a[++len]=line+i; } a[++len]=0; *rlen=len; return a; } void set_aspect_ratio() { XSizeHints *hints=XAllocSizeHints(); hints->min_aspect.x=4*(global.split_screen / (global.red_and_blue ? global.split_screen : 1)); hints->min_aspect.y=3; hints->max_aspect.x=4*(global.split_screen / (global.red_and_blue ? global.split_screen : 1)); hints->max_aspect.y=3; hints->flags=PAspect; XSetWMNormalHints(global.dpy,global.w,hints); } int load_stdin() { struct c3_shape s; // struct c3_line l; char *command; char *line; char *id; char **a; int len; int ret=0; int j,k,l; //struct timeval timeout; //fd_set master; //fd_set readfs; //FD_ZERO(&master); //FD_ZERO(&readfs); //FD_SET(0,&master);//just stdin. int i;//used to store the last triangle. even though I have a global for that. >_> // printf("# entering load_stdin()\n"); for(i=0;global.shape[i];i++) ;//hop to the end. fcntl(0,F_SETFL,O_NONBLOCK); if(feof(stdin)) { clearerr(stdin); } // readfs=master; // timeout.tv_sec=0; // timeout.tv_usec=1; // if((j=select(1,&readfs,0,0,&timeout)) == -1) { // perror("select"); // return 0; // } // if(FD_ISSET(0,&readfs)) { while((line=read_line_hack(stdin,0))) {//load as long there's something to load if(*line == '#') return 0; //printf("# read command: %s\n",line); a=line_splitter(line,&len); if(len > 1) { id=a[0]; command=a[1]; } else { printf("Ohhhh. shit.\n"); return 0; } ret=1; if(!strcmp(command,"deleteallexcept")) { for(j=0;global.shape[j];j++) {//mark first. compress later. if(strcmp(global.shape[j]->id,a[2])) {//TODO: memory leak! //free(global.triangle[j]->id); //free(global.triangle[j]); global.shape[j]=0; } } l=0; for(k=0;kid,s.id)) {//??? where is s.id supposed to be set from? free(global.shape[j]->id); free(global.shape[j]); global.shape[j]=0; } } l=0; for(k=0;kid,a[2])) { free(global.shape[j]->id); global.shape[j]->id=strdup(id); } } } continue; } if(!strcmp(command,"renamegroup")) { if(len == 4) { for(j=0;global.shape[j];j++) { if(!strcmp(global.shape[j]->id,a[2])) { free(global.shape[j]->id); global.shape[j]->id=strdup(a[3]); } } } continue; } if(!strcmp(command,"export")) { for(j=0;global.shape[j];j++) { if(!strcmp(global.shape[j]->id,a[2])) { // to=global.shape[j]; // printf("%s addshape %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf\n",a[2], // to->p1.x,to->p1.y,to->p1.z, // to->p2.x,to->p2.y,to->p2.z, // to->p3.x,to->p3.y,to->p3.z // ); } } continue; } if(!strcmp(command,"dump")) { printf("%s set camera.p.x %Lf\n",global.user,camera.p.x); printf("%s set camera.p.y %Lf\n",global.user,camera.p.y); printf("%s set camera.p.z %Lf\n",global.user,camera.p.z); printf("%s set camera.xr %d\n",global.user,camera.xr); printf("%s set camera.yr %d\n",global.user,camera.yr); printf("%s set camera.zr %d\n",global.user,camera.zr); printf("%s set camera.zoom %Lf\n",global.user,camera.zoom); continue; } if(!strcmp(command,"quit")) { return -1; } if(!strcmp(command,"set")) { //set variable //TODO: add more things to this. if(len != 3 && len != 4) continue; if(len == 4) { if(!strcmp(a[2],"camera.p.x")) camera.p.x=strtold(a[3],0); else if(!strcmp(a[2],"camera.p.y")) camera.p.y=strtold(a[3],0); else if(!strcmp(a[2],"camera.p.z")) camera.p.z=strtold(a[3],0); else if(!strcmp(a[2],"camera.zoom")) camera.zoom=strtold(a[3],0); else if(!strcmp(a[2],"camera.xr")) camera.xr=atoi(a[3]); else if(!strcmp(a[2],"camera.yr")) camera.yr=atoi(a[3]); else if(!strcmp(a[2],"camera.zr")) camera.zr=atoi(a[3]); else printf("# unknown variable: %s\n",a[2]); continue; } if(!strcmp(a[2],"force_redraw")) global.force_redraw^=1; else if(!strcmp(a[2],"red_and_blue")) { global.red_and_blue^=1; set_aspect_ratio(); } else { printf("# unknown variable: %s\n",a[2]); continue; } printf("# %s toggled!\n",a[2]); continue; } if(!strcmp(command,"addshape")) { if(len > 3) { global.shape[i]=malloc(sizeof(struct c3_shape)); global.shape[i]->id=strdup(id); global.shape[i]->len=strtold(a[2],0); for(j=0;j < global.shape[i]->len;j++) { global.shape[i]->p[j].x=strtold(a[(j*3)+3],0);//second arg is just for a return value. set to 0 if you don't want it. global.shape[i]->p[j].y=strtold(a[(j*3)+4],0); global.shape[i]->p[j].z=strtold(a[(j*3)+5],0); } i++; global.shapes=i; global.shape[i]=0; } else { printf("# ERROR: wrong amount of parts for addshape. got: %d expected: 11\n",len); } continue; } if(!strcmp(command,"scaleup")) {//should this scale separately so it can be a deform too? for(i=0;global.shape[i];i++) { if(!strcmp(global.shape[i]->id,id)) { for(j=0;j < global.shape[i]->len;j++) { global.shape[i]->p[j].x*=strtold(a[2],0); global.shape[i]->p[j].y*=strtold(a[2],0); global.shape[i]->p[j].z*=strtold(a[2],0); } } } continue; //return ret; } if(!strcmp(command,"move")) { if(len > 4) { for(i=0;global.shape[i];i++) { if(!strcmp(global.shape[i]->id,id)) { for(j=0;j < global.shape[i]->len;j++) { global.shape[i]->p[j].x+=strtold(a[2],0); global.shape[i]->p[j].y+=strtold(a[3],0); global.shape[i]->p[j].z+=strtold(a[4],0); } } } } else { printf("# ERROR: wrong amount of parts for move. got: %d expected: 11\n",len); } continue; //return ret; } printf("# I don't know what command you're talking about. %s\n",command); /* if(!strcmp(command,"rotate")) { for(i=0;global.shape[i];i++) { global.shape[i]->p1=rotate_c3_about() global.shape[i]->p2= global.shape[i]->p3= } */ free(line); if(a) free(a); } return ret; } int export_file(FILE *fp) {//not used yet. maybe export in obj optionally? no. that should be an external program // struct c3_shape *to; // int i; // for(i=0;global.shape[i];i++) { // to=global.shape[i]; // printf("%s addshape %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf\n",to->id,to->p1.x,to->p1.y,to->p1.z,to->p2.x,to->p2.y,to->p2.z,to->p3.x,to->p3.y,to->p3.z); // } return 0; } //push a string back into stdin so it can be read by the file loader. :P int selfcommand(char *s) { char t; if(!strlen(s)) return 0; ungetc(s[strlen(s)-1],stdin); t=s[strlen(s)-1]; s[strlen(s)-1]=0; selfcommand(s); putchar(t); return 0; } int keypress_handler(int sym) { char line[1024]; real tmpx; // real tmpy; //unused atm real tmpz; switch(sym) { case XK_Return: snprintf(line,sizeof(line)-1,"%s action %s\n",global.user,global.selected_object); selfcommand(line); break; case XK_Up: tmpx=WALK_SPEED*sinl(d2r(camera.yr+90)); tmpz=WALK_SPEED*cosl(d2r(camera.yr+90)); camera.p.x+=tmpx; camera.p.z+=tmpz; snprintf(line,sizeof(line)-1,"%s move %Lf 0 %Lf 0 0 0 0 0 0\n",global.user,tmpx,tmpz); selfcommand(line); break; case XK_Down: tmpx=WALK_SPEED*sinl(d2r(camera.yr+270)); tmpz=WALK_SPEED*cosl(d2r(camera.yr+270)); camera.p.x+=tmpx; camera.p.z+=tmpz; snprintf(line,sizeof(line)-1,"%s move %Lf 0 %Lf 0 0 0 0 0 0\n",global.user,tmpx,tmpz); selfcommand(line); break; case XK_Left: tmpx=WALK_SPEED*sinl(d2r(camera.yr)); tmpz=WALK_SPEED*cosl(d2r(camera.yr)); camera.p.x+=tmpx; camera.p.z+=tmpz; snprintf(line,sizeof(line)-1,"%s move %Lf 0 %Lf 0 0 0 0 0 0\n",global.user,tmpx,tmpz); selfcommand(line); break; case XK_Right: tmpx=WALK_SPEED*sinl(d2r(camera.yr+180)); tmpz=WALK_SPEED*cosl(d2r(camera.yr+180)); camera.p.x+=tmpx; camera.p.z+=tmpz; snprintf(line,sizeof(line)-1,"%s move %Lf 0 %Lf 0 0 0 0 0 0\n",global.user,tmpx,tmpz); selfcommand(line); break; case XK_w: camera.p.y+=1; snprintf(line,sizeof(line)-1,"%s move 0 1 0 0 0 0 0 0 0\n",global.user); selfcommand(line); break; case XK_s: camera.p.y-=1; snprintf(line,sizeof(line)-1,"%s move 0 -1 0 0 0 0 0 0 0\n",global.user); selfcommand(line); break; case XK_r: camera.xr+=5; while(camera.xr > 360) camera.xr-=360; break; case XK_y: camera.xr-=5; while(camera.xr < 0) camera.xr+=360; break; case XK_q: camera.yr+=5; while(camera.yr > 360) camera.yr-=360; break; case XK_e: camera.yr-=5; while(camera.yr < 0) camera.yr+=360; break; case XK_u: camera.zr+=5; while(camera.zr > 360) camera.zr-=360; break; case XK_o: camera.zr-=5; while(camera.zr < 0) camera.zr+=360; break; case XK_z: camera.zoom+=1; break; case XK_x: camera.zoom-=1; break; case XK_c: global.mmz*=1.1; break; case XK_v: global.mmz/=1.1; break; case XK_h: global.split+=1; break; case XK_j: global.split-=1; break; case XK_d: global.debug ^= 1; break; case XK_f: global.derp ^= 1; break; case XK_m: global.drawminimap += 1; global.drawminimap %= 4; break; case XK_a: global.drawsky ^= 1; break; case XK_3: global.draw3d += 1; global.draw3d %= 4; break; case XK_Escape: return -1; default: return 0; break; } return 1; } int main(int argc,char *argv[]) { Cursor cursor; XEvent e; XSetWindowAttributes attributes; Window root,child;//why do I have this? // XColor toss; int i,j; char tmp[64]; unsigned int mask; char redraw=0; if(argc < 2) { fprintf(stderr,"usage: hackvr yourname < from_others > to_others\n"); return 1; } else { global.user=strdup(argv[1]); } fcntl(1,F_SETFL,O_NONBLOCK);//won't work printf("# Opening X Display... (%s)\n",getenv("DISPLAY")); if((global.dpy = XOpenDisplay(0)) == NULL) return printf("# failure.\n"),2; else printf("# done.\n"); global.color_map=DefaultColormap(global.dpy, DefaultScreen(global.dpy)); printf("# generating grays...\n"); for(i=0;i<=100;i++) { snprintf(tmp,sizeof(tmp),"gray%d",i); XAllocNamedColor(global.dpy,global.color_map,tmp,&global.colors[i],&global.colors[i]); } printf("# done.\n"); setbuf(stdin,0); setbuf(stdout,0); assert(global.dpy); global.split_screen=SPLIT_SCREEN; global.split_flip=-1; global.split=5; global.root_window=0; global.red_and_blue=RED_AND_BLUE; //global.colors[0]=BlackPixel(global.dpy,DefaultScreen(global.dpy)); // int whiteColor = //WhitePixel(global.dpy, DefaultScreen(global.dpy)); attributes.background_pixel=global.colors[0].pixel; if(global.root_window) { global.w = DefaultRootWindow(global.dpy); //this is still buggy. } else { global.w = XCreateWindow(global.dpy,DefaultRootWindow(global.dpy),0,0,WIDTH*(global.split_screen / (global.red_and_blue ? global.split_screen : 1)),HEIGHT,1,DefaultDepth(global.dpy,DefaultScreen(global.dpy)),InputOutput,DefaultVisual(global.dpy,DefaultScreen(global.dpy))\ ,CWBackPixel, &attributes); set_aspect_ratio(); XSelectInput(global.dpy, global.w, PointerMotionMask|StructureNotifyMask|ButtonPressMask|ButtonReleaseMask|KeyPressMask|ExposureMask); } XMapWindow(global.dpy, global.w); XStoreName(global.dpy,global.w,"hackvr"); global.greyscale=1; global.zsort=1; global.shape[0]=0;//we'll allocate as we need more. global.gc=XCreateGC(global.dpy, global.w, 0, 0); if(global.red_and_blue) { global.width=WIDTH; } else { global.width=WIDTH*global.split_screen; } global.height=HEIGHT; global.backbuffer=XCreatePixmap(global.dpy,global.w,global.width,global.height,DefaultDepth(global.dpy,DefaultScreen(global.dpy))); global.cleanbackbuffer=XCreatePixmap(global.dpy,global.w,global.width,global.height,DefaultDepth(global.dpy,DefaultScreen(global.dpy))); //backbuffer is uninitialized global.backgc=XCreateGC(global.dpy,global.backbuffer,0,0); cursor=XCreateFontCursor(global.dpy,XC_crosshair); XDefineCursor(global.dpy, global.w, cursor); XAllocNamedColor(global.dpy, global.color_map, "green", &global.green, &global.green); XAllocNamedColor(global.dpy, global.color_map, "red", &global.red, &global.red); XAllocNamedColor(global.dpy, global.color_map, "blue", &global.blue, &global.blue); XAllocNamedColor(global.dpy, global.color_map, "red", &global.redblue[0], &global.redblue[0]); XAllocNamedColor(global.dpy, global.color_map, "blue", &global.redblue[1], &global.redblue[1]); XSetForeground(global.dpy, global.gc, global.green.pixel); XSetForeground(global.dpy, global.backgc, global.colors[0].pixel);//black. we're about to draw the blank background using this. XSetBackground(global.dpy, global.gc, global.colors[160].pixel); XSetBackground(global.dpy, global.backgc, global.colors[140].pixel); XFillRectangle(global.dpy,global.cleanbackbuffer,global.backgc,0,0,global.width,global.height); XSetForeground(global.dpy, global.backgc, global.green.pixel); // XSetForeground(global.dpy, gc, whiteColor); // this was taking a "long" time. printf("# generating sky... "); skypixmap=XCreatePixmap(global.dpy,global.w,SKYW,SKYH,DefaultDepth(global.dpy,DefaultScreen(global.dpy))); for(i=0;i> ((!!sky[i-1][(j+(SKYW)-1)%(SKYW)]<<2) | (!!sky[i-1][j]<<1) | (!!sky[i-1][j+1%(SKYW)])) & 1); if(sky[i][j]) { XDrawPoint(global.dpy,skypixmap,global.backgc,j,i); } } } } printf("done.\n"); global.mapxoff=global.width/2; global.mapyoff=global.height/2; global.drawminimap=0; global.draw3d=1; global.debug=0; global.force_redraw=1;//use this for checking proper fps I guess. camera.zoom=30.0l; camera.xr=270; camera.yr=270; camera.zr=0; global.mmz=1; camera.p.x=0; camera.p.z=6; camera.p.y=5; printf("# entering main loop\n"); for(;;) { redraw=global.force_redraw; while(XPending(global.dpy)) {//these are taking too long? XNextEvent(global.dpy, &e); // printf("# handling event with type: %d\n",e.type); switch(e.type) { // case Expose: // if(e.xexpose.count == 0) redraw=1; // break; case MotionNotify: redraw=1; XQueryPointer(global.dpy,global.w,&root,&child,&global.rmousex,&global.rmousey,&global.mousex,&global.mousey,&mask); break; case ButtonPress: redraw=1; global.buttonpressed=e.xbutton.button; break; case ButtonRelease: redraw=1; global.buttonpressed=0; break; case ConfigureNotify: redraw=1; XGetGeometry(global.dpy,global.w,&root,&global.x,&global.y,&global.width,&global.height,&global.border_width,&global.depth); if(global.width / (global.split_screen / (global.red_and_blue ? global.split_screen : 1 )) / 4 * 3 != global.height) { if(global.height * 3 / 4 == global.height) { printf("math doesn't work.\n"); } printf("# DERPY WM CANT TAKE A HINT %d / %d / 4 * 3 = %d != %d\n",global.width,global.split_screen,global.width /global.split_screen /4 * 3,global.height); if(global.width / (global.split_screen / (global.red_and_blue ? global.split_screen : 1)) / 4 * 3 < global.height) { global.height=global.width / (global.split_screen / (global.red_and_blue ? global.split_screen : 1)) / 4 * 3; } else { global.width=global.height * 3 / 4 * (global.split_screen / (global.red_and_blue ? global.split_screen : 1)); } } global.mapxoff=global.width/(global.split_screen / (global.red_and_blue ? global.split_screen : 1))/2; global.mapyoff=global.height/2; break; case KeyPress: redraw=1; if(keypress_handler(XLookupKeysym(&e.xkey,0)) == -1) { printf("# exiting\n"); return 0; } break; default: //printf("# received event with type: %d\n",e.type); break; } } switch(load_stdin()) { case -1: return 0; break; case 0: break; default: redraw=1; break; } //camera.yr+=2; if(redraw) { draw_screen(global.dpy,global.w,global.gc); } //usleep(10000); } return 0; }