[lib3ds] 01/02: Add autopkgtest.

Anton Gladky gladk at moszumanska.debian.org
Tue Jun 10 19:09:38 UTC 2014


This is an automated email from the git hooks/post-receive script.

gladk pushed a commit to branch master
in repository lib3ds.

commit d40d059380c4e19895550fb6e50b4fdcfbcdf129
Author: Anton Gladky <gladk at debian.org>
Date:   Mon Jun 9 18:41:49 2014 +0200

    Add autopkgtest.
---
 debian/control       |    1 +
 debian/tests/build1  | 1354 ++++++++++++++++++++++++++++++++++++++++++++++++++
 debian/tests/control |    2 +
 3 files changed, 1357 insertions(+)

diff --git a/debian/control b/debian/control
index b8296a9..eac541f 100644
--- a/debian/control
+++ b/debian/control
@@ -13,6 +13,7 @@ Standards-Version: 3.9.5
 Homepage: http://www.lib3ds.org/
 Vcs-Git: git://anonscm.debian.org/debian-science/packages/lib3ds.git
 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=debian-science/packages/lib3ds.git
+XS-Testsuite: autopkgtest
 
 Package: lib3ds-1-3
 Replaces:
diff --git a/debian/tests/build1 b/debian/tests/build1
new file mode 100755
index 0000000..02480f9
--- /dev/null
+++ b/debian/tests/build1
@@ -0,0 +1,1354 @@
+#!/bin/sh
+# autopkgtest check: Build and run a program against lib3ds
+# (C) 2014 Anton Gladky <gladk at debian.org>
+
+set -e
+
+WORKDIR=$(mktemp -d)
+trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
+cd $WORKDIR
+cat <<EOF > demo.c
+/*
+* The 3D Studio File Format Library
+* Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.lib3ds.org>
+* All rights reserved.
+*
+* This program is  free  software;  you can redistribute it and/or modify it
+* under the terms of the  GNU Lesser General Public License  as published by 
+* the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+* your option) any later version.
+*
+* This  program  is  distributed in  the  hope that it will  be useful,  but
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+* License for more details.
+*
+* You should  have received  a copy of the GNU Lesser General Public License
+* along with  this program;  if not, write to the  Free Software Foundation,
+* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* $Id: 3dsplay.c,v 1.14 2007/06/18 06:51:53 jeh Exp $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <lib3ds/file.h>
+#include <lib3ds/camera.h>
+#include <lib3ds/mesh.h>
+#include <lib3ds/node.h>
+#include <lib3ds/material.h>
+#include <lib3ds/matrix.h>
+#include <lib3ds/vector.h>
+#include <lib3ds/light.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+// OS X has a different path than everyone else
+#ifdef __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/glut.h>
+#endif
+
+#ifdef	USE_SDL
+#include <SDL_image.h>
+#endif
+
+
+
+
+#define	MOUSE_SCALE	.1	/* degrees/pixel movement */
+
+/*!
+\example player.c
+
+Previews a <i>3DS</i> file using OpenGL.
+
+\code
+Syntax: player filename
+\endcode
+
+\warning To compile this program you must have OpenGL and glut installed.
+*/
+
+
+typedef	enum {ROTATING, WALKING} RunMode;
+
+static	RunMode runMode = ROTATING;
+
+static const char* filepath=NULL;
+static char datapath[256];
+static char filename[256];
+static int dbuf=1;
+static int halt=0;
+static int flush=0;
+static int anti_alias=1;
+
+static const char* camera=0;
+static Lib3dsFile *file=0;
+static float current_frame=0.0;
+static int gl_width;
+static int gl_height;
+static int menu_id=0;
+static int show_object=1;
+static int show_bounds=0;
+static int rotating = 0;
+static int show_cameras = 0;
+static int show_lights = 0;
+
+static int cameraList, lightList;	/* Icon display lists */
+
+static Lib3dsVector bmin, bmax;
+static float	sx, sy, sz, size;	/* bounding box dimensions */
+static float	cx, cy, cz;		/* bounding box center */
+
+static	float	view_rotx = 0., view_roty = 0., view_rotz = 0.;
+static	float	anim_rotz = 0.;
+
+static	int	mx, my;
+
+static const GLfloat white[4] = {1.,1.,1.,1.};
+static const GLfloat dgrey[4] = {.25,.25,.25,1.};
+static const GLfloat grey[4] = {.5,.5,.5,1.};
+static const GLfloat lgrey[4] = {.75,.75,.75,1.};
+static const GLfloat black[] = {0.,0.,0.,1.};
+static const GLfloat red[4] = {1.,0.,0.,1.};
+static const GLfloat green[4] = {0.,1.,0.,1.};
+static const GLfloat blue[4] = {0.,0.,1.,1.};
+
+
+static	void	solidBox(double bx, double by, double bz);
+static	void	solidCylinder(double r, double h, int slices);
+static	int	callback(void (*cb)(int m, int d, void *), void *client);
+static	void	call_callback(int idx, int data);
+
+static void solidBox(double bx, double by, double bz);
+static void solidCylinder(double r, double h, int slices);
+static const char *Basename(const char *filename);
+
+
+// texture size: by now minimum standard
+#define	TEX_XSIZE	1024
+#define	TEX_YSIZE	1024
+
+struct _player_texture
+{
+  int valid; // was the loading attempt successful ? 
+#ifdef	USE_SDL
+  SDL_Surface *bitmap;
+#else
+  void *bitmap;
+#endif
+  GLuint tex_id; //OpenGL texture ID
+  float scale_x, scale_y; // scale the texcoords, as OpenGL thinks in TEX_XSIZE and TEX_YSIZE
+};
+
+typedef struct _player_texture Player_texture; 
+Player_texture *pt; 
+int tex_mode; // Texturing active ? 
+
+#define	NA(a)	(sizeof(a)/sizeof(a[0]))
+
+#ifndef	MIN
+#define	MIN(a,b) ((a)<(b)?(a):(b))
+#define	MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+
+
+
+static	void
+menu_cb(int value)
+{
+  call_callback(value, 0);
+}
+
+
+/*!
+* Switch cameras based on user's menu choice.
+*/
+static void
+camera_menu(int menu, int value, void *client)
+{
+  Lib3dsCamera *c = (Lib3dsCamera*)client;
+  view_rotx = view_roty = view_rotz = anim_rotz = 0.;
+  camera=c->name;
+}
+
+
+/*!
+* Toggle an arbitrary int (bool) variable
+*/
+static	void
+toggle_bool(int menu, int value, void *client)
+{
+  int *var = client;
+  *var = !*var;
+  glutPostRedisplay();
+}
+
+
+
+/*!
+* Build the menu
+*/
+static void
+build_menu()
+{
+  Lib3dsCamera *c;
+  int i;
+  menu_id=glutCreateMenu(menu_cb);
+
+  for (c=file->cameras,i=0; c; c=c->next,++i)
+    glutAddMenuEntry(c->name, callback(camera_menu, c));
+
+  glutAddMenuEntry("Show cameras", callback(toggle_bool, &show_cameras));
+  glutAddMenuEntry("Show lights", callback(toggle_bool, &show_lights));
+  glutAddMenuEntry("Show bounds", callback(toggle_bool, &show_bounds));
+}
+
+
+/*!
+* Time function, called every frame
+*/
+static	void
+timer_cb(int value)
+{
+  glutPostRedisplay();
+
+  if (!halt) {
+    view_rotz += anim_rotz;
+    current_frame+=1.0;
+    if (current_frame>file->frames) {
+      current_frame=0;
+    }
+    lib3ds_file_eval(file, current_frame);
+    glutTimerFunc(10, timer_cb, 0);
+  }
+}
+
+static	void
+set_halt(int h)
+{
+  if( h != halt ) {
+    halt = h;
+    if( !halt )
+      glutTimerFunc(10, timer_cb, 0);
+  }
+}
+
+
+
+/*!
+* Initialize OpenGL
+*/
+static void
+init(void)
+{
+  glClearColor(0.5, 0.5, 0.5, 1.0);
+  glShadeModel(GL_SMOOTH);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  glDisable(GL_LIGHT1);
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_DEPTH_TEST);
+  glCullFace(GL_BACK);
+  //glDisable(GL_NORMALIZE);
+  //glPolygonOffset(1.0, 2);
+}
+
+
+/*!
+* Load the model from .3ds file.
+*/
+static void
+load_model(void)
+{
+  file=lib3ds_file_load(filepath);
+  if (!file) {
+    puts("3dsplayer: Error: Loading 3DS file failed.\n");
+    exit(1);
+  }
+
+  /* No nodes?  Fabricate nodes to display all the meshes. */
+  if( !file->nodes )
+  {
+    Lib3dsMesh *mesh;
+    Lib3dsNode *node;
+
+    for(mesh = file->meshes; mesh != NULL; mesh = mesh->next)
+    {
+      node = lib3ds_node_new_object();
+      strcpy(node->name, mesh->name);
+      node->parent_id = LIB3DS_NO_PARENT;
+      lib3ds_file_insert_node(file, node);
+    }
+  }
+
+  lib3ds_file_eval(file, 1.0f);
+  lib3ds_file_bounding_box_of_nodes(file, LIB3DS_TRUE, LIB3DS_FALSE, LIB3DS_FALSE, bmin, bmax);
+  sx = bmax[0] - bmin[0];
+  sy = bmax[1] - bmin[1];
+  sz = bmax[2] - bmin[2];
+  size = MAX(sx, sy); size = MAX(size, sz);
+  cx = (bmin[0] + bmax[0])/2;
+  cy = (bmin[1] + bmax[1])/2;
+  cz = (bmin[2] + bmax[2])/2;
+
+
+  /* No cameras in the file?  Add four */
+
+  if( !file->cameras ) {
+
+    /* Add some cameras that encompass the bounding box */
+
+    Lib3dsCamera *camera = lib3ds_camera_new("Camera_X");
+    camera->target[0] = cx;
+    camera->target[1] = cy;
+    camera->target[2] = cz;
+    memcpy(camera->position, camera->target, sizeof(camera->position));
+    camera->position[0] = bmax[0] + 1.5 * MAX(sy,sz);
+    camera->near_range = ( camera->position[0] - bmax[0] ) * .5;
+    camera->far_range = ( camera->position[0] - bmin[0] ) * 2;
+    lib3ds_file_insert_camera(file, camera);
+
+    /* Since lib3ds considers +Y to be into the screen, we'll put
+    * this camera on the -Y axis, looking in the +Y direction.
+    */
+    camera = lib3ds_camera_new("Camera_Y");
+    camera->target[0] = cx;
+    camera->target[1] = cy;
+    camera->target[2] = cz;
+    memcpy(camera->position, camera->target, sizeof(camera->position));
+    camera->position[1] = bmin[1] - 1.5 * MAX(sx,sz);
+    camera->near_range = ( bmin[1] - camera->position[1] ) * .5;
+    camera->far_range = ( bmax[1] - camera->position[1] ) * 2;
+    lib3ds_file_insert_camera(file, camera);
+
+    camera = lib3ds_camera_new("Camera_Z");
+    camera->target[0] = cx;
+    camera->target[1] = cy;
+    camera->target[2] = cz;
+    memcpy(camera->position, camera->target, sizeof(camera->position));
+    camera->position[2] = bmax[2] + 1.5 * MAX(sx,sy);
+    camera->near_range = ( camera->position[2] - bmax[2] ) * .5;
+    camera->far_range = ( camera->position[2] - bmin[2] ) * 2;
+    lib3ds_file_insert_camera(file, camera);
+
+    camera = lib3ds_camera_new("Camera_ISO");
+    camera->target[0] = cx;
+    camera->target[1] = cy;
+    camera->target[2] = cz;
+    memcpy(camera->position, camera->target, sizeof(camera->position));
+    camera->position[0] = bmax[0] + .75 * size;
+    camera->position[1] = bmin[1] - .75 * size;
+    camera->position[2] = bmax[2] + .75 * size;
+    camera->near_range = ( camera->position[0] - bmax[0] ) * .5;
+    camera->far_range = ( camera->position[0] - bmin[0] ) * 3;
+    lib3ds_file_insert_camera(file, camera);
+  }
+
+
+  /* No lights in the file?  Add some. */
+
+  if (file->lights == NULL)
+  {
+    Lib3dsLight *light;
+
+    light = lib3ds_light_new("light0");
+    light->spot_light = 0;
+    light->see_cone = 0;
+    light->color[0] = light->color[1] = light->color[2] = .6;
+    light->position[0] = cx + size * .75;
+    light->position[1] = cy - size * 1.;
+    light->position[2] = cz + size * 1.5;
+    light->position[3] = 0.;
+    light->outer_range = 100;
+    light->inner_range = 10;
+    light->multiplier = 1;
+    lib3ds_file_insert_light(file, light);
+
+    light = lib3ds_light_new("light1");
+    light->spot_light = 0;
+    light->see_cone = 0;
+    light->color[0] = light->color[1] = light->color[2] = .3;
+    light->position[0] = cx - size;
+    light->position[1] = cy - size;
+    light->position[2] = cz + size * .75;
+    light->position[3] = 0.;
+    light->outer_range = 100;
+    light->inner_range = 10;
+    light->multiplier = 1;
+    lib3ds_file_insert_light(file, light);
+
+    light = lib3ds_light_new("light2");
+    light->spot_light = 0;
+    light->see_cone = 0;
+    light->color[0] = light->color[1] = light->color[2] = .3;
+    light->position[0] = cx;
+    light->position[1] = cy + size;
+    light->position[2] = cz + size;
+    light->position[3] = 0.;
+    light->outer_range = 100;
+    light->inner_range = 10;
+    light->multiplier = 1;
+    lib3ds_file_insert_light(file, light);
+
+  }
+
+  if (!file->cameras) {
+    fputs("3dsplayer: Error: No Camera found.\n", stderr);
+    lib3ds_file_free(file);
+    file=0;
+    exit(1);
+  }
+  if (!camera) {
+    camera=file->cameras->name;
+  }
+
+  lib3ds_file_eval(file,0.);
+}
+
+
+
+#ifdef  USE_SDL
+/**
+* Convert an SDL bitmap for use with OpenGL.
+*
+* Written by Gernot < gz at lysator.liu.se >
+*/
+void *convert_to_RGB_Surface(SDL_Surface *bitmap)
+{
+  unsigned char *pixel = (unsigned char *)malloc(sizeof(char) * 4 * bitmap->h * bitmap->w); 
+  int soff = 0;   
+  int doff = 0;   
+  int x, y;
+  unsigned char *spixels = (unsigned char *)bitmap->pixels;
+  SDL_Palette *pal = bitmap->format->palette; 
+
+  for (y = 0; y < bitmap->h; y++)
+    for (x = 0; x < bitmap->w; x++)
+    {
+      SDL_Color* col = &pal->colors[spixels[soff]];
+
+      pixel[doff] = col->r; 
+      pixel[doff+1] = col->g; 
+      pixel[doff+2] = col->b; 
+      pixel[doff+3] = 255; 
+      doff += 4; 
+      soff++;
+    }
+
+    return (void *)pixel; 
+}
+#endif
+
+
+
+
+/*!
+* 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 < gz at lysator.liu.se > */
+
+              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();
+    }
+  }
+}
+
+
+
+
+/*!
+* Update information about a light.  Try to find corresponding nodes
+* if possible, and copy values from nodes into light struct.
+*/
+
+static void
+light_update(Lib3dsLight *l)
+{
+  Lib3dsNode *ln, *sn;
+
+  ln = lib3ds_file_node_by_name(file, l->name, LIB3DS_LIGHT_NODE);
+  sn = lib3ds_file_node_by_name(file, l->name, LIB3DS_SPOT_NODE);
+
+  if( ln != NULL ) {
+    memcpy(l->color, ln->data.light.col, sizeof(Lib3dsRgb));
+    memcpy(l->position, ln->data.light.pos, sizeof(Lib3dsVector));
+  }
+
+  if( sn != NULL )
+    memcpy(l->spot, sn->data.spot.pos, sizeof(Lib3dsVector));
+}
+
+
+
+
+static	void
+draw_bounds(Lib3dsVector tgt)
+{
+  double cx,cy,cz;
+  double lx,ly,lz;
+
+  lx = sx / 10.; ly = sy / 10.; lz = sz / 10.;
+  cx = tgt[0]; cy = tgt[1]; cz = tgt[2];
+
+  glDisable(GL_LIGHTING);
+  glColor4fv(white);
+  glBegin(GL_LINES);
+  glVertex3f(bmin[0],bmin[1],bmin[2]);
+  glVertex3f(bmax[0],bmin[1],bmin[2]);
+  glVertex3f(bmin[0],bmax[1],bmin[2]);
+  glVertex3f(bmax[0],bmax[1],bmin[2]);
+  glVertex3f(bmin[0],bmin[1],bmax[2]);
+  glVertex3f(bmax[0],bmin[1],bmax[2]);
+  glVertex3f(bmin[0],bmax[1],bmax[2]);
+  glVertex3f(bmax[0],bmax[1],bmax[2]);
+
+  glVertex3f(bmin[0],bmin[1],bmin[2]);
+  glVertex3f(bmin[0],bmax[1],bmin[2]);
+  glVertex3f(bmax[0],bmin[1],bmin[2]);
+  glVertex3f(bmax[0],bmax[1],bmin[2]);
+  glVertex3f(bmin[0],bmin[1],bmax[2]);
+  glVertex3f(bmin[0],bmax[1],bmax[2]);
+  glVertex3f(bmax[0],bmin[1],bmax[2]);
+  glVertex3f(bmax[0],bmax[1],bmax[2]);
+
+  glVertex3f(bmin[0],bmin[1],bmin[2]);
+  glVertex3f(bmin[0],bmin[1],bmax[2]);
+  glVertex3f(bmax[0],bmin[1],bmin[2]);
+  glVertex3f(bmax[0],bmin[1],bmax[2]);
+  glVertex3f(bmin[0],bmax[1],bmin[2]);
+  glVertex3f(bmin[0],bmax[1],bmax[2]);
+  glVertex3f(bmax[0],bmax[1],bmin[2]);
+  glVertex3f(bmax[0],bmax[1],bmax[2]);
+
+  glVertex3f(cx-size/32, cy, cz);
+  glVertex3f(cx+size/32, cy, cz);
+  glVertex3f(cx, cy-size/32, cz);
+  glVertex3f(cx, cy+size/32, cz);
+  glVertex3f(cx, cy, cz-size/32);
+  glVertex3f(cx, cy, cz+size/32);
+  glEnd();
+
+
+  glColor4fv(red);
+  glBegin(GL_LINES);
+  glVertex3f(0.,0.,0.);
+  glVertex3f(lx,0.,0.);
+  glEnd();
+
+  glColor4fv(green);
+  glBegin(GL_LINES);
+  glVertex3f(0.,0.,0.);
+  glVertex3f(0.,ly,0.);
+  glEnd();
+
+  glColor4fv(blue);
+  glBegin(GL_LINES);
+  glVertex3f(0.,0.,0.);
+  glVertex3f(0.,0.,lz);
+  glEnd();
+
+  glEnable(GL_LIGHTING);
+}
+
+
+static void
+draw_light(const GLfloat *pos, const GLfloat *color)
+{
+  glMaterialfv(GL_FRONT, GL_EMISSION, color);
+  glPushMatrix();
+  glTranslatef(pos[0], pos[1], pos[2]);
+  glScalef(size/20, size/20, size/20);
+  glCallList(lightList);
+  glPopMatrix();
+}
+
+
+
+/*!
+* 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();
+}
+
+
+/*!
+*
+*/
+static void
+reshape (int w, int h)
+{
+  gl_width=w;
+  gl_height=h;
+  glViewport(0,0,w,h);
+}
+
+
+/*!
+*
+*/
+static void
+keyboard(unsigned char key, int x, int y)
+{
+  switch (key) {
+case 27:
+  exit(0);
+  break;
+case 'h':
+  set_halt(!halt);
+  break;
+case 'a':
+  anim_rotz += .05;
+  break;
+case 'A':
+  anim_rotz -= .05;
+  break;
+case 'r':
+  view_rotx = view_roty = view_rotz = anim_rotz = 0.;
+  break;
+case 'z':
+  view_roty += 5.;
+  break;
+case 'Z':
+  view_roty -= 5.;
+  break;
+case 'b':
+  show_bounds = !show_bounds;
+  break;
+case 'o':
+  show_object = !show_object;
+  break;
+case '\001':
+  anti_alias = !anti_alias;
+  break;
+  }
+}
+
+
+/*!
+* Respond to mouse buttons.  Action depends on current operating mode.
+*/
+static	void
+mouse_cb(int button, int state, int x, int y)
+{
+  mx = x; my = y;
+  switch( button ) {
+case GLUT_LEFT_BUTTON:
+  switch( runMode ) {
+case ROTATING: rotating = state == GLUT_DOWN; break;
+default: break;
+  }
+  break;
+default:
+  break;
+  }
+}
+
+
+/*!
+* Respond to mouse motions; left button rotates the image or performs
+* other action according to current operating mode.
+*/
+static void
+drag_cb(int x, int y)
+{
+  if( rotating ) {
+    view_rotz += MOUSE_SCALE * (x - mx);
+    view_rotx += MOUSE_SCALE * (y - my);
+    mx = x;
+    my = y;
+    glutPostRedisplay();
+  }
+}
+
+
+/*!
+* Create camera and light icons
+*/
+static void
+create_icons()
+{
+  GLUquadricObj *qobj;
+
+#define	CBX	.25	// camera body dimensions
+#define	CBY	1.5
+#define	CBZ	1.
+
+  qobj = gluNewQuadric();
+  gluQuadricDrawStyle(qobj, GLU_FILL);
+  gluQuadricNormals(qobj, GLU_SMOOTH);
+
+  cameraList = glGenLists(1);
+  glNewList(cameraList, GL_COMPILE);
+  glMaterialfv(GL_FRONT, GL_AMBIENT, dgrey);
+  glMaterialfv(GL_FRONT, GL_DIFFUSE, lgrey);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, black);
+  glEnable(GL_CULL_FACE);
+  solidBox(CBX,CBY,CBZ);
+  glPushMatrix();
+  glTranslatef(0.,.9,1.8);
+  glRotatef(90., 0.,1.,0.);
+  solidCylinder(1., CBX*2, 12);
+  glTranslatef(0.,-1.8,0.);
+  solidCylinder(1., CBX*2, 12);
+  glPopMatrix();
+  glDisable(GL_CULL_FACE);
+  glPushMatrix();
+  glTranslated(0.,CBY,0.);
+  glRotated(-90., 1.,0.,0.);
+  gluCylinder(qobj, .2, .5, 1., 12, 1);
+  glPopMatrix();
+  glEndList();
+
+  lightList = glGenLists(1);
+  glNewList(lightList, GL_COMPILE);
+  glPushMatrix();
+  glMaterialfv(GL_FRONT, GL_AMBIENT, dgrey);
+  glMaterialfv(GL_FRONT, GL_DIFFUSE, dgrey);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, grey);
+  glEnable(GL_CULL_FACE);
+  gluSphere(qobj, .5, 12., 6.);
+  glRotated(180.,1.,0.,0.);
+  glMaterialfv(GL_FRONT, GL_EMISSION, dgrey);
+  gluCylinder(qobj, .2, .2, 1., 12, 1);
+  glPopMatrix();
+  glEndList();
+}
+
+
+void decompose_datapath(const char *fn)
+{
+  const char *ptr = strrchr(fn, '/');
+
+  if (ptr == NULL) {
+    strcpy(datapath, ".");
+    strcpy(filename, fn);
+  }
+  else {
+    strcpy(filename, ptr+1);
+    strcpy(datapath, fn);
+    datapath[ptr - fn] = '\0';
+  }
+}
+
+
+/*!
+*
+*/
+int
+main(int argc, char** argv)
+{
+  char *progname = argv[0];
+
+  glutInit(&argc, argv);
+
+  for(++argv; --argc > 0; ++argv)
+  {
+    if( strcmp(*argv, "-help") ==  0 || strcmp(*argv, "--help") == 0 )
+    {
+      fputs("View a 3DS model file using OpenGL.\n", stderr);
+      fputs("Usage: 3dsplayer [-nodb|-aa|-flush] <filename>\n", stderr);
+#ifndef USE_SDL
+      fputs("Texture rendering is not available; install SDL_image and recompile.\n", stderr);
+#endif
+      exit(0);
+    }
+    else if( strcmp(*argv, "-nodb") == 0 )
+      dbuf = 0;
+    else if( strcmp(*argv, "-aa") == 0 )
+      anti_alias = 1;
+    else if( strcmp(*argv, "-flush") == 0 )
+      flush = 1;
+    else {
+      filepath = *argv;
+      decompose_datapath(filepath);
+    }
+  }
+
+  if (filepath == NULL) {
+    fputs("3dsplayer: Error: No 3DS file specified\n", stderr);
+    exit(1);
+  }
+
+  glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | (dbuf ? GLUT_DOUBLE:0) );
+  glutInitWindowSize(500, 500);
+  glutInitWindowPosition(100, 100);
+  glutCreateWindow(filepath != NULL ? Basename(filepath) : progname);
+
+  init();
+  create_icons();
+  load_model();
+
+  build_menu();
+  glutAttachMenu(2);
+
+  glutDisplayFunc(display);
+  glutReshapeFunc(reshape);
+  glutKeyboardFunc(keyboard);
+  glutMouseFunc(mouse_cb);
+  glutMotionFunc(drag_cb);
+  glutTimerFunc(10, timer_cb, 0);
+  glutMainLoop();
+  return(0);
+}
+
+
+

+
+
+/* A few small utilities, so generic that they probably
+* don't even belong in this file.
+*/
+
+
+
+/*!
+* Render a box, centered at 0,0,0
+*
+* Box may be rendered with face culling enabled.
+*/
+static void
+solidBox(double bx, double by, double bz)
+{
+  glBegin(GL_POLYGON);
+  glNormal3d(0.,0.,1.);
+  glVertex3d(bx,by,bz);
+  glVertex3d(-bx,by,bz);
+  glVertex3d(-bx,-by,bz);
+  glVertex3d(bx,-by,bz);
+  glEnd();
+  glBegin(GL_POLYGON);
+  glNormal3d(0.,0.,-1.);
+  glVertex3d(-bx,by,-bz);
+  glVertex3d(bx,by,-bz);
+  glVertex3d(bx,-by,-bz);
+  glVertex3d(-bx,-by,-bz);
+  glEnd();
+  glBegin(GL_POLYGON);
+  glNormal3d(0.,-1.,0.);
+  glVertex3d(-bx,by,bz);
+  glVertex3d(bx,by,bz);
+  glVertex3d(bx,by,-bz);
+  glVertex3d(-bx,by,-bz);
+  glEnd();
+  glBegin(GL_POLYGON);
+  glNormal3d(0.,-1.,0.);
+  glVertex3d(bx,-by,bz);
+  glVertex3d(-bx,-by,bz);
+  glVertex3d(-bx,-by,-bz);
+  glVertex3d(bx,-by,-bz);
+  glEnd();
+  glBegin(GL_POLYGON);
+  glNormal3d(1.,0.,0.);
+  glVertex3d(bx,by,bz);
+  glVertex3d(bx,-by,bz);
+  glVertex3d(bx,-by,-bz);
+  glVertex3d(bx,by,-bz);
+  glEnd();
+  glBegin(GL_POLYGON);
+  glNormal3d(-1.,0.,0.);
+  glVertex3d(-bx,by,-bz);
+  glVertex3d(-bx,-by,-bz);
+  glVertex3d(-bx,-by,bz);
+  glVertex3d(-bx,by,bz);
+  glEnd();
+}
+
+
+
+/*!
+* Render a cylinder with end caps, along the Z axis centered at 0,0,0
+*
+* Cylinder may be rendered with face culling enabled.
+*/
+static void
+solidCylinder(double r, double h, int slices)
+{
+  GLUquadricObj *qobj = gluNewQuadric();
+  gluQuadricDrawStyle(qobj, GLU_FILL);
+  gluQuadricNormals(qobj, GLU_SMOOTH);
+
+  glPushMatrix();
+  glTranslated(0., 0., -h/2);
+  gluCylinder( qobj, r, r, h, slices, 1 );
+  glPushMatrix();
+  glRotated(180., 1.,0.,0.);
+  gluDisk( qobj, 0., r, slices, 1 );
+  glPopMatrix();
+  glTranslated(0., 0., h);
+  gluDisk( qobj, 0., r, slices, 1 );
+  glPopMatrix();
+}
+
+
+static const char *
+Basename(const char *filename)
+{
+  char *ptr = strrchr(filename, '/');
+  return ptr != NULL ? ptr+1 : filename;
+}
+
+
+
+/*
+* This module is a crude front end to the GLUT menu system, allowing for
+* slightly more sophisticated callbacks.
+*/
+
+#include <stdio.h>
+
+#define	MAX_CALLBACKS	100
+
+typedef struct {
+  void (*cb)(int, int, void *);
+  void	*client;
+} Callback;
+
+
+static	Callback	callbacks[MAX_CALLBACKS];
+static	int		ncb = 0;
+
+/*!
+* Register a callback, returning an integer value suitable for
+* passing to glutAddMenuEntry()
+*
+* \param cb Callback function to be called.
+* \param client Data to be passed to the callback.
+*
+* \return integer callback id
+*/
+static int
+callback(void (*cb)(int, int, void *client), void *client)
+{
+  if( ncb == 0 )
+  {
+    int i;
+    for(i=0; i < NA(callbacks); ++i)
+      callbacks[i].cb = NULL;
+  }
+  else if( ncb >= NA(callbacks) ) {
+    fprintf(stderr,
+      "callback() out of callbacks, try changing MAX_CALLBACKS\n");
+  }
+
+  callbacks[ncb].cb = cb;
+  callbacks[ncb].client = client;
+  return ncb++;
+}
+
+
+/*!
+* Call the indexed callback.
+*
+* \param idx Callback index.
+* \param data Data to be passed to the callback
+*/
+static void
+call_callback(int idx, int data)
+{
+  if( idx >= 0 && idx < NA(callbacks) && callbacks[idx].cb != NULL )
+    callbacks[idx].cb(idx, data, callbacks[idx].client);
+}
+
+EOF
+
+gcc -o demo demo.c -l3ds -lglut -lGL -lm -lGLU
+echo "build: OK"
+[ -x demo ]
+#./demo
+#touch a
+#xvfb-run --auth-file=a ./demo
+#echo "run: OK"
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..ecca1e1
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,2 @@
+Tests: build1
+Depends: freeglut3-dev, lib3ds-dev, build-essential

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/lib3ds.git



More information about the debian-science-commits mailing list