view old/simple_render/polygon.cpp @ 507:735f76483bb2

Reorganization..
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 12 Oct 2009 09:39:35 +0900
parents TaskManager/Test/simple_render/polygon.cpp@5c194c71eca8
children
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"
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::draw(SpanPackList *ss)
{
    SpanPack *spanPack;
    Span *span;

    //for (int i = 0; i < ss->length; i++) {
    for (int i = 0; i < 10; i++) {
	spanPack = &ss->packs[i];

	for(int n = 0; n < spanPack->info.size; n++) {
	    span = &spanPack->span[n];

	    int end    = span->length_x;
	    Uint32 rgb;
	    float tex1 = span->tex_x1;
	    float tex2 = span->tex_x2;
	    float tey1 = span->tex_y1;
	    float tey2 = span->tex_y2;
	    int tex_xpos;
	    int tex_ypos;
	    int tex_zpos;
	    int x = span->x;
	    int y = span->y;
	    float z = span->start_z;
	    float zpos = span->end_z;
	    float tex_x,tex_y,tex_z;
      
	    if(end == 1) {
		//printf("end == 1\n");
		//printf("tex_x:%f tex_y:%f\n",tex1,tex2);
		//if(tex1 > 1) tex1 = 1;
		//if(tey1 > 1) tey1 = 1;
		tex_xpos = (int)((span->tex_height-1) * tex1);
		tex_ypos = (int)((span->tex_width-1) * tey1);
		tex_zpos = (int)z;
		//printf("tex_xpos:%d tex_ypos:%d\n",tex_xpos,tex_ypos);
		//printf("image->h:%d tex_x:%f\n",(int)span->tex_height,tex1);
		rgb = get_rgb(tex_xpos,tex_ypos);
		viewer->write_pixel(x,y,zpos,rgb);
	    }else {
		//printf("end != 1\n");
		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);
		    //printf("tex_xpos:%d tex_ypos:%d\n",tex_xpos,tex_ypos);
		    //printf("z:%f zpos:%f tex_z:%f\n",z,zpos,tex_z);
		    //printf("tex_x:%f tex_y:%f\n",tex_x,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)
{
  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 = root->searchPolygon(tmp->parent_name);
	  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;

  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;
}