changeset 1331:1dd2b2f5e2e9 draft

add collada file test program.
author Taiki TAIRA <e095767@ie.u-ryukyu.ac.jp>
date Wed, 21 Dec 2011 04:22:17 +0900
parents 615555d5bfa0
children fab593a9feb1 6b7151aec7b6
files Renderer/Engine/SceneGraphRoot.cc Renderer/Test/collada_test/collada_test.cc
diffstat 2 files changed, 403 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Renderer/Engine/SceneGraphRoot.cc	Wed Dec 21 04:17:24 2011 +0900
+++ b/Renderer/Engine/SceneGraphRoot.cc	Wed Dec 21 04:22:17 2011 +0900
@@ -478,7 +478,7 @@
 
         float *vertex_table = (float*)malloc(sizeof(float)*s->vertex_float->count) ;
         float *normal_table = (float*)malloc(sizeof(float)*s->normal_float->count) ;
-	float *texcoord_table = (float*)malloc(sizeof(float)*s->texcoord_float->count) ;
+	    float *texcoord_table = (float*)malloc(sizeof(float)*s->texcoord_float->count) ;
 
         /* p separate vertex position and nomal position. */
         for (int i = 0,j=0; i < s->polylist_count; i+=2,j++) {
@@ -578,7 +578,12 @@
   
         LIST list;
         init_list(&list);
+<<<<<<< local
+
+	xml_walk(this, cur,&s, &list);
+=======
 	xml_walk(cur,&s, &list);
+>>>>>>> other
     }
     xmlFreeDoc(doc);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Renderer/Test/collada_test/collada_test.cc	Wed Dec 21 04:22:17 2011 +0900
@@ -0,0 +1,397 @@
+#include <stdio.h>
+#include <libxml/parser.h>
+
+typedef struct source {
+    char *id;
+    union {
+        float *array;
+        char *alias;
+    }u;
+    int count;
+    struct source *next;
+} SOURCE;
+typedef SOURCE *SOURCE_P;
+
+typedef struct list {
+    SOURCE_P first;
+    SOURCE_P end;
+} LIST;
+typedef LIST *LIST_P;
+
+/* add source list */
+static void
+addSource(LIST_P list, SOURCE_P src) {
+    if (list->first == NULL && list->end == NULL) {
+        list->first = list->end = src;
+        return;
+    }
+    list->end->next = src;
+    list->end = src;
+}
+
+/* compare a with b. Using to compare id */
+static int
+strcmp_a(const char *a, const char *b)
+{
+    while (*a && *a++ == *b++);
+    if (*a) return 0;
+    return a[-1] > b[-1] ? 1:-1;
+}
+/*
+static float
+get_point(char *id, int position, LIST_P list)
+{
+    SOURCE_P cur = list->first;
+    for (;cur ; cur=cur->next) {
+        if (!strcmp_a(id, cur->id)) {
+            if (cur->count == 0) //alias 
+                return get_point(cur->u.alias, position, list);
+            float *a = cur->u.array;
+            if (position <= cur->count) {
+                return a[position];
+            }
+       }
+    }
+}
+*/
+/**
+ * co
+ */
+static SOURCE_P
+most_match(const char *id , LIST_P list)
+{
+    SOURCE_P src = NULL;
+    SOURCE_P cur = NULL;
+    int tmplength = 0;
+    int strlength;
+    for (cur=list->first ;cur!=list->end ;cur=cur->next) {
+        for (strlength=0;id[strlength]==cur->id[strlength];strlength++); 
+        if (tmplength < strlength) {
+            tmplength = strlength;
+            src = cur;
+        }
+    }
+
+    if ( src == NULL) {
+        printf("not match list\n");
+    }
+
+    return src;
+}
+
+struct collada_state {
+    collada_state(){
+        polylist=0;
+        vertex_offset=-1;
+        vertex_count=0;
+
+        normal_offset=-1;
+        normal_count=0;
+
+        texcoord_offset=-1;
+        texcoord_count=0;
+  
+        polylist_count=0;
+    }
+
+    int polylist;
+
+    xmlChar *pid;
+
+    char *vertex_src;
+    int vertex_offset;
+    int vertex_count;
+
+    char *normal_src;
+    int normal_offset;
+    int normal_count;
+
+    char *texcoord_src;
+    int texcoord_offset;
+    int texcoord_count;
+  
+    float *vcount;
+    float *pcount;
+  
+    SOURCE_P normal_float;
+    SOURCE_P vertex_float;
+    SOURCE_P texcoord_float;
+
+    char *vertices_src;
+    int polylist_count;
+
+};
+
+char *skip_to_number(char *cont)
+{
+  if (cont == NULL) return(NULL);
+  for (;(*cont < '+' || *cont > '9') && (*cont != '\0');cont++) {}
+  if (*cont == '\0')
+    {
+      fprintf(stderr,"Content data is short\n");
+      return(NULL);
+    }
+  return(cont);
+}
+
+
+char *pickup_float(char *cont, float *index)
+{
+  int sign=1,exp=1;
+  float shift=10,val_dec=0,val_int=0;
+
+  cont = skip_to_number(cont);
+  if (cont == NULL) return(NULL);
+
+  for (;*cont != ' ' && *cont != '\n' && *cont != '\t' && *cont != ',' ;cont++)
+    {
+      if (*cont == '-')
+        {
+          sign = -1;
+        }
+      else if (*cont == '.')
+        {
+          shift = 0.1;
+        }
+      else if (*cont >= '0' && *cont <= '9')
+        {
+          if (shift == 10)
+            {
+              val_int *= shift;
+              val_int += *cont - 48;
+            }
+          else
+            {
+              val_dec += (*cont - 48) * shift;
+              shift *= 0.1;
+            }
+        }
+      else if (*cont == 'e' || *cont == 'E')
+        {
+          //cont = pickup_exponent(&exp,cont+1);
+          if (cont == NULL) return(NULL);
+        }
+      else if (*cont == '+' || *cont == '/' || *cont == ' ')
+        {
+          // ignore
+        }
+
+      else if (*cont == '\0')
+        {
+            // NULL end
+
+            /* ここの条件は collada の仕様に合わせたもの。
+             * 自前の blender script から吐き出される xml形式では、
+             * 文字の終わりをNULLでは判断せず、エラー処理としていた
+             * ので必要ではなかった。よって、自前 blender script の
+             * xml形式の時、途中で NULL が来た場合、エラー処理され
+             * なくなる。NULL を返すので、呼び出し側で判断する
+             */
+            
+            *index = sign * (val_int + val_dec) * exp;
+            return(NULL);
+        }
+      else
+        {
+          fprintf(stderr,"Pick up float failed : %c(%d)\n",*cont,*cont);
+          return(NULL);
+        }
+    }
+
+  *index = sign * (val_int + val_dec) * exp;
+  cont++;
+  return(cont);
+}
+
+
+
+static void 
+xml_walk(xmlNodePtr cur, struct collada_state *s, LIST_P list)
+{
+
+    int in_polylist=0;
+
+    // printf("name = %s, child:%s\n", (char *)cur->name, (char *)cur->children);
+    // printf("s->polylist = %d\n",s->polylist);
+
+    if (!xmlStrcmp(cur->name, (xmlChar*)"polylist")) {
+
+        s->polylist_count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));
+
+        s->polylist=1;
+        in_polylist=1;
+
+    } else if (!xmlStrcmp(cur->name, (xmlChar*)"vertices")) {
+
+        s->pid = xmlGetProp(cur, (xmlChar*)"id");
+
+    } else if (!s->polylist && !xmlStrcmp(cur->name, (xmlChar*)"input")) {
+
+        char *semantic = (char*)xmlGetProp(cur, (xmlChar*)"semantic");
+        if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"POSITION")) {
+            s->vertices_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
+        }
+
+    } else if (s->polylist && !xmlStrcmp(cur->name, (xmlChar*)"input")) {
+	char *semantic = (char*)xmlGetProp(cur, (xmlChar*)"semantic");
+
+        if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"VERTEX")) {
+	         s->vertex_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
+             s->vertex_offset = atoi((char*)xmlGetProp(cur, (xmlChar*)"offset"));
+             
+             s->vertex_float = most_match(s->vertices_src+1, list);
+
+        } else if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"NORMAL")) {
+
+            s->normal_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
+            s->normal_offset = atoi((char*)xmlGetProp(cur, (xmlChar*)"offset"));
+            s->normal_float = most_match(s->normal_src+1, list);
+                
+       } else if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"TEXCOORD")) {
+
+            s->texcoord_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
+            s->texcoord_offset = atoi((char*)xmlGetProp(cur, (xmlChar*)"offset"));
+            s->texcoord_float = most_match(s->texcoord_src+1, list);
+       }
+
+    } else if (!xmlStrcmp(cur->name, (xmlChar*)"vcount")) {
+        char *vcont = (char*)xmlNodeGetContent(cur);
+
+        s->vcount = (float*)malloc(sizeof(float)*s->polylist_count);
+
+        for (int i=0; vcont!=NULL; i++) {
+            /* store vcount list */
+             vcont = pickup_float(vcont, s->vcount+i);
+        }
+        
+    } else if (!xmlStrcmp(cur->name, (xmlChar*)"p")) {
+
+        char *pcont = (char*)xmlNodeGetContent(cur);
+
+        int vcsum = 0;
+        for (int i=0; i < s->polylist_count; i++) {
+            vcsum += s->vcount[i];
+        }
+
+        s->pcount = (float*)malloc(sizeof(float)*vcsum);
+
+        for (int i=0; pcont != NULL; i++) {
+            pcont = pickup_float(pcont, s->pcount+i);
+        } 
+        
+        int vertexp[vcsum];
+
+        for (int i=0; i<vcsum ;i++) {
+            vertexp[i]=0;
+        }
+        
+        float *vertex_table = (float*)malloc(sizeof(float)*s->vertex_float->count) ;
+        float *normal_table = (float*)malloc(sizeof(float)*s->normal_float->count) ;
+	    float *texcoord_table = (float*)malloc(sizeof(float)*s->texcoord_float->count) ;
+
+        /* p separate vertex position and nomal position. */
+        for (int i=0, j=0; i < s->polylist_count; i+=2,j++) {
+            vertexp[j] = (int)s->pcount[i];
+            normal_table[j] = s->normal_float->u.array[(int)s->pcount[i+1]];
+            if (s->texcoord_offset == 2) {
+	            texcoord_table[j] = s->texcoord_float->u.array[(int)s->pcount[i+2]];
+	            i++;
+            }
+        }
+
+        for (int i=0; vertexp[i];i++) {
+            if (s->vcount[i] == 4) {
+                for (int j=0; j > s->vcount[i]; j++) {
+                    vertex_table[i] = s->vertex_float->u.array[vertexp[i]];
+                    vertex_table[i+3] = s->vertex_float->u.array[vertexp[i+1]];
+                    i += 2;
+                }
+            } else  if (s->vcount[i]==3) {
+                vertex_table[i] = s->vertex_float->u.array[vertexp[i]];
+            }
+        }
+	/*TEST*/
+        for (int i=0; i<vcsum; i++) {
+            //printf("normal_table= %f\n", normal_table[i]);
+            printf("vertexp= %d\n", vertexp[i]);
+        } 
+
+        free(vertex_table);
+        free(normal_table);
+        free(texcoord_table);
+
+        /* got out of polylist */
+        s->polylist = 0;
+        in_polylist = 0;
+               
+    } else if (!xmlStrcmp(cur->name, (xmlChar*)"float_array")) {
+
+        SOURCE_P src = (SOURCE_P)malloc(sizeof(SOURCE));
+        
+        char *id = (char*)xmlGetProp(cur, (xmlChar*)"id");
+        src->id = (char*)xmlGetProp(cur, (xmlChar*)"id");
+        
+        int count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));
+        src->count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));
+        src->u.array = (float*)malloc(sizeof(float) * src->count);
+        
+        char *cont =(char*)xmlNodeGetContent(cur);
+        //const char *id = get_property("id", cur);
+        //int count = atoi(get_property("count", cur));
+
+        printf("id:%s count:%d cont:%s\n", id, count, cont);
+        /* store float inpoint list */
+        for (int i = 0; cont != NULL; i++) {
+            cont = pickup_float(cont, src->u.array+i);
+        }
+
+        src->next = NULL;
+        addSource(list, src);
+        
+    }
+   
+    for (cur=cur->children; cur; cur=cur->next){
+        xml_walk(cur, s, list);
+    }    
+}
+
+void
+init_list(LIST_P list) {
+      list->first = NULL;
+        list->end = NULL;
+}
+
+
+int main(int argc, char *argv[]) {
+
+  const char *xmlColladafile = argv[1];
+
+  /*make parse dom*/
+  xmlDocPtr doc;
+  xmlNodePtr cur;
+  //,cur_images,cur_effects,cur_geometries,cur_visual_scenes;
+  //SceneGraphPtr tmp;
+
+  doc = xmlParseFile(xmlColladafile);
+  cur = xmlDocGetRootElement(doc);
+  
+  if(xmlStrcmp(cur->name, (xmlChar*)"COLLADA")){
+    return 0;
+  }
+  
+  /* node analyze */
+  struct collada_state s;
+  
+  LIST list;
+  
+  for(cur=cur->children; cur; cur=cur->next){
+    init_list(&list);
+    xml_walk(cur,&s, &list);
+  }
+
+  //printlist(list);
+  xmlFreeDoc(doc);
+
+  return 0;
+
+}