Mercurial > hg > Members > kono > Cerium
diff TaskManager/Test/test_render/polygon.cpp @ 109:5c194c71eca8
Cerium cvs version
author | gongo@gendarme.local |
---|---|
date | Wed, 12 Nov 2008 17:39:33 +0900 |
parents | |
children | a52e193f9a42 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TaskManager/Test/test_render/polygon.cpp Wed Nov 12 17:39:33 2008 +0900 @@ -0,0 +1,916 @@ +#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" +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; + child = 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->child != NULL) + { + cout << "--move child : " << t->child->name << endl; + t = t->child; + } + 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(child != NULL) + { + cout << "child->name = " << child->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::create_scene_graph_pack() +{ + //SceneGraphPack *sgp = new SceneGraphPack; + sgp = new SceneGraphPack; + int i = 0; + int nnpn = -1; + + Polygon *t; + t = this; + + while(t) + { + //SceneGraphNode node; + sgp->node[i].size = t->size; + int d,tex; + for(d=0,tex=0; d<t->size*3; d+=3,tex+=2) + { + sgp->node[i].vertex[d] = t->data[d]; + sgp->node[i].vertex[d+1] = t->data[d+1]; + sgp->node[i].vertex[d+2] = t->data[d+2]; + sgp->node[i].texture[tex] = t->data[d+t->size*6]; + sgp->node[i].texture[tex+1] = t->data[d+t->size*6+1]; + } + + sgp->node[i].obj_pos[0] = 0; + sgp->node[i].obj_pos[1] = 0; + sgp->node[i].obj_pos[2] = 0; + sgp->node[i].obj_pos[3] = 1; + sgp->node[i].angle[0] = 0; + sgp->node[i].angle[1] = 0; + sgp->node[i].angle[2] = 0; + sgp->node[i].angle[3] = 1; + + for(int tm=0; tm<16; tm++) + { + sgp->node[i].translation[tm] = 0; + } + sgp->node[i].id = 0; + sgp->node[i].move = 0; + sgp->node[i].interaction = 0; + sgp->node[i].pn = nnpn; + + if(t->child != NULL) + { + nnpn = i; + t = t->child; + } + else if(t->brother != NULL) + { + nnpn = sgp->node[i].pn; + t = t->brother; + } + else + { + while(t) + { + if(t->brother != NULL) + { + t = t->brother; + break; + } + else + { + if(t->parent == NULL) + { + t = NULL; + break; + } + nnpn = sgp->node[nnpn].pn; + t = t->parent; + } + } + } + //printf("sgp->node[%d].pn = %d\n", i, sgp->node[i].pn); + i++; + } + sgp->info.size = i; + + + //for(int s=0; s<i; s++) + //{ + //printf("sgp.node[%d].pn = %d\n",s,sgp.node[s].pn); + //} + + //delete sgp; +} +*/ + + +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->child == NULL) + { + p->child = list; + } + else + { + bros = p->child; + while(bros->brother != NULL) + { + bros = bros->brother; + } + bros->brother = list; + } + break; + } + p = p->next; + } + } + } +} + +/* +void Polygon::create_scene_graph_pack() +{ + SceneGraphPack sgp; + int i = 0; + int nnpn = -1; + + Polygon *t; + t = this; + while(t) + { + //t->draw(); + SceneGraphNode node; + node.obj_pos[0] = 0; + node.obj_pos[1] = 0; + node.obj_pos[2] = 0; + node.obj_pos[3] = 1; + for(int tm=0; tm<16; tm++) + { + node.translation[tm] = 0; + } + node.id = 0; + node.move = 0; + node.interaction = 0; + for(int a=0; a<10; a++) + { + node.op[a] = -1; + } + node.pn = nnpn; + int p = 0; + + if(t->child != NULL) + { + //glPushMatrix(); + //node.op[p] = PUSH; + //nnpn = i; + t = t->child; + } + else if(t->brother != NULL) + { + //glPopMatrix(); + //glPushMatrix(); + //node.op[p] = SHIFT; + //nnpn = node.pn; + t = t->brother; + } + else + { + while(t) + { + if(t->brother != NULL) + { + //glPopMatrix(); + //glPushMatrix(); + //node.op[p] = SHIFT; + t = t->brother; + break; + } + else + { + t = t->parent; + if(t) + { + //glPopMatrix(); + //node.op[p] = POP; + //nnpn = sgp.node[nnpn].pn; + p++; + } + } + } + } + sgp.node[i] = node; + i++; + } + + sgp.info.size = i; + + for(int s=0; s<4; s++) + { + for(int a=0; sgp.node[s].op[a]!=-1; a++) + { + printf("sgp.node[%d].op[%d] = %d\n",s, a, sgp.node[s].op[a]); + } + //printf("sgp.node[%d].pn = %d\n",s,sgp.node[s].pn); + } +} +*/ + + + +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); + + //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; + child = 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,"No such parent %s\n",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->next = child; + } + + this->lastChild = child; + +#if 1 + if (this->children == NULL) { + this->children = child; + } +#endif + + 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; +} +