Exemplo n.º 1
0
/*!
 * \ingroup mesh
 */
Lib3dsBool
lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io)
{
  Lib3dsChunk c;
  Lib3dsWord chunk;

  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) {
    return(LIB3DS_FALSE);
  }

  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
    switch (chunk) {
      case LIB3DS_MESH_MATRIX:
        {
          int i,j;
          
          lib3ds_matrix_identity(mesh->matrix);
          for (i=0; i<4; i++) {
            for (j=0; j<3; j++) {
              mesh->matrix[i][j]=lib3ds_io_read_float(io);
            }
          }
        }
        break;
      case LIB3DS_MESH_COLOR:
        {
          mesh->color=lib3ds_io_read_byte(io);
        }
        break;
      case LIB3DS_POINT_ARRAY:
        {
          unsigned i,j;
          unsigned points;
          
          lib3ds_mesh_free_point_list(mesh);
          points=lib3ds_io_read_word(io);
          if (points) {
            if (!lib3ds_mesh_new_point_list(mesh, points)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->points; ++i) {
              for (j=0; j<3; ++j) {
                mesh->pointL[i].pos[j]=lib3ds_io_read_float(io);
              }
            }
            ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
            ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
          }
        }
        break;
      case LIB3DS_POINT_FLAG_ARRAY:
        {
          unsigned i;
          unsigned flags;
          
          lib3ds_mesh_free_flag_list(mesh);
          flags=lib3ds_io_read_word(io);
          if (flags) {
            if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->flags; ++i) {
              mesh->flagL[i]=lib3ds_io_read_word(io);
            }
            ASSERT((!mesh->points) || (mesh->flags==mesh->points));
            ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
          }
        }
        break;
      case LIB3DS_FACE_ARRAY:
        {
          lib3ds_chunk_read_reset(&c, io);
          if (!face_array_read(mesh, io)) {
            return(LIB3DS_FALSE);
          }
        }
        break;
      case LIB3DS_MESH_TEXTURE_INFO:
        {
          int i,j;

          for (i=0; i<2; ++i) {
            mesh->map_data.tile[i]=lib3ds_io_read_float(io);
          }
          for (i=0; i<3; ++i) {
            mesh->map_data.pos[i]=lib3ds_io_read_float(io);
          }
          mesh->map_data.scale=lib3ds_io_read_float(io);

          lib3ds_matrix_identity(mesh->map_data.matrix);
          for (i=0; i<4; i++) {
            for (j=0; j<3; j++) {
              mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io);
            }
          }
          for (i=0; i<2; ++i) {
            mesh->map_data.planar_size[i]=lib3ds_io_read_float(io);
          }
          mesh->map_data.cylinder_height=lib3ds_io_read_float(io);
        }
        break;
      case LIB3DS_TEX_VERTS:
        {
          unsigned i;
          unsigned texels;
          
          lib3ds_mesh_free_texel_list(mesh);
          texels=lib3ds_io_read_word(io);
          if (texels) {
            if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->texels; ++i) {
              mesh->texelL[i][0]=lib3ds_io_read_float(io);
              mesh->texelL[i][1]=lib3ds_io_read_float(io);
            }
            ASSERT((!mesh->points) || (mesh->texels==mesh->points));
            ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
          }
        }
        break;
      default:
        lib3ds_chunk_unknown(chunk);
    }
  }
  {
    unsigned j;

    for (j=0; j<mesh->faces; ++j) {
      ASSERT(mesh->faceL[j].points[0]<mesh->points);
      ASSERT(mesh->faceL[j].points[1]<mesh->points);
      ASSERT(mesh->faceL[j].points[2]<mesh->points);
      lib3ds_vector_normal(
        mesh->faceL[j].normal,
        mesh->pointL[mesh->faceL[j].points[0]].pos,
        mesh->pointL[mesh->faceL[j].points[1]].pos,
        mesh->pointL[mesh->faceL[j].points[2]].pos
      );
    }
  }

  if (lib3ds_matrix_det(mesh->matrix) < 0.0)
  {
    /* Flip X coordinate of vertices if mesh matrix 
       has negative determinant */
    Lib3dsMatrix inv_matrix, M;
    Lib3dsVector tmp;
    unsigned i;

    lib3ds_matrix_copy(inv_matrix, mesh->matrix);
    lib3ds_matrix_inv(inv_matrix);

    lib3ds_matrix_copy(M, mesh->matrix);
    lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f);
    lib3ds_matrix_mult(M, inv_matrix);

    for (i=0; i<mesh->points; ++i) {
      lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos);
      lib3ds_vector_copy(mesh->pointL[i].pos, tmp);
    }
  }

  lib3ds_chunk_read_end(&c, io);

  return(LIB3DS_TRUE);
}
Exemplo n.º 2
0
Lib3dsMesh* GLC_WorldTo3ds::create3dsMeshFromGLC_Mesh(GLC_Mesh* pMesh, const QString& meshName)
{
	// Create empty 3ds mesh with the given name
	Lib3dsMesh* p3dsMesh= lib3ds_mesh_new(meshName.toLocal8Bit().data());

	const int stride= 3;

	GLfloatVector vertice= pMesh->positionVector();
	const uint pointsCount= vertice.count() / stride;

	// Add points to the 3DS mesh
	lib3ds_mesh_new_point_list(p3dsMesh, pointsCount);

	for (uint i= 0; i < pointsCount; ++i)
	{
		Lib3dsPoint point;
		point.pos[0]= vertice[i * 3];
		point.pos[1]= vertice[i * 3 + 1];
		point.pos[2]= vertice[i * 3 + 2];

		p3dsMesh->pointL[i]= point;
	}

	// Add texel to the 3DS mesh
	GLfloatVector texelVector= pMesh->texelVector();
	if(!texelVector.isEmpty())
	{
		lib3ds_mesh_new_texel_list(p3dsMesh, pointsCount);
		for (uint i= 0; i < pointsCount; ++i)
		{
			p3dsMesh->texelL[i][0]= texelVector[i * 2];
			p3dsMesh->texelL[i][1]= texelVector[i * 2 + 1];
		}
	}

	// Add faces to the 3ds mesh
	const uint totalFaceCount= pMesh->faceCount(0);
	lib3ds_mesh_new_face_list(p3dsMesh, totalFaceCount);

	QSet<GLC_Material*> materialSet= pMesh->materialSet();
	QSet<GLC_Material*>::iterator iMat= materialSet.begin();
	uint currentFaceIndex= 0;
	while(iMat != materialSet.end())
	{
		GLC_Material* pCurrentGLCMat= *iMat;
		Lib3dsMaterial* pMaterial= get3dsMaterialFromGLC_Material(pCurrentGLCMat);
		IndexList currentTriangleIndex= pMesh->getEquivalentTrianglesStripsFansIndex(0, pCurrentGLCMat->id());
		const int faceCount= currentTriangleIndex.count() / 3;
		for (int i= 0; i < faceCount; ++i)
		{
			Lib3dsFace face;
			strcpy(face.material, pMaterial->name);

			face.points[0]= currentTriangleIndex.at(i * 3);
			face.points[1]= currentTriangleIndex.at(i * 3 + 1);
			face.points[2]= currentTriangleIndex.at(i * 3 + 2);

			p3dsMesh->faceL[currentFaceIndex++]= face;
			Q_ASSERT(currentFaceIndex <= totalFaceCount);
		}
		++iMat;
	}

	return p3dsMesh;
}
Exemplo n.º 3
0
static void dump_to_3ds(Lib3dsFile *f, FILE *fp)
{
	Lib3dsMesh	*m = lib3ds_mesh_new("Warzone Mesh");
	Lib3dsMaterial	*material = lib3ds_material_new("Warzone texture");
	Lib3dsTextureMap *texture = &material->texture1_map;
	int i, num, x, y, levels;
	char s[200];

	num = fscanf(fp, "PIE %d\n", &i);
	if (num != 1)
	{
		fprintf(stderr, "Bad PIE file %s\n", input);
		exit(1);
	}
	fprintf(stdout, "PIE version %d\n", i);

	num = fscanf(fp, "TYPE %d\n", &i); // ignore
	if (num != 1)
	{
		fprintf(stderr, "Bad TYPE directive in %s\n", input);
		exit(1);
	}

	num = fscanf(fp, "TEXTURE %d %s %d %d\n", &i, s, &x, &y);
	if (num != 4)
	{
		fprintf(stderr, "Bad TEXTURE directive in %s\n", input);
		exit(1);
	}
	strcpy(texture->name, s);

	num = fscanf(fp, "LEVELS %d\n", &levels);
	if (num != 1)
	{
		fprintf(stderr, "Bad LEVELS directive in %s\n", input);
		exit(1);
	}

	f->frames = levels;
	f->meshes = m;
	f->materials = material;
	for (i = 0; i < levels; i++)
	{
		int j, points, faces, faces3DS, faceCount, points3DS, pointCount;
		WZ_FACE *faceList;
		WZ_POSITION *posList;

		num = fscanf(fp, "LEVEL %d\n", &x);
		if (num != 1 || (i + 1) != x)
		{
			fprintf(stderr, "Bad LEVEL directive in %s, was %d should be %d\n", input, x, i + 1);
			exit(1);
		}

		num = fscanf(fp, "POINTS %d\n", &points);
		if (num != 1)
		{
			fprintf(stderr, "Bad POINTS directive in %s frame %d\n", input, i);
			exit(1);
		}
		posList = malloc(sizeof(WZ_POSITION) * points);
		for (j = 0; j < points; j++)
		{
			if (swapYZ)
			{
				num = fscanf(fp, "%d %d %d\n", &posList[j].x, &posList[j].z, &posList[j].y);
			}
			else
			{
				num = fscanf(fp, "%d %d %d\n", &posList[j].x, &posList[j].y, &posList[j].z);
			}
			if (num != 3)
			{
				fprintf(stderr, "Bad POINTS entry frame %d, number %d\n", i, j);
				exit(1);
			}
		}

		num = fscanf(fp, "POLYGONS %d", &faces);
		if (num != 1)
		{
			fprintf(stderr, "Bad POLYGONS directive in %s frame %d\n", input, i);
			exit(1);			
		}
		faces3DS = faces;	// for starters
		faceList = malloc(sizeof(WZ_FACE) * faces);
		points3DS = 0;
		for (j = 0; j < faces; ++j)
		{
			int k;
			unsigned int flags;

			num = fscanf(fp, "\n%x", &flags);
			if (num != 1)
			{
				fprintf(stderr, "Bad POLYGONS texture flag entry frame %d, number %d\n", i, j);
				exit(1);
			}
			if (!(flags & iV_IMD_TEX))
			{
				fprintf(stderr, "Bad texture flag entry frame %d, number %d - no texture flag!\n", i, j);
				exit(1);
			}

			num = fscanf(fp, "%d", &faceList[j].vertices);
			if (num != 1)
			{
				fprintf(stderr, "Bad POLYGONS vertices entry frame %d, number %d\n", i, j);
				exit(1);
			}
			assert(faceList[j].vertices <= MAX_POLYGON_SIZE); // larger polygons not supported
			assert(faceList[j].vertices >= 3); // points and lines not supported
			if (faceList[j].vertices > 3)
			{
				// since they are triangle fans already, we get to do easy tessellation
				faces3DS += (faceList[j].vertices - 3);
			}
			points3DS += faceList[j].vertices;

			// Read in vertex indices and texture coordinates
			for (k = 0; k < faceList[j].vertices; k++)
			{
				num = fscanf(fp, "%d", &faceList[j].index[k]);
				if (num != 1)
				{
					fprintf(stderr, "Bad vertex position entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
			if (flags & iV_IMD_TEXANIM)
			{
				// read in and discard animation values for now
				int frames, rate, width, height;

				num = fscanf(fp, "%d %d %d %d", &frames, &rate, &width, &height);
				if (num != 4)
				{
					fprintf(stderr, "Bad texture animation entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
			for (k = 0; k < faceList[j].vertices; k++)
			{
				num = fscanf(fp, "%d %d", &faceList[j].texCoord[k][0], &faceList[j].texCoord[k][1]);
				if (num != 2)
				{
					fprintf(stderr, "Bad texture coordinate entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
		}

		// Calculate position list. Since positions hold texture coordinates in 3DS, unlike in Warzone,
		// we need to use some black magic to transfer them over here.
		lib3ds_mesh_new_point_list(m, points3DS);
		lib3ds_mesh_new_texel_list(m, points3DS);
		pointCount = 0;
		for (j = 0; j < faces; j++)
		{
			int k;

			for (k = 0; k < faceList[j].vertices; k++)
			{
				Lib3dsVector pos;

				pos[0] = posList[faceList[j].index[k]].x;
				pos[1] = posList[faceList[j].index[k]].y;
				pos[2] = posList[faceList[j].index[k]].z;

				lib3ds_vector_copy(m->pointL[pointCount].pos, pos);
				faceList[j].index[k] = pointCount; // use new position list

				if (invertUV)
				{
					m->texelL[pointCount][0] = ((float)faceList[j].texCoord[k][0] / 256.0f);
					m->texelL[pointCount][1] = 1.0f - ((float)faceList[j].texCoord[k][1] / 256.0f);
				}
				else
				{
					m->texelL[pointCount][0] = ((float)faceList[j].texCoord[k][0] / 256.0f);
					m->texelL[pointCount][1] = ((float)faceList[j].texCoord[k][1] / 256.0f);
				}
				pointCount++;
			}
		}

		lib3ds_mesh_new_face_list(m, faces3DS);
		faceCount = 0;

		// TODO reverse winding afterwards
		for (j = 0; j < faces; j++)
		{
			int k, key, previous;

			key = m->faceL[faceCount].points[0] = faceList[j].index[0];
			m->faceL[faceCount].points[1] = faceList[j].index[1];
			previous = m->faceL[faceCount].points[2] = faceList[j].index[2];
			faceCount++;

			// Generate triangles from the Warzone triangle fans (PIEs, get it?)
			for (k = 3; k < faceList[j].vertices; k++)
			{
				m->faceL[faceCount].points[0] = key;
				m->faceL[faceCount].points[1] = previous;
				previous = m->faceL[faceCount].points[0] = faceList[j].index[k];
			}

			// Since texture coordinates are properties of positions, not indices,
			// we do not need a similar expansion of these
		}
		free(faceList);
		free(posList);
	}
	if (!lib3ds_file_save(f, output))
	{
		fprintf(stderr, "Cannot open \"%s\" for writing: %s", output, strerror(errno));
		exit(1);
	}
}