Mercurial > hg > Game > Cerium
view TaskManager/Test/test_render/polygon.cpp @ 130:40978d4b608a draft
テクスチャの大きさを128x128以外にも使えるように。(若干バグ有り)
author | gongo@gendarme.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Tue, 25 Nov 2008 17:19:43 +0900 |
parents | e9e12e2088bd |
children | 91c74dbc32e4 |
line wrap: on
line source
#include <iostream> #include <SDL.h> #include <SDL_opengl.h> #include <SDL_image.h> #include <libxml/parser.h> #include "polygon.h" #include "xml.h" #include "texture.h" #include "sys.h" #include "triangle.h" #include "vertex.h" #include "Span.h" #include "SpanC.h" #include "scene_graph_pack.h" #include "error.h" #include "viewer_types.h" using namespace std; //extern int decode(char *cont, char *file_name); extern int decode(char *cont, FILE *outfile); SDL_Surface* Polygon::texture_image; Polygon::Polygon() { xyz[0] = 0; xyz[1] = 0; xyz[2] = 0; xyz[3] = 1; c_xyz[0] = 0; c_xyz[1] = 0; c_xyz[2] = 0; c_xyz[3] = 1; angle[0] = 0; angle[1] = 0; angle[2] = 0; angle[3] = 1; next = NULL; parent = NULL; brother = NULL; children = NULL; lastChild = NULL; } void Polygon::tree_check() { Polygon *t; t = this; while(t) { cout << "my_name : " << t->name << endl; if(t->children != NULL) { cout << "--move children : " << t->children->name << endl; t = t->children; } else if(t->brother != NULL) { cout << "--move brother : " << t->brother->name << endl; t = t->brother; } else { while(t) { if(t->brother != NULL) { cout << "--move brother : " << t->brother->name << endl; t = t->brother; break; } else { if(t->parent) { cout << "--move parent : " << t->parent->name << endl; } t = t->parent; } } } } } void Polygon::print_member() { //int n; cout << "size = " << size << endl; cout << "name = " << name << endl; cout << "parent_name = " << parent_name << endl; /* for(n=0; n<size*3; n+=3) { cout<<"coordinate = "<<data[n]<<" "<<data[n+1]<<" "<< data[n+2]<<endl; } */ /* for(n=size*3; n<size*6; n+=3) { cout<<"narmal = "<<data[n]<<" "<<data[n+1]<<" "<<data[n+2]<<endl; } */ cout<<"c_xyz = "<<c_xyz[0]<<" "<<c_xyz[1]<<" "<<c_xyz[2]<<endl; /* for(n=size*6; n<size*9; n+=3) { cout<<"texture = "<<data[n]<<" "<<data[n+1]<<" "<<data[n+2]<<endl; } */ /* for(n=0; n<size*3; n+=3) { cout<<"coordinate = "<<data[n]<<" "<<data[n+1]<<" "<<data[n+2]<<endl; cout<<"normal = "<<data[n+size*3]<<" "<<data[n+size*3+1]<<" "<<data[n+size*3+2]<<endl; cout<<"texture = "<<data[n+size*6]<<" "<<1-data[n+size*6+1]<<endl; } */ //cout << "image_name = " << image_name << endl; if(parent != NULL) { cout << "parent->name = " << parent->name << endl; } if(children != NULL) { cout << "children->name = " << children->name << endl; } } void Polygon::draw(SceneGraphPack *sgp) { float xyz1[4],xyz2[4],xyz3[4]; /***SceneGraphUpdate***/ //sgp_update(); for (int i = 0; i < sgp->info.size; i++) { SceneGraphNode node = sgp->node[i]; /***draw***/ int n,nt; for(n=0,nt=0; n<node.size*3; n+=9,nt+=6) { xyz1[0] = node.vertex[n]; xyz1[1] = node.vertex[n+1]; xyz1[2] = node.vertex[n+2]*-1; xyz1[3] = 1; xyz2[0] = node.vertex[n+3]; xyz2[1] = node.vertex[n+3+1]; xyz2[2] = node.vertex[n+3+2]*-1; xyz2[3] = 1; xyz3[0] = node.vertex[n+6]; xyz3[1] = node.vertex[n+6+1]; xyz3[2] = node.vertex[n+6+2]*-1; xyz3[3] = 1; rotate(xyz1, node.translation); rotate(xyz2, node.translation); rotate(xyz3, node.translation); Vertex *ver1 = new Vertex(xyz1[0],xyz1[1],xyz1[2],node.texture[nt],node.texture[nt+1]); Vertex *ver2 = new Vertex(xyz2[0],xyz2[1],xyz2[2],node.texture[nt+2],node.texture[nt+2+1]); Vertex *ver3 = new Vertex(xyz3[0],xyz3[1],xyz3[2],node.texture[nt+4],node.texture[nt+4+1]); Triangle *tri = new Triangle(ver1,ver2,ver3); Span_c *span = new Span_c(); span->viewer = viewer; span->p = this; span->create_span(tri,texture_image); delete ver1; delete ver2; delete ver3; delete tri; delete span; } } } void Polygon::draw(PolygonPack *pp) { for(int n=0; n<pp->info.size; n++) { Vertex *ver1 = new Vertex(pp->tri[n].ver1.x,pp->tri[n].ver1.y,pp->tri[n].ver1.z,pp->tri[n].ver1.tex_x,pp->tri[n].ver1.tex_y); Vertex *ver2 = new Vertex(pp->tri[n].ver2.x,pp->tri[n].ver2.y,pp->tri[n].ver2.z,pp->tri[n].ver2.tex_x,pp->tri[n].ver2.tex_y); Vertex *ver3 = new Vertex(pp->tri[n].ver3.x,pp->tri[n].ver3.y,pp->tri[n].ver3.z,pp->tri[n].ver3.tex_x,pp->tri[n].ver3.tex_y); Triangle *tri = new Triangle(ver1,ver2,ver3); Span_c *span = new Span_c(); span->viewer = viewer; span->p = this; span->create_span(tri,texture_image); delete ver1; delete ver2; delete ver3; delete tri; delete span; } } void Polygon::draw(SpanPack *sp) { Span *span; for (int n = 0; n < sp->info.size; n++) { span = &sp->span[n]; //int x = span->x; //int y = span->y; float z = span->start_z; int end = span->length_x; float zpos = span->end_z; float tex1 = span->tex_x1; float tex2 = span->tex_x2; float tey1 = span->tex_y1; float tey2 = span->tex_y2; Uint32 rgb; int tex_xpos; int tex_ypos; int tex_zpos; float tex_x, tex_y, tex_z; if (end == 1) { tex_xpos = (int)((span->tex_height-1) * tex1); tex_ypos = (int)((span->tex_width-1) * tey1); tex_zpos = (int)z; rgb = get_rgb(tex_xpos, tex_ypos); //viewer->write_pixel(x, y, zpos, rgb); } else { for (int j = 0; j < end; j++) { tex_x = tex1*(end-1-j)/(end-1) + tex2*j/(end-1); tex_y = tey1*(end-1-j)/(end-1) + tey2*j/(end-1); tex_z = z*(end-1-j)/(end-1) + zpos*j/(end-1); if (tex_x > 1) tex_x = 1; if (tex_y > 1) tex_y = 1; tex_xpos = (int)((span->tex_height-1) * tex_x); tex_ypos = (int)((span->tex_width-1) * tex_y); rgb = get_rgb(tex_xpos,tex_ypos); //viewer->write_pixel(j + x, y, tex_z, rgb); } } } } void Polygon::add_next() { Polygon *p; p = new Polygon; next = p; } void Polygon::create_tree() { Polygon *list; Polygon *check_list; Polygon *p; Polygon *bros; check_list = this; for (list=this; list; list=list->next) { if (xmlStrcmp((xmlChar *)list->parent_name, (xmlChar *)"NULL")) { p = this; while (p) { if (!xmlStrcmp((xmlChar *)p->name,(xmlChar *)list->parent_name)) { list->parent = p; if(p->children == NULL) { p->children = list; } else { bros = p->children; while(bros->brother != NULL) { bros = bros->brother; } bros->brother = list; } break; } p = p->next; } } } } void Polygon::pickup_coordinate(char *cont) { for(int n=0; n<size*3; n+=3) { cont = pickup_float(cont, data+n); cont = pickup_float(cont, data+n+1); cont = pickup_float(cont, data+n+2); if (cont == NULL) { cout << "Analyzing obj data failed coordinate\n"; } } } void Polygon::pickup_normal(char *cont) { for(int n=size*3;n<size*6;n+=3) { cont = pickup_float(cont,data+n); cont = pickup_float(cont,data+n+1); cont = pickup_float(cont,data+n+2); if (cont == NULL) { cout << "Analyzing obj data failed normal\n"; } } } void Polygon::pickup_model(char *cont) { cont = pickup_float(cont,c_xyz); cont = pickup_float(cont,c_xyz+1); cont = pickup_float(cont,c_xyz+2); if (cont == NULL) { cout << "Analyzing obj data failed model\n"; } } void Polygon::pickup_texture(char *cont) { for(int n=size*6; n<size*9; n+=3) { cont = pickup_float(cont,data+n); cont = pickup_float(cont,data+n+1); data[n+2] = 1.0; if (cont == NULL) { cout << "Analyzing obj data failed texture\n"; } } } char *get_pixel(int tx, int ty, SDL_Surface *texture_image) { return (char*)texture_image->pixels+(texture_image->format->BytesPerPixel*((texture_image->w)*ty+tx)); } unsigned my_ntohl(unsigned u) { // rr gg bb 00 // rr // bb gg rr //unsigned u1 = ((u&0xff)<<24) + // ((u&0xff00)<<8) + // ((u&0xff0000)>>8) + // ((u&0xff000000)>>24); unsigned u1; unsigned b = (u&0xff000000)>>24; unsigned g = (u&0xff0000)>>16; unsigned r = (u&0xff00)>>8; u1 = r + (g<<8) + (b<<16); //printf("pixel %x->%x\n",u,u1); return u1; } Uint32 Polygon::get_rgb(int tx, int ty) { SDL_PixelFormat *fmt; //Uint32 temp, pixel; Uint8 red, green, blue; fmt = texture_image->format; if (tx<0) tx = 0; if (texture_image->w-1< tx) tx = texture_image->w-1 ; if (ty<0) ty = 0; if (texture_image->h-1< ty) ty = texture_image->h-1 ; //SDL_LockSurface(texture_image); char *p = get_pixel(tx,ty,texture_image); #if 0 pixel = my_ntohl(*(Uint32*)p); //printf("pixel = %d\n", pixel); //printf("pixel %x bpp = %d ",p, fmt->BytesPerPixel); //SDL_UnlockSurface(texture_image); temp = pixel&fmt->Rmask; temp = temp>>fmt->Rshift; temp = temp<<fmt->Rloss; red = (Uint8)temp; temp = pixel&fmt->Gmask; temp = temp>>fmt->Gshift; temp = temp<<fmt->Gloss; green = (Uint8)temp; temp = pixel&fmt->Bmask; temp = temp>>fmt->Bshift; temp = temp<<fmt->Bloss; blue = (Uint8)temp; #endif blue = (Uint8) p[0]; green = (Uint8) p[1]; red = (Uint8) p[2]; //printf("tx = %d ty = %d ", tx,ty); //printf("pixel color => R: %d, G: %d, B: %d\n", red, green, blue); SDL_PixelFormat *pf; //pf = viewer->screen->format; //cout << SDL_MapRGB(pf, red, green, blue) << endl; return SDL_MapRGB(pf, red, green, blue); } /* * surface nodeからポリゴンの情報を読み出す 再帰しない */ void Polygon::get_data(xmlNodePtr cur) { char *cont; //char *image_name; for(;cur;cur=cur->next) { if(!xmlStrcmp(cur->name,(xmlChar*)"coordinate")) { cont = (char *)xmlNodeGetContent(cur); pickup_coordinate(cont); } else if(!xmlStrcmp(cur->name,(xmlChar*)"normal")) { cont = (char *)xmlNodeGetContent(cur); pickup_normal(cont); } else if(!xmlStrcmp(cur->name,(xmlChar*)"model")) { cont = (char *)xmlNodeGetContent(cur); pickup_model(cont); } else if(!xmlStrcmp(cur->name,(xmlChar*)"texture")) { cont = (char *)xmlNodeGetContent(cur); pickup_texture(cont); } else if(!xmlStrcmp(cur->name,(xmlChar*)"image")) { char image_name[20] = "/tmp/image_XXXXXX"; int fd = mkstemp(image_name); FILE *outfile = fdopen(fd, "wb"); if(NULL == outfile) { cout << "error open file\n"; } cont = (char *)xmlNodeGetContent(cur); //decode(cont, image_name); decode(cont, outfile); fclose(outfile); texture_image = IMG_Load(image_name); /** * image を 32bit(RGBA) に変換する */ SDL_Surface *tmpImage = SDL_CreateRGBSurface(SDL_HWSURFACE, texture_image->w, texture_image->h, 32, redMask, greenMask, blueMask, alphaMask); SDL_Surface *converted; converted = SDL_ConvertSurface(texture_image, tmpImage->format, SDL_HWSURFACE); if( converted != NULL){ SDL_FreeSurface(texture_image); texture_image = converted; } //load_texture(image_name); if(unlink(image_name)) { cout << "unlink error\n"; } } } } /* * ノードを受け取って、そこからポリゴンを生成 * リークしてない? data上書きしちゃだめ */ void Polygon::create_data(xmlNodePtr cur) { char *p = (char *)xmlGetProp(cur,(xmlChar *)"size"); //error 出力? #ifndef _DEBUG if(strlen(p)>8){ __debug("Polygon size is too large.\n"); exit(1); } #endif size = atoi((char *)xmlGetProp(cur,(xmlChar *)"size")); name = (char *)xmlGetProp(cur,(xmlChar *)"name"); parent_name = (char *)xmlGetProp(cur,(xmlChar *)"parent"); next = NULL; data = new float[size*3*3]; get_data(cur->children); } /* * xmlをオープンして、Surfaceノードからポリゴンを作る * */ void Polygon::set_data(char *file_name) { xmlDocPtr doc; xmlNodePtr cur; Polygon *tmp; doc = xmlParseFile(file_name); cur = xmlDocGetRootElement(doc); xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"); tmp = this; for (cur=cur->children; cur; cur=cur->next) { if (!xmlStrcmp(cur->name,(xmlChar*)"surface")) { tmp->create_data(cur); if(cur->next->next) { tmp->add_next(); tmp = tmp->next; } } } create_tree(); //tree_check(); //create_scene_graph_pack(); xmlFreeDoc(doc); /* for(int s=0; s<sgp->info.size; s++) { printf("sgp->node[%d].pn = %d\n",s,sgp->node[s].pn); } */ //delete sgp; } void Polygon::delete_data() { Polygon *n,*m; n = this; delete [] n->data; if(next) { for(n = this->next; n; n=m) { m = n->next; delete [] n->data; delete n; } } } /* construct polygon from xml. */ /* Polygon::Polygon(char *xmlfile) { Polygon(); xmlDocPtr doc; xmlNodePtr cur; Polygon *tmp; doc = xmlParseFile(file_name); cur = xmlDocGetRootElement(doc); xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"); tmp = this; for (cur=cur->children; cur; cur=cur->next) { if ( xmlStrcmp(cur->name,(xmlChar*)"surface")!=0 ) continue; if ( xmlStrcmp(cur->parent )) tmp->create_data(cur); if(cur->next->next) { tmp->add_next(); tmp = tmp->next; } } create_tree(); //tree_check(); //create_scene_graph_pack(); xmlFreeDoc(doc); } */ /* construct polygon from xmlNode. */ Polygon::Polygon(xmlNodePtr surface) { #if 1 xyz[0] = 0; xyz[1] = 0; xyz[2] = 0; xyz[3] = 1; c_xyz[0] = 0; c_xyz[1] = 0; c_xyz[2] = 0; c_xyz[3] = 1; angle[0] = 0; angle[1] = 0; angle[2] = 0; angle[3] = 1; next = NULL; parent = NULL; brother = NULL; children = NULL; lastChild = NULL; #else /* これ使うにはどうすればいいの? */ this->Polygon(); #endif size = atoi((char *)xmlGetProp(surface,(xmlChar *)"size")); name = (char *)xmlGetProp(surface,(xmlChar *)"name"); parent_name = (char *)xmlGetProp(surface,(xmlChar *)"parent"); next = NULL; data = new float[size*3*3]; get_data(surface->children); } /* XMLファイルからポリゴンを作成 */ Polygon *Polygon::createFromXMLfile(char *xmlfile) { xmlDocPtr doc; xmlNodePtr cur; Polygon *root=NULL, *tmp, *parent; /* パース DOM生成 */ doc = xmlParseFile(xmlfile); cur = xmlDocGetRootElement(doc); /* ?? */ xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"); /* XMLのノードを一つずつ解析 */ for (cur=cur->children; cur; cur=cur->next) { /* 扱うのはsurfaceオンリー */ if ( xmlStrcmp(cur->name,(xmlChar*)"surface")!=0 ) continue; /* ポリゴン生成 */ tmp = new Polygon(cur); if ( tmp->parent_name==NULL || 0==strcmp(tmp->parent_name, "NULL")) { /* このsurfaceがroot */ root = tmp; } else { /* 親はこのsurfaceより前に定義されているものとする (していい?) */ // ここで parent_name を用いるのは間違っていて、 // *cur->properties->children から探すべきらしい kono parent = root->searchPolygon(tmp->parent_name); if (parent==NULL) { fprintf(stderr, "[%s] No such parent %s\n", tmp->name, tmp->parent_name); root->addChild(tmp); } else { parent->addChild(tmp); } } } xmlFreeDoc(doc); return root; } /* 子供を追加 */ Polygon *Polygon::addChild(Polygon *child) { Polygon *tmp; /* childrenのリストの最後に加える */ if (this->lastChild != NULL) { tmp = this->lastChild; tmp->children = child; } this->lastChild = child; if (this->children == NULL) { this->children = child; } return child; } /* thisの子や子孫にnameのものが存在すればそいつを返す なければNULL. */ Polygon *Polygon::searchPolygon(char *name) { Polygon *tmp, *result; /* 本人か */ if( 0==strcmp(this->name, name) ) return this; /* 子供から再帰的に探す */ for( tmp=this->children; tmp; tmp=tmp->next ) { if( (result=tmp->searchPolygon(name))!=NULL ) return result; } /* 無かったら NULL. */ return NULL; }