Пример #1
0
 std::string operator()(const lambda& value) const {
   template_type interpreted{value([this](const mstch::node& n) {
     return visit(render_node(ctx), n);
   })};
   auto rendered = render_context::push(ctx).render(interpreted);
   return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered;
 }
Пример #2
0
    void QuadTreeRenderer::render(Renderer *renderer, const QuadTree *qt)
    {
        renderer->set_material(m_material);
        renderer->set_vao(m_vao);
        renderer->set_primitive_type(PrimitiveType::Lines);

        const QuadTreeNode *root = qt->get_root();
        render_node(renderer, root, 0);
    }
Пример #3
0
void ast_render(FILE *f, AstNode *node, int indent_size) {
    AstRender ar = {0};
    ar.f = f;
    ar.indent_size = indent_size;
    ar.indent = 0;

    assert(node->type == NodeTypeRoot);

    render_node(&ar, node);
}
Пример #4
0
void m3ds::display() {
	if (m_file) {
		glEnable(GL_TEXTURE_2D);
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
		{
			Lib3dsNode* p;
			for (p = m_file->nodes; p != 0; p = p->next)
				render_node(p);
		}
	}
}
Пример #5
0
/*!
 *
 */
static void
display(void)
{
  Lib3dsNode *c,*t;
  Lib3dsMatrix M;
  
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  if (!file) {
    return;
  }
  c=lib3ds_file_node_by_name(file, camera, LIB3DS_CAMERA_NODE);
  t=lib3ds_file_node_by_name(file, camera, LIB3DS_TARGET_NODE);
  if (!c || !t) {
    return;
  }

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective( c->data.camera.fov, 1.0*gl_width/gl_height, 100.0, 20000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glRotatef(-90, 1.0,0,0);
  {
    GLfloat lightPos[] = {0.0f, -1.0f, 0.0f, 0.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glPushMatrix();
    glTranslatef(0,-10,0);
    glutSolidTeapot(10.0);
    glPopMatrix();
  }

  lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll);
  glMultMatrixf(&M[0][0]);

  {
    Lib3dsNode *p;
    for (p=file->nodes; p!=0; p=p->next) {
      render_node(p);
    }
  }

  if (!halt) {
    current_frame+=1.0;
    if (current_frame>file->frames) {
      current_frame=0;
    }
    lib3ds_file_eval(file, current_frame);
    glutSwapBuffers();
    glutPostRedisplay();
  }
}
Пример #6
0
void child_Appearance (struct X3D_Appearance *node) {
	struct X3D_Node *tmpN;
	
	/* printf ("in Appearance, this %d, nodeType %d\n",node, node->_nodeType);
	   printf (" vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
	   render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision); */
	
	/* Render the material node... */
	RENDER_MATERIAL_SUBNODES(node->material);
	    
	if (node->fillProperties) {
		POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->fillProperties,tmpN);
		render_node(tmpN);
	}
Пример #7
0
int main()
{
   text_t result = new_text();
   html5_document_t doc = new_html5_core_document();
   add_node(doc->body,alefbeys());

   render_node(doc->document,result);
   printf("%s\n",text_get_text(result));
   
   delete_html5_document(doc);
   delete_text(result);
   
   return 0;
}
Пример #8
0
char*
cmark_render(cmark_node *root,
             int options,
             int width,
             void (*outc)(cmark_renderer*,
                          cmark_escaping,
                          int32_t,
                          unsigned char),
             int (*render_node)(cmark_renderer *renderer,
                                cmark_node *node,
                                cmark_event_type ev_type,
                                int options))
{
	cmark_strbuf pref = GH_BUF_INIT;
	cmark_strbuf buf = GH_BUF_INIT;
	cmark_node *cur;
	cmark_event_type ev_type;
	char *result;
	cmark_iter *iter = cmark_iter_new(root);

	cmark_renderer renderer = { &buf, &pref, 0, width,
	                            0, 0, true, false, false,
	                            outc, S_cr, S_blankline, S_out
	                          };

	while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
		cur = cmark_iter_get_node(iter);
		if (!render_node(&renderer, cur, ev_type, options)) {
			// a false value causes us to skip processing
			// the node's contents.  this is used for
			// autolinks.
			cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT);
		}
	}

	// ensure final newline
	if (renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') {
		cmark_strbuf_putc(renderer.buffer, '\n');
	}

	result = (char *)cmark_strbuf_detach(renderer.buffer);

	cmark_iter_free(iter);
	cmark_strbuf_free(renderer.prefix);
	cmark_strbuf_free(renderer.buffer);

	return result;
}
Пример #9
0
	void x3ds_instance::render_node(Lib3dsNode* node)
	{
		for (Lib3dsNode* p = node->childs; p != 0; p = p->next)
		{
			render_node(p);
		}

		if (node->type == LIB3DS_OBJECT_NODE)
		{
			if (strcmp(node->name, "$$$DUMMY") == 0)
			{
				return;
			}

			Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(m_def->m_file, node->data.object.morph);
			if (mesh == NULL)
			{
				mesh = lib3ds_file_mesh_by_name(m_def->m_file, node->name);
			}
			assert(mesh);
			
			// build mesh list
			if (node->user.i == 0)
			{
				node->user.i = glGenLists(1);
				glNewList(node->user.i, GL_COMPILE);
				create_mesh_list(mesh);
				glEndList();
			}

			// exec mesh list
			glPushMatrix();
			Lib3dsObjectData* d = &node->data.object;
			glMultMatrixf(&node->matrix[0][0]);
			glTranslatef( - d->pivot[0], - d->pivot[1], - d->pivot[2]);
			glCallList(node->user.i);
			glPopMatrix();
		}
	}
Пример #10
0
    void QuadTreeRenderer::render_node(Renderer *renderer, const QuadTreeNode *node, size_t level)
    {
        if (node->has_objects())
        {
            const float radius = node->get_radius();
            const Vector2 center = node->get_center();

            Matrix4 mat_t, mat_s;
            mat_t.translation(center.x, 0.0f, center.y);
            mat_s.scale(radius, 10.0f, radius);

            renderer->set_model_matrix(mat_t * mat_s);
            renderer->set_indices(m_ibuffer, 0, 12 * 2);
            renderer->emit_command();
        }

        if (!node->is_leaf())
        {
            for (size_t i = 0; i < 4; i++)
            {
                render_node(renderer, node->get_child(i), level + 1);
            }
        }
    }
Пример #11
0
/*!
* Main display function; called whenever the scene needs to be redrawn.
*/
static void
display(void)
{
  Lib3dsNode *c,*t;
  Lib3dsFloat fov, roll;
  float near, far, dist;
  float *campos;
  float *tgt;
  Lib3dsMatrix M;
  Lib3dsCamera *cam;
  Lib3dsVector v;
  Lib3dsNode *p;

  if( file != NULL && file->background.solid.use )
    glClearColor(file->background.solid.col[0],
    file->background.solid.col[1],
    file->background.solid.col[2], 1.);

  /* TODO: fog */

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  if( anti_alias )
    glEnable(GL_POLYGON_SMOOTH);
  else
    glDisable(GL_POLYGON_SMOOTH);


  if (!file) {
    return;
  }

  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, file->ambient);

  c=lib3ds_file_node_by_name(file, camera, LIB3DS_CAMERA_NODE);
  t=lib3ds_file_node_by_name(file, camera, LIB3DS_TARGET_NODE);

  if( t != NULL )
    tgt = t->data.target.pos;

  if( c != NULL ) {
    fov = c->data.camera.fov;
    roll = c->data.camera.roll;
    campos = c->data.camera.pos;
  }

  if ((cam = lib3ds_file_camera_by_name(file, camera)) == NULL)
    return;

  near = cam->near_range;
  far = cam->far_range;

  if (c == NULL || t == NULL) {
    if( c == NULL ) {
      fov = cam->fov;
      roll = cam->roll;
      campos = cam->position;
    }
    if( t == NULL )
      tgt = cam->target;
  }

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  /* KLUDGE alert:  OpenGL can't handle a near clip plane of zero,
  * so if the camera's near plane is zero, we give it a small number.
  * In addition, many .3ds files I've seen have a far plane that's
  * much too close and the model gets clipped away.  I haven't found
  * a way to tell OpenGL not to clip the far plane, so we move it
  * further away.  A factor of 10 seems to make all the models I've
  * seen visible.
  */
  if( near <= 0. ) near = far * .001;

  gluPerspective( fov, 1.0*gl_width/gl_height, near, far);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glRotatef(-90, 1.0,0,0);

  /* User rotates the view about the target point */

  lib3ds_vector_sub(v, tgt, campos);
  dist = lib3ds_vector_length(v);

  glTranslatef(0.,dist, 0.);
  glRotatef(view_rotx, 1., 0., 0.);
  glRotatef(view_roty, 0., 1., 0.);
  glRotatef(view_rotz, 0., 0., 1.);
  glTranslatef(0.,-dist, 0.);

  lib3ds_matrix_camera(M, campos, tgt, roll);
  glMultMatrixf(&M[0][0]);

  /* Lights.  Set them from light nodes if possible.  If not, use the
  * light objects directly.
  */
  {
    static const GLfloat a[] = {0.0f, 0.0f, 0.0f, 1.0f};
    static GLfloat c[] = {1.0f, 1.0f, 1.0f, 1.0f};
    static GLfloat p[] = {0.0f, 0.0f, 0.0f, 1.0f};
    Lib3dsLight *l;

    int li=GL_LIGHT0;
    for (l=file->lights; l; l=l->next) {
      glEnable(li);

      light_update(l);

      c[0] = l->color[0];
      c[1] = l->color[1];
      c[2] = l->color[2];
      glLightfv(li, GL_AMBIENT, a);
      glLightfv(li, GL_DIFFUSE, c);
      glLightfv(li, GL_SPECULAR, c);

      p[0] = l->position[0];
      p[1] = l->position[1];
      p[2] = l->position[2];
      glLightfv(li, GL_POSITION, p);

      if (l->spot_light) {
        p[0] = l->spot[0] - l->position[0];
        p[1] = l->spot[1] - l->position[1];
        p[2] = l->spot[2] - l->position[2];
        glLightfv(li, GL_SPOT_DIRECTION, p);
      }
      ++li;
    }
  }




  if( show_object )
  {
    for (p=file->nodes; p!=0; p=p->next) {
      render_node(p);
    }
  }

  if( show_bounds )
    draw_bounds(tgt);

  if( show_cameras )
  {
    for( cam = file->cameras; cam != NULL; cam = cam->next )
    {
      lib3ds_matrix_camera(M, cam->position, cam->target, cam->roll);
      lib3ds_matrix_inv(M);

      glPushMatrix();
      glMultMatrixf(&M[0][0]);
      glScalef(size/20, size/20, size/20);
      glCallList(cameraList);
      glPopMatrix();
    }
  }

  if( show_lights )
  {
    Lib3dsLight *light;
    for( light = file->lights; light != NULL; light = light->next )
      draw_light(light->position, light->color);
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
  }


  glutSwapBuffers();
}
Пример #12
0
/*!
* Render node recursively, first children, then parent.
* Each node receives its own OpenGL display list.
*/
static void
render_node(Lib3dsNode *node)
{
  ASSERT(file);

  {
    Lib3dsNode *p;
    for (p=node->childs; p!=0; p=p->next) {
      render_node(p);
    }
  }
  if (node->type==LIB3DS_OBJECT_NODE) {
    Lib3dsMesh *mesh;

    if (strcmp(node->name,"$$$DUMMY")==0) {
      return;
    }

    mesh = lib3ds_file_mesh_by_name(file, node->data.object.morph);
    if( mesh == NULL )
      mesh = lib3ds_file_mesh_by_name(file, node->name);

    if (!mesh->user.d) {
      ASSERT(mesh);
      if (!mesh) {
        return;
      }

      mesh->user.d=glGenLists(1);
      glNewList(mesh->user.d, GL_COMPILE);

      {
        unsigned p;
        Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces);
        Lib3dsMaterial *oldmat = (Lib3dsMaterial *)-1;
        {
          Lib3dsMatrix M;
          lib3ds_matrix_copy(M, mesh->matrix);
          lib3ds_matrix_inv(M);
          glMultMatrixf(&M[0][0]);
        }
        lib3ds_mesh_calculate_normals(mesh, normalL);

        for (p=0; p<mesh->faces; ++p) {
          Lib3dsFace *f=&mesh->faceL[p];
          Lib3dsMaterial *mat=0;
#ifdef	USE_SDL
          Player_texture *pt = NULL;
          int tex_mode = 0;
#endif
          if (f->material[0]) {
            mat=lib3ds_file_material_by_name(file, f->material);
          }

          if( mat != oldmat ) {
            if (mat) {
              if( mat->two_sided )
                glDisable(GL_CULL_FACE);
              else
                glEnable(GL_CULL_FACE);

              glDisable(GL_CULL_FACE);

              /* Texturing added by Gernot < *****@*****.** > */

              if (mat->texture1_map.name[0]) {		/* texture map? */
                Lib3dsTextureMap *tex = &mat->texture1_map;
                if (!tex->user.p) {		/* no player texture yet? */
                  char texname[1024];
                  pt = malloc(sizeof(*pt));
                  tex->user.p = pt;
                  //snprintf(texname, sizeof(texname), "%s/%s", datapath, tex->name);
                  strcpy(texname, datapath);
                  strcat(texname, "/");
                  strcat(texname, tex->name);
#ifdef	DEBUG
                  printf("Loading texture map, name %s\n", texname);
#endif	/* DEBUG */
#ifdef	USE_SDL
#ifdef  USE_SDL_IMG_load
                  pt->bitmap = IMG_load(texname);
#else
                  pt->bitmap = IMG_Load(texname);
#endif /* IMG_Load */

#else /* USE_SDL */
                  pt->bitmap = NULL;
                  fputs("3dsplayer: Warning: No image loading support, skipping texture.\n", stderr);
#endif /* USE_SDL */
                  if (pt->bitmap) {	/* could image be loaded ? */
                    /* this OpenGL texupload code is incomplete format-wise!
                    * to make it complete, examine SDL_surface->format and
                    * tell us @lib3ds.sf.net about your improvements :-)
                    */
                    int upload_format = GL_RED; /* safe choice, shows errors */
#ifdef USE_SDL
                    int bytespp = pt->bitmap->format->BytesPerPixel;
                    void *pixel = NULL;
                    glGenTextures(1, &pt->tex_id);
#ifdef	DEBUG
                    printf("Uploading texture to OpenGL, id %d, at %d bytepp\n",
                      pt->tex_id, bytespp);
#endif	/* DEBUG */
                    if (pt->bitmap->format->palette) {
                      pixel = convert_to_RGB_Surface(pt->bitmap);
                      upload_format = GL_RGBA;
                    }
                    else {
                      pixel = pt->bitmap->pixels;
                      /* e.g. this could also be a color palette */
                      if (bytespp == 1) upload_format = GL_LUMINANCE;
                      else if (bytespp == 3) upload_format = GL_RGB;
                      else if (bytespp == 4) upload_format = GL_RGBA;
                    }
                    glBindTexture(GL_TEXTURE_2D, pt->tex_id);
                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                      TEX_XSIZE, TEX_YSIZE, 0,
                      GL_RGBA, GL_UNSIGNED_BYTE, NULL);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
                    glTexParameteri(GL_TEXTURE_2D,
                      GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                    glTexParameteri(GL_TEXTURE_2D,
                      GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
                    glTexSubImage2D(GL_TEXTURE_2D,
                      0, 0, 0, pt->bitmap->w, pt->bitmap->h,
                      upload_format, GL_UNSIGNED_BYTE, pixel);
                    pt->scale_x = (float)pt->bitmap->w/(float)TEX_XSIZE;
                    pt->scale_y = (float)pt->bitmap->h/(float)TEX_YSIZE;
#endif /* USE_SDL */
                    pt->valid = 1;
                  }
                  else {
                    fprintf(stderr,
                      "Load of texture %s did not succeed "
                      "(format not supported !)\n",
                      texname);
                    pt->valid = 0;
                  }
                }
                else {
                  pt = (Player_texture *)tex->user.p;
                }
                tex_mode = pt->valid;
              }
              else {
                tex_mode = 0;
              }
              glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient);
              glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);
              glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);
              glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*mat->shininess));
            }
            else {
              static const Lib3dsRgba a={0.7, 0.7, 0.7, 1.0};
              static const Lib3dsRgba d={0.7, 0.7, 0.7, 1.0};
              static const Lib3dsRgba s={1.0, 1.0, 1.0, 1.0};
              glMaterialfv(GL_FRONT, GL_AMBIENT, a);
              glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
              glMaterialfv(GL_FRONT, GL_SPECULAR, s);
              glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*0.5));
            }
            oldmat = mat;
          }

          else if (mat != NULL && mat->texture1_map.name[0]) {
            Lib3dsTextureMap *tex = &mat->texture1_map;
            if (tex != NULL && tex->user.p != NULL) {
              pt = (Player_texture *)tex->user.p;
              tex_mode = pt->valid;
            }
          }


          {
            int i;

            if (tex_mode) {
              //printf("Binding texture %d\n", pt->tex_id);
              glEnable(GL_TEXTURE_2D);
              glBindTexture(GL_TEXTURE_2D, pt->tex_id);
            }

            glBegin(GL_TRIANGLES);
            glNormal3fv(f->normal);
            for (i=0; i<3; ++i) {
              glNormal3fv(normalL[3*p+i]);

              if (tex_mode) {
                glTexCoord2f(mesh->texelL[f->points[i]][1]*pt->scale_x,
                  pt->scale_y - mesh->texelL[f->points[i]][0]*pt->scale_y);
              }

              glVertex3fv(mesh->pointL[f->points[i]].pos);
            }
            glEnd();

            if (tex_mode)
              glDisable(GL_TEXTURE_2D);
          }
        }

        free(normalL);
      }

      glEndList();
    }

    if (mesh->user.d) {
      Lib3dsObjectData *d;

      glPushMatrix();
      d=&node->data.object;
      glMultMatrixf(&node->matrix[0][0]);
      glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]);
      glCallList(mesh->user.d);
      /* glutSolidSphere(50.0, 20,20); */
      glPopMatrix();
      if( flush )
        glFlush();
    }
  }
}
Пример #13
0
void m3ds::render_node(Lib3dsNode* node) {
	assert(m_file);
	{
		Lib3dsNode* p;
		for (p = node->childs; p != 0; p = p->next)
			render_node(p);
	}
	if (node->type == LIB3DS_OBJECT_NODE) {
		if (!strcmp(node->name, "$$$DUMMY")) return;
		if (!node->user.d) {
			Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(m_file, node->name);
			assert(mesh);
			if (!mesh)
				return;
			node->user.d = glGenLists(1);
			glNewList(node->user.d, GL_COMPILE);
			{
				unsigned int p;
				Lib3dsVector* normalL = new Lib3dsVector[3 * mesh->faces];
				{
					Lib3dsMatrix M;
					lib3ds_matrix_copy(M, mesh->matrix);
					lib3ds_matrix_inv(M);
					glMultMatrixf(&M[0][0]);
				}
				lib3ds_mesh_calculate_normals(mesh, normalL);

				for (p = 0; p < mesh->faces; ++p) {
					Lib3dsFace* f = &mesh->faceL[p];
					Lib3dsMaterial* mat = 0;
					if (f->material[0]) {
						mat = lib3ds_file_material_by_name(m_file, f->material);
						if (mat->texture1_map.name[0]) {
							std::string str = mat->texture1_map.name;
							std::map<std::string, texture*>::iterator ite;
							ite = texlib::instance()->find(str);
							if (ite == texlib::instance()->end()) {
								texture* pt = NULL;
								char str2[512];
								memset(str2, 0, 512);
								sprintf(str2, "%s%s", s_prefix, str.c_str());
								char* ext = &str2[strlen(str2) - 3];
								ext[0] = tolower(ext[0]);
								ext[1] = tolower(ext[1]);
								ext[2] = tolower(ext[2]);
								if (!strcmp(ext, "tga")) {
									tga_tex* tex = new tga_tex(str2);
									if (tex->get_tex_id() != -1) {
										pt = tex;
										texlib::instance()->insert(texlib::value_type(str, pt));
									}
								} else if (!strcmp(ext, "bmp")) {
									bmp_tex* tex = new bmp_tex(str2);
									if (tex->get_tex_id() != -1) {
										pt = tex;
										texlib::instance()->insert(texlib::value_type(str, pt));
									}
								} else if (!strcmp(ext, "pcx")) {
									pcx_tex* tex = new pcx_tex(str2);
									if (tex->get_tex_id() != -1) {
										pt = tex;
										texlib::instance()->insert(texlib::value_type(str, pt));
									}
								} else {
									ext[0] = 't';
									ext[1] = 'g';
									ext[2] = 'a';
									tga_tex* tex = new tga_tex(str2);
//									str = str2;
									if (tex->get_tex_id() != -1) {
										pt = tex;
									} else {
										pt = texlib::instance()->operator[]("default.tga");
									}
									texlib::instance()->insert(texlib::value_type(str, pt));
								}
								glBindTexture(GL_TEXTURE_2D, (pt) ? pt->get_tex_id() :
									((*texlib::instance())["default.tga"])->get_tex_id());
							} else {
								glBindTexture(GL_TEXTURE_2D, (ite->second)->get_tex_id());
							}
						}	
					}
					if (mat) {
						static GLfloat a[4] = {0.0f, 0.0f, 0.0f, 1.0f};
						float s;
						glMaterialfv(GL_FRONT, GL_AMBIENT, a);
						glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);
						glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);
						s = pow(2.0f, 10.0f * mat->shininess);
						if (s > 128.0) s = 128.0;
						glMaterialf(GL_FRONT, GL_SHININESS, s);
					} else {
						Lib3dsRgba a = {0.2f, 0.2f, 0.2f, 1.0f};
						Lib3dsRgba d = {0.8f, 0.8f, 0.8f, 1.0f};
						Lib3dsRgba s = {0.0f, 0.0f, 0.0f, 1.0f};
						glMaterialfv(GL_FRONT, GL_AMBIENT, a);
						glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
						glMaterialfv(GL_FRONT, GL_SPECULAR, s);
					}
					glBegin(GL_TRIANGLES);
						glNormal3fv(f->normal);
						for (int i = 0; i < 3; ++i) {
							assert(mesh);
							if (mesh->texelL)
								glTexCoord2fv(mesh->texelL[f->points[i]]);
							glNormal3fv(normalL[3 * p + i]);
							glVertex3fv(mesh->pointL[f->points[i]].pos);
						}
					glEnd();
				}
				delete [] normalL;
			}
			glEndList();
		}
		if (node->user.d) {
			Lib3dsObjectData* d;
			glPushMatrix();
			d = &node->data.object;
			glMultMatrixf(&node->matrix[0][0]);
			glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]);
			glCallList(node->user.d);
			glPopMatrix();
		}
	}
}
Пример #14
0
/*!
 *
 */
static void
render_node(Lib3dsNode *node)
{
  ASSERT(file);

  {
    Lib3dsNode *p;
    for (p=node->childs; p!=0; p=p->next) {
      render_node(p);
    }
  }
  if (node->type==LIB3DS_OBJECT_NODE) {
    if (strcmp(node->name,"$$$DUMMY")==0) {
      return;
    }

    if (!node->user.d) {
      Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name);
      ASSERT(mesh);
      if (!mesh) {
        return;
      }

      node->user.d=glGenLists(1);
      glNewList(node->user.d, GL_COMPILE);

      {
        unsigned p;
        Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces);

        {
          Lib3dsMatrix M;
          lib3ds_matrix_copy(M, mesh->matrix);
          lib3ds_matrix_inv(M);
          glMultMatrixf(&M[0][0]);
        }
        lib3ds_mesh_calculate_normals(mesh, normalL);

        for (p=0; p<mesh->faces; ++p) {
          Lib3dsFace *f=&mesh->faceL[p];
          Lib3dsMaterial *mat=0;
          if (f->material[0]) {
            mat=lib3ds_file_material_by_name(file, f->material);
          }
          if (mat) {
            float s[1];
            s[0]=1.0;
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient);
            glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);
            glMaterialf(GL_FRONT, GL_SHININESS, 11.0-0.2*mat->shininess);
          }
          else {
            Lib3dsRgba a={0.2, 0.2, 0.2, 1.0};
            Lib3dsRgba d={0.8, 0.8, 0.8, 1.0};
            Lib3dsRgba s={0.0, 0.0, 0.0, 1.0};
            glMaterialfv(GL_FRONT, GL_AMBIENT, a);
            glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
            glMaterialfv(GL_FRONT, GL_SPECULAR, s);
          }
          {
            int i;
            glBegin(GL_TRIANGLES);
              glNormal3fv(f->normal);
              for (i=0; i<3; ++i) {
                glNormal3fv(normalL[3*p+i]);
                glVertex3fv(mesh->pointL[f->points[i]].pos);
              }
            glEnd();
          }
        }

        free(normalL);
      }

      glEndList();
    }

    if (node->user.d) {
      Lib3dsObjectData *d;

      glPushMatrix();
      d=&node->data.object;
      glMultMatrixf(&node->matrix[0][0]);
      glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]);
      glCallList(node->user.d);
      /*glutSolidSphere(50.0, 20,20);*/
      glPopMatrix();
    }
  }
}
Пример #15
0
/*!
* Render node recursively, first children, then parent.
* Each node receives its own OpenGL display list.
*/
static void
render_node(Lib3dsNode *node) {
	assert(file);
	
	
	{
		Lib3dsNode *p;
		for (p = node->childs; p != 0; p = p->next) {
			render_node(p);
		}
	}
	if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
		int index;
		Lib3dsMesh *mesh;
		Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
		
		
		if (strcmp(node->name, "$$$DUMMY") == 0) {
			return;
		}
		
		
		index = lib3ds_file_mesh_by_name(file, n->instance_name);
		if (index < 0)
			index = lib3ds_file_mesh_by_name(file, node->name);
		if (index < 0) {
			return;
		}
		mesh = file->meshes[index];
		
		
		if (!mesh->user_id) {
			assert(mesh);
			
			
			mesh->user_id = glGenLists(1);
			glNewList(mesh->user_id, GL_COMPILE);
			
			
			{
				int p;
				float (*normalL)[3] = (float(*)[3])malloc(3 * 3 * sizeof(float) * mesh->nfaces);
				Lib3dsMaterial *oldmat = (Lib3dsMaterial *) - 1;
				{
					float M[4][4];
					lib3ds_matrix_copy(M, mesh->matrix);
					lib3ds_matrix_inv(M);
					glMultMatrixf(&M[0][0]);
				}
				lib3ds_mesh_calculate_vertex_normals(mesh, normalL);
				
				
				for (p = 0; p < mesh->nfaces; ++p) {
					Lib3dsMaterial *mat = 0;
#ifdef USE_SDL
					Player_texture *pt = NULL;
					int tex_mode = 0;
#endif
					if (mesh->faces[p].material > 0) {
						mat = file->materials[mesh->faces[p].material];
					}
					
					
					if (mat != oldmat) {
						if (mat) {
							if (mat->two_sided)
								glDisable(GL_CULL_FACE);
							else
								glEnable(GL_CULL_FACE);
							
							
							glDisable(GL_CULL_FACE);
							
							
							/* Texturing added by Gernot < *****@*****.** > */
							
							
							if (mat->texture1_map.name[0]) { /* texture map? */
								Lib3dsTextureMap *tex = &mat->texture1_map;
								if (!tex->user_ptr) { /* no player texture yet? */
									char texname[1024];
									pt = (Player_texture*)malloc(sizeof(*pt));
									tex->user_ptr = pt;
									//snprintf(texname, sizeof(texname), "%s/%s", datapath, tex->name);
									strcpy(texname, datapath);
									strcat(texname, "/");
									strcat(texname, tex->name);
#ifdef DEBUG
									printf("Loading texture map, name %s\n", texname);
#endif /* DEBUG */
#ifdef USE_SDL
#ifdef USE_SDL_IMG_load
									pt->bitmap = IMG_load(texname);
#else
									pt->bitmap = IMG_Load(texname);
#endif /* IMG_Load */
									
									
#else /* USE_SDL */
									pt->bitmap = NULL;
									fputs("3dsplayer: Warning: No image loading support, skipping texture.\n", stderr);
#endif /* USE_SDL */
									if (pt->bitmap) { /* could image be loaded ? */
																		/* this OpenGL texupload code is incomplete format-wise!
																		* to make it complete, examine SDL_surface->format and
																		* tell us @lib3ds.sf.net about your improvements :-)
										*/
										int upload_format = GL_RED; /* safe choice, shows errors */
#ifdef USE_SDL
										int bytespp = pt->bitmap->format->BytesPerPixel;
										void *pixel = NULL;
										glGenTextures(1, &pt->tex_id);
#ifdef DEBUG
										printf("Uploading texture to OpenGL, id %d, at %d bytepp\n",
											pt->tex_id, bytespp);
#endif /* DEBUG */
										if (pt->bitmap->format->palette) {
											pixel = convert_to_RGB_Surface(pt->bitmap);
											upload_format = GL_RGBA;
										} else {
											pixel = pt->bitmap->pixels;
											/* e.g. this could also be a color palette */
											if (bytespp == 1) upload_format = GL_LUMINANCE;
											else if (bytespp == 3) upload_format = GL_RGB;
											else if (bytespp == 4) upload_format = GL_RGBA;
										}
										glBindTexture(GL_TEXTURE_2D, pt->tex_id);
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
											TEX_XSIZE, TEX_YSIZE, 0,
											GL_RGBA, GL_UNSIGNED_BYTE, NULL);
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
										glTexParameteri(GL_TEXTURE_2D,
											GL_TEXTURE_MAG_FILTER, GL_LINEAR);
										glTexParameteri(GL_TEXTURE_2D,
											GL_TEXTURE_MIN_FILTER, GL_LINEAR);
										glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
										glTexSubImage2D(GL_TEXTURE_2D,
											0, 0, 0, pt->bitmap->w, pt->bitmap->h,
											upload_format, GL_UNSIGNED_BYTE, pixel);
										pt->scale_x = (float)pt->bitmap->w / (float)TEX_XSIZE;
										pt->scale_y = (float)pt->bitmap->h / (float)TEX_YSIZE;
#endif /* USE_SDL */
										pt->valid = 1;
									} else {
										fprintf(stderr,
											"Load of texture %s did not succeed "
											"(format not supported !)\n",
											texname);
										pt->valid = 0;
									}
								} else {
									pt = (Player_texture *)tex->user_ptr;
								}
								tex_mode = pt->valid;
							} else {
								tex_mode = 0;
							}
							
							
							{
								float a[4], d[4], s[4];
								int i;
								for (i=0; i<3; ++i) {
									a[i] = mat->ambient[i];
									d[i] = mat->diffuse[i];
									s[i] = mat->specular[i];
								}
								a[3] = d[3] = s[3] = 1.0f;
								
								glMaterialfv(GL_FRONT, GL_AMBIENT, a);
								glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
								glMaterialfv(GL_FRONT, GL_SPECULAR, s);
							}
							glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*mat->shininess));
 } else {
	 static const float a[4] = {0.7, 0.7, 0.7, 1.0};
	 static const float d[4] = {0.7, 0.7, 0.7, 1.0};
	 static const float s[4] = {1.0, 1.0, 1.0, 1.0};
	 glMaterialfv(GL_FRONT, GL_AMBIENT, a);
	 glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
	 glMaterialfv(GL_FRONT, GL_SPECULAR, s);
	 glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*0.5));
 }
 oldmat = mat;
 }
 
 
 else if (mat != NULL && mat->texture1_map.name[0]) {
	 Lib3dsTextureMap *tex = &mat->texture1_map;
	 if (tex != NULL && tex->user_ptr != NULL) {
		 pt = (Player_texture *)tex->user_ptr;
		 tex_mode = pt->valid;
	 }
 }
 
 
 
 
 {
	 int i;
	 
#ifndef USE_GL10
	 if (tex_mode) {
		 //printf("Binding texture %d\n", pt->tex_id);
		 glEnable(GL_TEXTURE_2D);
		 glBindTexture(GL_TEXTURE_2D, pt->tex_id);
	 }
#endif	 
	 
#if 0
	 {
		 float v1[3], n[3], v2[3];
		 glBegin(GL_LINES);
		 for (i = 0; i < 3; ++i) {
			 lib3ds_vector_copy(v1, mesh->vertices[f->points[i]]);
			 glVertex3fv(v1);
			 lib3ds_vector_copy(n, normalL[3*p+i]);
			 lib3ds_vector_scalar(n, 10.f);
			 lib3ds_vector_add(v2, v1, n);
			 glVertex3fv(v2);
		 }
		 glEnd();
	 }
#endif
	 
	 
	 glBegin(GL_TRIANGLES);
	 for (i = 0; i < 3; ++i) {
		 glNormal3fv(normalL[3*p+i]);
		 
		 
		 if (tex_mode) {
			 glTexCoord2f(
				 mesh->texcos[mesh->faces[p].index[i]][1]*pt->scale_x,
				 pt->scale_y - mesh->texcos[mesh->faces[p].index[i]][0]*pt->scale_y);
		 }
		 
		 
		 glVertex3fv(mesh->vertices[mesh->faces[p].index[i]]);
	 }
	 glEnd();
	 
	 
	 if (tex_mode)
		 glDisable(GL_TEXTURE_2D);
 }
 }
 
 
 free(normalL);
 }
 
 
 glEndList();
 }
 
 
 if (mesh->user_id) {
	 glPushMatrix();
	 glMultMatrixf(&node->matrix[0][0]);
	 glTranslatef(-n->pivot[0], -n->pivot[1], -n->pivot[2]);
	 glCallList(mesh->user_id);
	 /* glutSolidSphere(50.0, 20,20); */
	 glPopMatrix();
	 if (flush)
		 glFlush();
 }
 }
}
Пример #16
0
void to_dot2_base(
    std::ostream& out,
    Iterator      begin,
    Iterator      end,
    root_namer_t  root_namer,
    node_hook_t   node_hook
)
{
    typedef std::set<node_cp> node_cset_t;
    node_clist_t queue;
    node_cset_t skip;

    copy(begin, end, std::back_inserter(queue));

    // Header
    out << "digraph G {" << std::endl;
    out << "  ordering = out;" << std::endl;
    out << "  edge [arrowsize=0.5, fontsize=9];" << std::endl;
    out << "  node [fontname=Courier, penwidth=0.2, shape=rect, height=0.4];"
        << std::endl;

    // Body
    while (! queue.empty()) {
        node_cp node = queue.front();
        queue.pop_front();
        if (skip.count(node)) {
            continue;
        }
        skip.insert(node);

        // If node is a literal...
        if (node->is_literal()) {
            render_literal(out, node);
        }
        else {
            boost::shared_ptr<const Call> call =
                boost::dynamic_pointer_cast<const Call>(node);
            assert(call);
            std::string extra;

            // Let node hook run.
            if (node_hook) {
                node_hook(out, extra, node);
            }

            // Otherwise node is a call.
            if (node->children().size() > 8) {
                // High degree nodes, have no absorbption.
                render_node(out, node,
                            "label=<" + escape_html(call->name()) + ">"
                           );
                BOOST_FOREACH(const node_cp& child, node->children()) {
                    render_edge(out, node, child);
                    queue.push_back(child);
                }
            }
            else {
                // Try to absorb children.
                std::vector<std::string> name;
                name.push_back("<b>" + call->name() + "</b>");
                unsigned int placeholder = 0;

                BOOST_FOREACH(const node_cp& child, node->children()) {
                    if (is_absorbable(child, root_namer)) {
                        if (child->to_s()[0] == '\'') {
                            name.push_back(
                                "<i>" + escape_html(child->to_s()) + "</i>"
                            );
                        }
                        else {
                            name.push_back(
                                "<font>" + escape_html(child->to_s()) +
                                "</font>"
                            );
                        }
                    }
                    else {
                        ++placeholder;
                        name.push_back(
                            "<font>" + circle_n(placeholder) + "</font>"
                        );
                        render_edge(out, node, child, circle_n(placeholder));
                        queue.push_back(child);
                    }
                }
                render_node(out, node,
                            "label=<" +
                            boost::algorithm::join(name, " ") + ">" +
                            extra
                           );
            }
        }
Пример #17
0
	void	x3ds_instance::display()
	{
		assert(m_def != NULL);

		if (m_def->m_file == NULL)
		{
			return;
		}

		//update_material();

		// save GL state
		glPushAttrib (GL_ALL_ATTRIB_BITS);	
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();

		// apply gameSWF matrix

		rect bound;
		m_def->get_bound(&bound);

		matrix m = get_parent()->get_world_matrix();
		m.transform(&bound);

		// get viewport size
		GLint vp[4]; 
		glGetIntegerv(GL_VIEWPORT, vp); 
//		int vp_width = vp[2];
		int vp_height = vp[3];

		bound.twips_to_pixels();
		int w = (int) (bound.m_x_max - bound.m_x_min);
		int h = (int) (bound.m_y_max - bound.m_y_min);
		int x = (int) bound.m_x_min;
		int y = (int) bound.m_y_min;
		glViewport(x, vp_height - y - h, w, h);

		// set 3D params

		glClear(GL_DEPTH_BUFFER_BIT);
		glDepthFunc(GL_LEQUAL);
		glEnable(GL_DEPTH_TEST);
		glCullFace(GL_BACK);

		glEnable(GL_POLYGON_SMOOTH);
//		glEnable(GL_BLEND);
//		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_BLEND);

		// set GL matrix to identity
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();

		assert(m_camera);

		Lib3dsNode* cnode = lib3ds_file_node_by_name(m_def->m_file, m_camera->name, LIB3DS_CAMERA_NODE);
		Lib3dsNode* tnode = lib3ds_file_node_by_name(m_def->m_file, m_camera->name, LIB3DS_TARGET_NODE);

		float* target = tnode ? tnode->data.target.pos : m_camera->target;

		float	view_angle;
		float roll;
		float* camera_pos;
		if (cnode)
		{
			view_angle = cnode->data.camera.fov;
			roll = cnode->data.camera.roll;
			camera_pos = cnode->data.camera.pos;
		}
		else
		{
			view_angle = m_camera->fov;
			roll = m_camera->roll;
			camera_pos = m_camera->position;
		}

		float ffar = m_camera->far_range;
		float nnear = m_camera->near_range <= 0 ? ffar * .001f : m_camera->near_range;

		float top = tan(view_angle * 0.5f) * nnear;
		float bottom = -top;
		float aspect = 1.3333f;	// 4/3 == width /height
		float left = aspect* bottom;
		float right = aspect * top;

		//	gluPerspective(fov, aspect, nnear, ffar) ==> glFrustum(left, right, bottom, top, nnear, ffar);
		//	fov * 0.5 = arctan ((top-bottom)*0.5 / near)
		//	Since bottom == -top for the symmetrical projection that gluPerspective() produces, then:
		//	top = tan(fov * 0.5) * near
		//	bottom = -top
		//	Note: fov must be in radians for the above formulae to work with the C math library. 
		//	If you have comnputer your fov in degrees (as in the call to gluPerspective()), 
		//	then calculate top as follows:
		//	top = tan(fov*3.14159/360.0) * near
		//	The left and right parameters are simply functions of the top, bottom, and aspect:
		//	left = aspect * bottom
		//	right = aspect * top
		glFrustum(left, right, bottom, top, nnear, ffar);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glRotatef(-90., 1.0, 0., 0.);

		// apply camera matrix
		Lib3dsMatrix cmatrix;
		lib3ds_matrix_camera(cmatrix, camera_pos, target, roll);
		glMultMatrixf(&cmatrix[0][0]);

		// apply light
		set_light();

		// draw 3D model

		for (Lib3dsNode* p = m_def->m_file->nodes; p != 0; p = p->next)
		{
			render_node(p);
		}

		// restore openGL state
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
		glPopAttrib();
	}
void Model3DS::draw()
{
    for (Lib3dsNode *node = file->nodes; node!=0; node=node->next) {
        render_node(node);
    }
}
Пример #19
0
static void render_node(AstRender *ar, AstNode *node) {
    assert(node->type == NodeTypeRoot || *node->parent_field == node);

    switch (node->type) {
        case NodeTypeRoot:
            for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
                AstNode *child = node->data.root.top_level_decls.at(i);
                print_indent(ar);
                render_node(ar, child);

                if (child->type == NodeTypeImport ||
                    child->type == NodeTypeVariableDeclaration ||
                    child->type == NodeTypeTypeDecl ||
                    child->type == NodeTypeErrorValueDecl ||
                    child->type == NodeTypeFnProto)
                {
                    fprintf(ar->f, ";");
                }
                fprintf(ar->f, "\n");
            }
            break;
        case NodeTypeRootExportDecl:
            zig_panic("TODO");
        case NodeTypeFnProto:
            {
                const char *fn_name = buf_ptr(&node->data.fn_proto.name);
                const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
                const char *extern_str = extern_string(node->data.fn_proto.is_extern);
                const char *inline_str = inline_string(node->data.fn_proto.is_inline);
                fprintf(ar->f, "%s%s%sfn %s(", pub_str, inline_str, extern_str, fn_name);
                int arg_count = node->data.fn_proto.params.length;
                bool is_var_args = node->data.fn_proto.is_var_args;
                for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
                    AstNode *param_decl = node->data.fn_proto.params.at(arg_i);
                    assert(param_decl->type == NodeTypeParamDecl);
                    const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
                    if (buf_len(&param_decl->data.param_decl.name) > 0) {
                        const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
                        fprintf(ar->f, "%s%s: ", noalias_str, arg_name);
                    }
                    render_node(ar, param_decl->data.param_decl.type);

                    if (arg_i + 1 < arg_count || is_var_args) {
                        fprintf(ar->f, ", ");
                    }
                }
                if (is_var_args) {
                    fprintf(ar->f, "...");
                }
                fprintf(ar->f, ")");

                AstNode *return_type_node = node->data.fn_proto.return_type;
                if (!is_node_void(return_type_node)) {
                    fprintf(ar->f, " -> ");
                    render_node(ar, return_type_node);
                }
                break;
            }
        case NodeTypeFnDef:
            if (node->data.fn_def.fn_proto->data.fn_proto.directives) {
                for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
                    render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
                }
            }
            render_node(ar, node->data.fn_def.fn_proto);
            fprintf(ar->f, " ");
            render_node(ar, node->data.fn_def.body);
            break;
        case NodeTypeFnDecl:
            zig_panic("TODO");
        case NodeTypeParamDecl:
            zig_panic("TODO");
        case NodeTypeBlock:
            fprintf(ar->f, "{\n");
            ar->indent += ar->indent_size;
            for (int i = 0; i < node->data.block.statements.length; i += 1) {
                AstNode *statement = node->data.block.statements.at(i);
                print_indent(ar);
                render_node(ar, statement);
            }
            ar->indent -= ar->indent_size;
            fprintf(ar->f, "\n");
            print_indent(ar);
            fprintf(ar->f, "}");
            break;
        case NodeTypeDirective:
            fprintf(ar->f, "#%s(",  buf_ptr(&node->data.directive.name));
            render_node(ar, node->data.directive.expr);
            fprintf(ar->f, ")\n");
            break;
        case NodeTypeReturnExpr:
            zig_panic("TODO");
        case NodeTypeDefer:
            zig_panic("TODO");
        case NodeTypeVariableDeclaration:
            {
                const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
                const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
                const char *var_name = buf_ptr(&node->data.variable_declaration.symbol);
                const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
                fprintf(ar->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name);
                if (node->data.variable_declaration.type) {
                    fprintf(ar->f, ": ");
                    render_node(ar, node->data.variable_declaration.type);
                }
                if (node->data.variable_declaration.expr) {
                    fprintf(ar->f, " = ");
                    render_node(ar, node->data.variable_declaration.expr);
                }
                break;
            }
        case NodeTypeTypeDecl:
            {
                const char *pub_str = visib_mod_string(node->data.type_decl.visib_mod);
                const char *var_name = buf_ptr(&node->data.type_decl.symbol);
                fprintf(ar->f, "%stype %s = ", pub_str, var_name);
                render_node(ar, node->data.type_decl.child_type);
                break;
            }
        case NodeTypeErrorValueDecl:
            zig_panic("TODO");
        case NodeTypeBinOpExpr:
            fprintf(ar->f, "(");
            render_node(ar, node->data.bin_op_expr.op1);
            fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op));
            render_node(ar, node->data.bin_op_expr.op2);
            fprintf(ar->f, ")");
            break;
        case NodeTypeUnwrapErrorExpr:
            zig_panic("TODO");
        case NodeTypeNumberLiteral:
            switch (node->data.number_literal.kind) {
                case NumLitUInt:
                    fprintf(ar->f, "%" PRIu64, node->data.number_literal.data.x_uint);
                    break;
                case NumLitFloat:
                    fprintf(ar->f, "%f", node->data.number_literal.data.x_float);
                    break;
            }
            break;
        case NodeTypeStringLiteral:
            if (node->data.string_literal.c) {
                fprintf(ar->f, "c");
            }
            fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf));
            break;
        case NodeTypeCharLiteral:
            {
                uint8_t c = node->data.char_literal.value;
                if (is_printable(c)) {
                    fprintf(ar->f, "'%c'", c);
                } else {
                    fprintf(ar->f, "'\\x%x'", (int)c);
                }
                break;
            }
        case NodeTypeSymbol:
            {
                TypeTableEntry *override_type = node->data.symbol_expr.override_type_entry;
                if (override_type) {
                    fprintf(ar->f, "%s", buf_ptr(&override_type->name));
                } else {
                    fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol));
                }
            }
            break;
        case NodeTypePrefixOpExpr:
            {
                PrefixOp op = node->data.prefix_op_expr.prefix_op;
                fprintf(ar->f, "%s", prefix_op_str(op));

                render_node(ar, node->data.prefix_op_expr.primary_expr);
                break;
            }
        case NodeTypeFnCallExpr:
            if (node->data.fn_call_expr.is_builtin) {
                fprintf(ar->f, "@");
            }
            fprintf(ar->f, "(");
            render_node(ar, node->data.fn_call_expr.fn_ref_expr);
            fprintf(ar->f, ")(");
            for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
                AstNode *param = node->data.fn_call_expr.params.at(i);
                if (i != 0) {
                    fprintf(ar->f, ", ");
                }
                render_node(ar, param);
            }
            fprintf(ar->f, ")");
            break;
        case NodeTypeArrayAccessExpr:
            zig_panic("TODO");
        case NodeTypeSliceExpr:
            zig_panic("TODO");
        case NodeTypeFieldAccessExpr:
            {
                AstNode *lhs = node->data.field_access_expr.struct_expr;
                Buf *rhs = &node->data.field_access_expr.field_name;
                render_node(ar, lhs);
                fprintf(ar->f, ".%s", buf_ptr(rhs));
                break;
            }
        case NodeTypeImport:
            zig_panic("TODO");
        case NodeTypeCImport:
            zig_panic("TODO");
        case NodeTypeBoolLiteral:
            zig_panic("TODO");
        case NodeTypeNullLiteral:
            zig_panic("TODO");
        case NodeTypeUndefinedLiteral:
            zig_panic("TODO");
        case NodeTypeIfBoolExpr:
            zig_panic("TODO");
        case NodeTypeIfVarExpr:
            zig_panic("TODO");
        case NodeTypeWhileExpr:
            zig_panic("TODO");
        case NodeTypeForExpr:
            zig_panic("TODO");
        case NodeTypeSwitchExpr:
            zig_panic("TODO");
        case NodeTypeSwitchProng:
            zig_panic("TODO");
        case NodeTypeSwitchRange:
            zig_panic("TODO");
        case NodeTypeLabel:
            zig_panic("TODO");
        case NodeTypeGoto:
            zig_panic("TODO");
        case NodeTypeBreak:
            zig_panic("TODO");
        case NodeTypeContinue:
            zig_panic("TODO");
        case NodeTypeAsmExpr:
            zig_panic("TODO");
        case NodeTypeStructDecl:
            {
                const char *struct_name = buf_ptr(&node->data.struct_decl.name);
                const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod);
                const char *container_str = container_string(node->data.struct_decl.kind);
                fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);
                ar->indent += ar->indent_size;
                for (int field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) {
                    AstNode *field_node = node->data.struct_decl.fields.at(field_i);
                    assert(field_node->type == NodeTypeStructField);
                    const char *field_name = buf_ptr(&field_node->data.struct_field.name);
                    print_indent(ar);
                    fprintf(ar->f, "%s", field_name);
                    if (!is_node_void(field_node->data.struct_field.type)) {
                        fprintf(ar->f, ": ");
                        render_node(ar, field_node->data.struct_field.type);
                    }
                    fprintf(ar->f, ",\n");
                }

                ar->indent -= ar->indent_size;
                fprintf(ar->f, "}");
                break;
            }
        case NodeTypeStructField:
            zig_panic("TODO");
        case NodeTypeContainerInitExpr:
            fprintf(ar->f, "(");
            render_node(ar, node->data.container_init_expr.type);
            fprintf(ar->f, "){");
            assert(node->data.container_init_expr.entries.length == 0);
            fprintf(ar->f, "}");
            break;
        case NodeTypeStructValueField:
            zig_panic("TODO");
        case NodeTypeArrayType:
            {
                fprintf(ar->f, "[");
                if (node->data.array_type.size) {
                    render_node(ar, node->data.array_type.size);
                }
                fprintf(ar->f, "]");
                if (node->data.array_type.is_const) {
                    fprintf(ar->f, "const ");
                }
                render_node(ar, node->data.array_type.child_type);
                break;
            }
        case NodeTypeErrorType:
            fprintf(ar->f, "error");
            break;
        case NodeTypeTypeLiteral:
            fprintf(ar->f, "type");
            break;
    }
}