Exemplo n.º 1
0
int main(int argc, char*argv[]){
	// GalPot Pot("../../Torus/pot/PJM11.Tpot");
	Logarithmic Pot(220.,1.,0.9);

	if(argc<8){
		std::cerr<<"Need to pass phase-space point and filename\n";
		return 0;
	}
	VecDoub X(6,0.);
	for(unsigned i=0;i<6;++i)
		X[i]=atof(argv[i+1]);
	Orbit O(&Pot);
	// Fudge
	Actions_AxisymmetricStackel_Fudge AA(&Pot,-30.);

	// Iterative Torus
	// IterativeTorusMachine Tor(&AA,&Pot,1e-8,5,1e-3);

	// Generating Function
	Actions_Genfunc AG(&Pot,"axisymmetric");

	// Average generating Function
	Actions_Genfunc_Average AGav(&Pot,"axisymmetric");

	// uvorb
	uv_orb UV(&Pot,1.,20.,10,10,"example.delta_uv");

	// Polar Adiabatic
	Actions_PolarAdiabaticApproximation PAA(&Pot,"example.paa",true,false);

	// Spheroidal Adiabatic
	Actions_SpheroidalAdiabaticApproximation SAA(&Pot,"example.saa",true,false,-30.);

	// Spheroidal Adiabatic
	Actions_StackelFit SF(&Pot);

	double tt = 10.;
	if(argc>8) tt=atof(argv[8]);
	O.integrate(X,tt*Pot.torb(X),0.01*Pot.torb(X));
	// O.plot(0,2);

	std::ofstream outfile;
	outfile.open(argv[7]);
	outfile<<"# Fudge Genfunc GenfuncAv uvOrb PAA SAA FIT\n";

	int guess_alpha=1;
	VecDoub Fudge, ITorus, Genfunc, GenfuncAv, uvAct, paaAct, saaAct, fitAct;
	for(auto i:O.results()){
		Fudge = AA.actions(i,&guess_alpha);
		// ITorus = Tor.actions(i);
		Genfunc = AG.actions(i);
		GenfuncAv = AGav.actions(i);
		uvAct = UV.actions(i);
		paaAct = PAA.actions(i);
		saaAct = SAA.actions(i,&guess_alpha);
		fitAct = SF.actions(i);
		outfile
				<<Fudge[0]<<" "<<Fudge[2]<<" "
				// <<ITorus[0]<<" "<<ITorus[2]<<" "
				<<Genfunc[0]<<" "<<Genfunc[2]<<" "
				<<GenfuncAv[0]<<" "<<GenfuncAv[2]<<" "
				<<uvAct[0]<<" "<<uvAct[2]<<" "
				<<paaAct[0]<<" "<<paaAct[2]<<" "
				<<saaAct[0]<<" "<<saaAct[2]<<" "
				<<fitAct[0]<<" "<<fitAct[2]<<" ";
		for(auto j:i) outfile<<j<<" ";
		outfile <<std::endl;
	}
	outfile.close();
}
Exemplo n.º 2
0
void PtrFreeScene :: translate_geometry_qbvh(const lux_ext_mesh_list_t& meshs) {
  lux_defined_meshs_t defined_meshs(PtrFreeScene::mesh_ptr_compare);

  Mesh new_mesh;
  Mesh current_mesh;

  std::vector<Point>    tmp_vertexes;
  std::vector<Normal>   tmp_normals;
  std::vector<Spectrum> tmp_colors;
  std::vector<UV>       tmp_uvs;
  std::vector<Triangle> tmp_triangles;
  std::vector<Mesh>     tmp_mesh_descs;

  for(lux_ext_mesh_list_t::const_iterator it = meshs.begin(); it != meshs.end(); ++it) {
    const luxrays::ExtMesh* mesh = *it;
    bool is_existing_instance;
    if (mesh->GetType() == luxrays::TYPE_EXT_TRIANGLE_INSTANCE) {
      const luxrays::ExtInstanceTriangleMesh* imesh = static_cast<const luxrays::ExtInstanceTriangleMesh*>(mesh);

      // check if is one of the already done meshes
      lux_defined_meshs_t::iterator it = defined_meshs.find(imesh->GetExtTriangleMesh());
      if (it == defined_meshs.end()) {
        // it is a new one
        current_mesh = new_mesh;

        new_mesh.verts_offset += imesh->GetTotalVertexCount();
        new_mesh.tris_offset  += imesh->GetTotalTriangleCount();
        is_existing_instance = false;
        const uint index = tmp_mesh_descs.size();
        defined_meshs[imesh->GetExtTriangleMesh()] = index;
      } else {
        // it is not a new one
        current_mesh = tmp_mesh_descs[it->second];
        is_existing_instance = true;
      }

      current_mesh.trans = imesh->GetTransformation().GetMatrix().m;
      current_mesh.inv_trans = imesh->GetInvTransformation().GetMatrix().m;

      mesh = imesh->GetExtTriangleMesh();
    } else {
      // not a luxrays::TYPE_EXT_TRIANGLE_INSTANCE
      current_mesh = new_mesh;
      new_mesh.verts_offset += mesh->GetTotalVertexCount();
      new_mesh.tris_offset  += mesh->GetTotalTriangleCount();

      if (mesh->HasColors()) {
        new_mesh.colors_offset += mesh->GetTotalVertexCount();
        current_mesh.has_colors = true;
      } else {
        current_mesh.has_colors = false;
      }
      is_existing_instance = false;
    }

    tmp_mesh_descs.push_back(current_mesh);

    if (!is_existing_instance) {

      assert(mesh->GetType() == luxrays::TYPE_EXT_TRIANGLE);

      // translate mesh normals and colors

      uint offset = tmp_normals.size();
      tmp_normals.resize(offset + mesh->GetTotalVertexCount());
      for(uint j = 0; j < mesh->GetTotalVertexCount(); ++j)
        tmp_normals[offset + j] = Normal(mesh->GetNormal(j));

      if (mesh->HasColors()) {
        offset = tmp_colors.size();
        tmp_colors.resize(offset + mesh->GetTotalVertexCount());
        for(uint j = 0; j < mesh->GetTotalVertexCount(); ++j)
          tmp_colors[offset + j] = Spectrum(mesh->GetColor(j));
      }

      // translate vertex uvs

      if (original_scene->texMapCache->GetSize()) {
        // TODO: should check if the only texture map is used for infintelight
        offset = tmp_uvs.size();
        tmp_uvs.resize(offset + mesh->GetTotalVertexCount());
        if (mesh->HasUVs())
          for(uint j = 0; j < mesh->GetTotalVertexCount(); ++j)
            tmp_uvs[offset + j] = UV(mesh->GetUV(j));
        else
          for(uint j = 0; j < mesh->GetTotalVertexCount(); ++j)
            tmp_uvs[offset + j] = UV(0.f, 0.f);
      }

      // translate meshrverticener size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.s
      offset = tmp_vertexes.size();
      tmp_vertexes.resize(offset + mesh->GetTotalVertexCount());
      for(uint j = 0; j < mesh->GetTotalVertexCount(); ++j)
        tmp_vertexes[offset + j] = Point(mesh->GetVertex(j));

      // translate mesh indices
      offset = tmp_triangles.size();
      const luxrays::Triangle *mtris = mesh->GetTriangles();
      tmp_triangles.resize(offset + mesh->GetTotalTriangleCount());
      for(uint j = 0; j < mesh->GetTotalTriangleCount(); ++j)
        tmp_triangles[offset + j] = Triangle(mtris[j]);
    }
  }

  this->vertex_count     = tmp_vertexes.size();
  this->normals_count     = tmp_normals.size();
  this->colors_count     = tmp_colors.size();
  this->uvs_count        = tmp_uvs.size();
  this->triangles_count  = tmp_triangles.size();
  this->mesh_descs_count = tmp_mesh_descs.size();

  reset_array(this->vertexes,   this->vertex_count);
  reset_array(this->normals,    this->normals_count);
  reset_array(this->colors,     this->colors_count);
  reset_array(this->uvs,        this->uvs_count);
  reset_array(this->triangles,  this->triangles_count);
  reset_array(this->mesh_descs, this->mesh_descs_count);

  memcpy(vertexes,   &tmp_vertexes[0],   sizeof(Point)    * this->vertex_count);
  memcpy(normals,    &tmp_normals[0],    sizeof(Normal)   * this->normals_count);
  memcpy(colors,     &tmp_colors[0],     sizeof(Spectrum) * this->colors_count);
  memcpy(uvs,        &tmp_uvs[0],        sizeof(UV)       * this->uvs_count);
  memcpy(triangles,  &tmp_triangles[0],  sizeof(Triangle) * this->triangles_count);
  memcpy(mesh_descs, &tmp_mesh_descs[0], sizeof(Mesh)     * this->mesh_descs_count);
}
Exemplo n.º 3
0
 * be used as a texture again. Use the second set of vertices to draw a quad to
 * the right of the first. Do this all in one command buffer.  The image should
 * be a LunarG logo quad on the left and a green quad on the right.
 */

#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include <cube_data.h>

// Using OpenGL based glm, so Y is upside down between OpenGL and Vulkan

static const VertexUV vb_Data[] = {
    // Textured quad:
    {XYZ1(-2, -0.5, -1), UV(0.f, 0.f)},  // lft-top        / Z
    {XYZ1(-1, -0.5, -1), UV(1.f, 0.f)},  // rgt-top       /
    {XYZ1(-2, 0.5, -1), UV(0.f, 1.f)},   // lft-btm      +------> X
    {XYZ1(-2, 0.5, -1), UV(0.f, 1.f)},   // lft-btm      |
    {XYZ1(-1, -0.5, -1), UV(1.f, 0.f)},  // rgt-top      |
    {XYZ1(-1, 0.5, -1), UV(1.f, 1.f)},   // rgt-btm      v Y
    // Green quad:
    {XYZ1(1, -0.5, -1), UV(0.f, 0.f)},  // lft-top
    {XYZ1(2, -0.5, -1), UV(1.f, 0.f)},  // rgt-top
    {XYZ1(1, 0.5, -1), UV(0.f, 1.f)},   // lft-btm
    {XYZ1(1, 0.5, -1), UV(0.f, 1.f)},   // lft-btm
    {XYZ1(2, -0.5, -1), UV(1.f, 0.f)},  // rgt-top
    {XYZ1(2, 0.5, -1), UV(1.f, 1.f)},   // rgt-btm
};

#define DEPTH_PRESENT false
real_t MLTPerturbationPathMutation::mutate(const Path &X, Path &Y) {
   const unsigned n = X.length();
   PERTURBATION_TYPE type;
   Path lens(m_renderer);
   Y = X;
   
   { // delete current lens subpath
      Y.pop_back();              // pop previous sensor vertex
      
      if (!Y.back().bsdf->isSpecular() && Y.length() >= 2 && 
          Y[Y.length() - 2].bsdf->isSpecular())
      {                          // path has suffix SDE
         type = PERTURBATION_TYPE_CAUSTIC;
         
         Y.pop_back();           // pop diffuse vertex
         while(Y.back().bsdf->isSpecular()) {
            Y.pop_back();        // pop zero or more specular vertices
            
            if (Y.empty())
               return 0;         // mutation failed
         }
      } else {
         type = PERTURBATION_TYPE_LENS;
         
         while(Y.back().bsdf->isSpecular()) {
            Y.pop_back();        // pop zero or more specular vertices
            
            if (Y.empty())
               return 0;         // mutation failed
         }
         
         Y.pop_back();           // pop diffuse vertex
         
         while(Y.length() >= 2 && Y.back().bsdf->isSpecular()) {
            // path has suffix SDS*E and is a multi-chain candidate
            type = PERTURBATION_TYPE_MULTI_CHAIN;
            
            do {                 // remove one or more specular vertices
               Y.pop_back();
               
               if (Y.empty())
                  return 0;      // mutation failed
            } while(Y.back().bsdf->isSpecular());
            
            Y.pop_back();        // pop diffuse vertex
         }
         
         if (type == PERTURBATION_TYPE_LENS && !Y.empty() && 
             Y.back().bsdf->isSpecular())
         {
            return 0;            // mutation failed
         }
      }
   }
   
   const unsigned s = Y.length();
   
   if (type == PERTURBATION_TYPE_LENS || 
       type == PERTURBATION_TYPE_MULTI_CHAIN)
   {
      { // determine new point on image plane
         const Viewport &viewport = m_renderer->getOutput()->getViewport();
         const real_t pA = viewport.getInvWidth() * viewport.getInvHeight();
         Point2 filmPt(X.back().pt->uv.u, X.back().pt->uv.v);
         
         /*const real_t theta = Random::sample(0, 2 * M_PI);
         const real_t r     = m_r2 * exp(-log(m_r2 / m_r1) * Random::sample(0, 1));
         
         filmPt[0] += r * cos(theta);
         filmPt[1] += r * sin(theta);*/
         
         filmPt[0] += Random::sample(-5, 5) * viewport.getInvWidth ();
         filmPt[1] += Random::sample(-5, 5) * viewport.getInvHeight();
         
         filmPt[0]  = CLAMP(filmPt[0], 0, 1);
         filmPt[1]  = CLAMP(filmPt[1], 0, 1);
         
         SurfacePoint *pt = new SurfacePoint();
         m_renderer->getCamera()->getPoint(*pt, UV(filmPt));
         if (!lens.prepend(PathVertex(pt, 1, pA)))
            return 0;            // mutation failed
      }
      
      // prepend vertices until we reach a non-specular vertex
      do {
         if (!lens.prepend(false, false))
            return 0;            // mutation failed
         
         if (lens.length() > n)
            return 0;            // mutation failed
         
         if (lens.front().pt->shape->getMaterial() != 
             X[n - lens.length()].pt->shape->getMaterial())
         {
            return 0;            // mutation failed
         }
         
         lens.front().bsdf->setWi(lens.front().wi);
         lens.front().event = 
            lens.front().bsdf->sample(X[n - lens.length()].event);
      } while(lens.front().bsdf->isSpecular());
      
      if (type == PERTURBATION_TYPE_MULTI_CHAIN) {
         do {                    // add one or more DS+ chains
            const unsigned t = n - lens.length();
            if (t == 0 || Y.length() + lens.length() >= n)
               break;
            
//#warning ""
//#warning ""
// WARNING:  "trying multi-chain not perturbing interior vertices"  (current; commented out for windows)
//#warning ""
//#warning ""
            
            Vector3 wo = (X[t - 1].pt->position - X[t].pt->position).getNormalized();
            _perturbVector(wo);
            
            PathVertex &v = lens.front();
            v.event = Event(wo, v.event);
            
            do {                 // add DS+
               if (!lens.prepend(false, false))
                  return 0;     // mutation failed
               
               if (lens.length() > n)
                  return 0;      // mutation failed
               
               if (lens.front().pt->shape->getMaterial() != 
                   X[n - lens.length()].pt->shape->getMaterial())
               {
                  return 0;     // mutation failed
               }
               
               lens.front().bsdf->setWi(lens.front().wi);
               lens.front().event = 
                  lens.front().bsdf->sample(X[n - lens.length()].event);
            } while(lens.front().bsdf->isSpecular());
         } while(lens.length() + Y.length() < n);
      }
   } else {
      ASSERT(type == PERTURBATION_TYPE_CAUSTIC);
      ASSERT(X[s - 1].pt->position == Y.back().pt->position);
      ASSERT(X[s].bsdf->isSpecular());
      ASSERT(!Y.back().bsdf->isSpecular());
      
      /*real_t t = (X[n - 1].pt->position - X[n - 2].pt->position).getNormalized();
      for(unsigned i = s; i < n - 1; ++i)
      t /= (X[i].pt->position - X[i - 1].pt->position).getNormalized();*/
      
      Vector3 wo = (X[s].pt->position - X[s - 1].pt->position).getNormalized();
      _perturbVector(wo);
      
      PathVertex &v = Y.back();
      v.event = Event(wo, v.event);
      
      do {
         if (!Y.append(false, false))
            return 0;            // mutation failed
         
         if (Y.back().pt->shape->getMaterial() != X[Y.length() - 1].pt->shape->getMaterial())
            return 0;            // mutation failed
         
         if (Y.length() >= n - 1)
            break;
         
         Y.back().bsdf->setWi(Y.back().wi);
         Y.back().event = Y.back().bsdf->sample(X[Y.length() - 1].event);
      } while(1);
      
      { // determine new point on image plane
         const Viewport &viewport = m_renderer->getOutput()->getViewport();
         const real_t pA = viewport.getInvWidth() * viewport.getInvHeight();
         Point2 filmPt = m_renderer->getCamera()->getProjection(Y.back().pt->position);
         
         filmPt[0] = CLAMP(filmPt[0], 0, 1);
         filmPt[1] = CLAMP(filmPt[1], 0, 1);
         
         Point2 orig(X.back().pt->uv.u, X.back().pt->uv.v);
         //cerr << filmPt << " vs " << orig << endl;
         
         SurfacePoint *pt = new SurfacePoint();
         m_renderer->getCamera()->getPoint(*pt, UV(filmPt));
         if (!lens.prepend(PathVertex(pt, 1, pA)))
            return 0;            // mutation failed
      }
   }
   
   { // attempt to join old subpath with new lens subpath
      if (!Y.append(lens))
         return 0;               // mutation failed
      
      if (!Y.front().isEmitter() || !Y.back().isSensor())
         return 0;               // mutation failed
   }
   
   real_t Txy = 1, Tyx = 1;
   
   switch(type) {
      case PERTURBATION_TYPE_CAUSTIC:
         Txy = Y[Y.length() - 1].pL;
         Tyx = X[X.length() - 1].pL;
         break;
      case PERTURBATION_TYPE_LENS:
      case PERTURBATION_TYPE_MULTI_CHAIN:
      default:
         Txy = Y[s].pE;
         Tyx = X[s].pE;
         break;
   }
   
   const real_t Fx    = X.getRadiance().getRGB().luminance();
   const real_t den   = Txy * Fx;
   
   if (den == 0)
      return 0;                  // mutation failed
   
// TODO:  #warning "TESTING"
   const real_t a = ((Y.getRadiance()/X.getRadiance()).getRGB()).luminance() * (Tyx/Txy);
   return MIN(1.0, a);
   
   const real_t Fy    = Y.getRadiance().getRGB().luminance();
   const real_t alpha = MIN(1.0, (Fy * Tyx) / den);
   
   /*if (type == PERTURBATION_TYPE_MULTI_CHAIN)
      cerr << "multi-chain " << "alpha: " << alpha << endl;
   else if (type == PERTURBATION_TYPE_LENS)
      cerr << "lens        " << "alpha: " << alpha << endl;
   else 
      cerr << "caustic     " << "alpha: " << alpha << endl;*/
   
   return alpha;
}
Exemplo n.º 5
0
CylinderMesh::CylinderMesh(float radius, float height, int stacks, int slices) : Mesh(GL_TRIANGLE_STRIP, true)
{
    // bottom disc
    m_faces.push_back(Face(UV(0.5f, 0.5f), -Vector::X, Vector::Zero));
    
    for (int sliceNumber = slices; sliceNumber >= 0; --sliceNumber)
    {
        float phi = sliceNumber * 2 * M_PI / slices + M_PI_2;
        float sinPhi = std::sin(phi);
        float cosPhi = std::cos(phi);

        m_faces.push_back(Face(UV(cosPhi, sinPhi),
                               -Vector::X,
                               Vector(0.0f, radius * cosPhi, radius * sinPhi))
                         );
    }

    // cylinder
    for (int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
    {
        for (int sliceNumber = slices; sliceNumber >=0 ; --sliceNumber)
        {
            float phi = sliceNumber * 2 * M_PI / slices + M_PI_2;
            float sinPhi = std::sin(phi);
            float cosPhi = std::cos(phi);

            float s = static_cast<float>(sliceNumber)/static_cast<float>(slices);
            float t = 1.0f-static_cast<float>(stackNumber)/static_cast<float>(stacks);

            m_faces.push_back(Face(UV(s, t),
                                   Vector(0.0f, cosPhi, sinPhi),
                                   Vector(height * stackNumber / stacks, radius * cosPhi, radius * sinPhi))
                             );
        }
    }

    // upper disc
    for (int sliceNumber = slices; sliceNumber >= 0; --sliceNumber)
    {
        float phi = sliceNumber * 2 * M_PI / slices + M_PI_2;
        float sinPhi = std::sin(phi);
        float cosPhi = std::cos(phi);

        m_faces.push_back(Face(UV(cosPhi, sinPhi),
                               Vector::X,
                               Vector(height, radius * cosPhi, radius * sinPhi))
                         );
    }
    m_faces.push_back(Face(UV(0.5f, 0.5f), Vector::X, Vector(height, 0.0f, 0.0f)));


    // bottom disc
    for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
    {
        m_indices.push_back( 0 );
        m_indices.push_back( 1 + sliceNumber );
    }

    // cylinder
    for (int stackNumber = 0; stackNumber < stacks; ++stackNumber)
    {
        for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
        {
            m_indices.push_back( (1+slices+1) + stackNumber*(slices+1) + sliceNumber);
            m_indices.push_back( (1+slices+1) + (stackNumber+1)*(slices+1) + sliceNumber);
        }
    }

    // upper disc
    for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
    {
        m_indices.push_back( (1+slices+1) + (stacks+1)*(slices+1) + sliceNumber );
        m_indices.push_back( (1+slices+1) + (stacks+1)*(slices+1) + (slices+1) );
    }

    init();
}
Exemplo n.º 6
0
IMPEXP void loadLWO(Object &obj, const string &fn, MapString *mapStr, map<Material *,UVMapper *> *mappers_out)
{
	unsigned int i;
	IFFReader lwo_data;
	vector<string> clips;
	map<string, Material *, string_less> surftags;
	map<string, map<int, map<int, map<int, UV, int_less>, int_less>, int_less >, string_less> vmad_ref;	
	vector<string> taglist;

	vector<UVMapper *> mappers;
	vector<unsigned short> mapper_layer;
	vector<Material *> mapper_mat;
	
	int slashPos = fn.find_last_of('/');

	string baseDir = fn.substr(0,slashPos+1);
	string lwoFn = fn.substr(slashPos+1,fn.length()-(slashPos+1));
	
	Logger::log("Loading Object: %s\n",fn.c_str());
	
//	if (mapStr)
//	{
//		//fn = 
//		mapStr->getString(fn.c_str());
//	}
	
	FILE *file;
	
	file = fopen(fn.c_str(), "rb");

	if(!file) 
	{
		Logger::log("file not found: %s\n",fn.c_str());	
		return;
	}
	
	fclose(file);
	
	lwo_data.load(fn);

	unsigned int totalPoints = 0;
	unsigned int pointSetCount = 0;
	
	vector<unsigned int> pointSetOfs;
	
	IFFBlock *pointData;
	
	/* Points */
	while ((pointData = lwo_data.getBlock("PNTS",pointSetCount++)))
	{
		unsigned int numPoints = pointData->size/12;
		
		for (unsigned int t = 0; t < numPoints; t++)
		{
			float x,y,z;

			/* x-axis is reversed in lw? */		
			x = -pointData->getFloat();
			y = pointData->getFloat();
			z = pointData->getFloat();
			
			obj.addPoint(totalPoints+t,XYZ(x,y,z));
		}

		pointSetOfs.push_back(totalPoints);
		totalPoints += numPoints;
	}

	std::vector<string> blockList;
	lwo_data.getBlockNames(blockList);
	
	int vmadLayer = -1;
	std::vector<int> vmadIndex;
	std::map<string,vector<int> > vmadNamedIndex;
	
	for (unsigned int i = 0; i < blockList.size(); i++)
	{
		if (blockList[i] == "LAYR")
		{
			vmadLayer++;
		}
		if (blockList[i] == "VMAD")
		{
			printf("VMAD: %d\n",vmadLayer);
			vmadIndex.push_back(vmadLayer);
		}
	}
	
	int polsCount = 0;
	unsigned int faceNum = 0;
	
	vector<unsigned int> faceSetOfs;

	/* Faces */
	IFFBlock *faceData; // = lwo_data.getBlock("POLS");

	while ((faceData = lwo_data.getBlock("POLS",polsCount)))
	{
		char faceHeader[4];
		bool isPatchData=false; 
		faceData->getHeader(faceHeader);

		Logger::log("POLS type:%s\n",faceHeader);
		isPatchData = (strncmp("PTCH",faceHeader, 4) == 0);
		
		if (isPatchData) Logger::log("Loading Faces as Patches..\n");
		
		faceSetOfs.push_back(faceNum);

		obj.setSegment(polsCount);

		while (!faceData->finished())
		{
			unsigned short numPoints;
			vector<unsigned long> face_temp;
			int p;

			numPoints = faceData->getShort();
			obj.addFace(faceNum);
			face_temp.resize(numPoints);

			/* lightwave defines faces clockwise, we need counterclockwise */
			if (numPoints)
			{
				for (p = numPoints-1; p >= 0; p--)
				{
					face_temp[p] = faceData->getVx();
				}
			}
			else
			{
				Logger::log(LOG_WARNING,"Warning face %lu has no points.\n",faceNum);
			}
			
			for (p = 0; p < numPoints; p++)
			{
				obj.addFacePoint(faceNum,pointSetOfs[polsCount]+face_temp[p]);
			}				
			
			if (isPatchData) obj.setPatch(faceNum,true);

			faceNum++;
		}
		

		if (isPatchData) 		Logger::log("Patch Count: [%lu]\n",faceNum);
		else					Logger::log("Face Count: [%lu]\n",faceNum);


		polsCount++;
	}

	/* Discontinuous UV maps */
	/* UV Map */
	IFFBlock *vmadData;
	int vmadCount = 0;
	
	while ((vmadData = lwo_data.getBlock("VMAD",vmadCount)))
	{
		char vmadTag[5];
		string vmadName;
		int dimension;

		std::map<string,int> vmadSubCounter;

		if (vmadData->size)
		{
			vmadData->getHeader(vmadTag);
			vmadTag[4] = 0;

			dimension = vmadData->getShort();
			
			vmadData->getString(vmadName);
			
//			vmad_ref[vmadName].resize(obj.faces.size());
										
			Logger::log("vmad name: %s\n",vmadName.c_str());
			Logger::log("vmad type: %s\n",vmadTag);

			vmadNamedIndex[vmadName].push_back(vmadIndex[vmadCount]);

			unsigned int subCount = vmadNamedIndex[vmadName].size()-1;
			
			if (strncmp(vmadTag,"TXUV",4)==0)
			{
				while (!vmadData->finished())
				{
					unsigned int polyIndex,pointIndex;
					float u, v;

					pointIndex = vmadData->getVx();
					polyIndex = vmadData->getVx();
					
					u = vmadData->getFloat();
					v = vmadData->getFloat();							
												
					vmad_ref[vmadName][subCount][pointIndex][polyIndex] = UV(u,v);
				}
			}
			else
			{
				Logger::log("non TXUV vmad, can't apply..\n");
			}
		}
		
		vmadCount++;
	}



	/* Image Clips */
	IFFBlock *clipData;
	unsigned int clipNum = 0;

	while ( (clipData = lwo_data.getBlock("CLIP",clipNum++)) )
	{
		IFFReader clipTemp = IFFReader();

		unsigned long clipIndex = clipData->getLong();
		clipTemp.processIFFBlock(clipData->data+4, clipData->size-4,2);

		IFFBlock *stilData = clipTemp.getBlock("STIL");
		if (stilData)
		{
			string strRef;

			if (!(clips.size() > clipIndex)) clips.resize(clipIndex+1);

			strRef = string(stilData->data);

			clips[clipIndex] = strRef;
		
			Logger::log("Still Image #%lu : %s\n",clipIndex,strRef.c_str());
		}
	}


	std::vector< std::vector<mapPair> > point_mapref;
	point_mapref.resize(obj.points.size());

	/* build a list of which faces share which points */
	for (i = 0; i < obj.faces.size(); i++)	
	{
		for (unsigned int j = 0; j < obj.faces[i]->points.size(); j++)
		{
			mapPair point_map_temp;
			
			point_map_temp.faceref = i;
			point_map_temp.pointref = j;
			
			point_mapref[obj.faces[i]->pointref[j]].push_back(point_map_temp);
		}
	}


	/* Surfaces (SURF) */
	int surfCount = 0;
	IFFBlock *surfaceData;

	while ((surfaceData = lwo_data.getBlock("SURF",surfCount))) 
	{	
		RGBA color;
		Material *surfMat;
		unsigned short texLayer = 0;
		unsigned short texCount = 0;
		int reflCount = 0;
		int bumpCount = 0;

		IFFReader surfTemp = IFFReader();

		string surfName(surfaceData->data);

		int surfPtr = 0;

		Logger::log("Surface name: %s\n",surfName.c_str());

		surfPtr = surfName.size();

		while (*(surfaceData->data+surfPtr) == 0) surfPtr++;
		
		Logger::log(" size: %lu\n",(surfaceData->size-surfPtr));
		
		surfTemp.processIFFBlock(surfaceData->data+surfPtr, surfaceData->size-surfPtr,2);

		if (!surfTemp.getBlock("COLR"))
		{
			string surfName2 = surfaceData->data+surfPtr;
			
			Logger::log("Surface name2: %s\n",surfName2.c_str());
			
			surfPtr+=surfName2.size();
			while (*(surfaceData->data+surfPtr) == 0) surfPtr++;
			
			surfTemp.processIFFBlock(surfaceData->data+surfPtr, surfaceData->size-surfPtr,2);
		}
		


		
		surfMat = new Material();
		surfMat->setId(surfName);
		surftags[surfName] = surfMat;
		

		float tran = 1.0f;
		IFFBlock *tranData = surfTemp.getBlock("TRAN");
		if (tranData)
		{
			tran = 1.0f-tranData->getFloat();
		}


		IFFBlock *colorData = surfTemp.getBlock("COLR");
		if (colorData)
		{
			color.r = colorData->getFloat();
			color.g = colorData->getFloat();
			color.b = colorData->getFloat();
			color.a = tran;

			Logger::log("Surface %s color: %f, %f, %f\n",surfName.c_str(),color.r,color.g,color.b);
			surfMat->setColor(color);			
		}

		float diff = 1.0f;
		IFFBlock *diffData = surfTemp.getBlock("DIFF");
		if (diffData)
		{
			diff = diffData->getFloat();
		}
		surfMat->setDiffuse(RGBA(diff,diff,diff,1.0f)); 

		Logger::log("diff: %f\n",diff);

		float lumi = 0.0f;
		IFFBlock *lumiData = surfTemp.getBlock("LUMI");
		if (lumiData)
		{
			lumi = lumiData->getFloat(); 
			
			Logger::log(", lumi amount: %f ",lumi);
		}
		surfMat->setAmbient(RGBA(color.r*lumi,color.g*lumi,color.b*lumi,1.0f));
		

		float spec = 0.0f;
		IFFBlock *specData = surfTemp.getBlock("SPEC");
		if (specData)
		{
			spec = specData->getFloat(); 

			Logger::log(", specular: %f ",spec);
		}
		surfMat->setSpecular(RGBA(spec,spec,spec,1.0f));
		
		float glos = 0.40f;
		IFFBlock *glosData = surfTemp.getBlock("GLOS");
		if (glosData)
		{
			glos = glosData->getFloat();

			Logger::log(", shininess: %f",glos);
		}
		surfMat->setShininess(128.0f*glos);


		float max_smooth = 0.0f;
		IFFBlock *smoothData = surfTemp.getBlock("SMAN");
		if (smoothData)
		{
			max_smooth = smoothData->getFloat();

			Logger::log(", smoothing: %f",max_smooth*180.0f/M_PI);
		}
		surfMat->setMaxSmooth(max_smooth*180.0f/M_PI);


		float refl = 0.0f;
		IFFBlock *reflData = surfTemp.getBlock("REFL");
		if (reflData)
		{
			refl = reflData->getFloat();

			Logger::log(", reflection: %f\n",refl);
			
			surfMat->setReflective(refl);
		}
//		surfMat->env_opacity(refl);

		unsigned short sidedness = 1;
		IFFBlock *sideData = surfTemp.getBlock("SIDE");
		if (sideData)
		{
			sidedness = sideData->getShort();
		}
		surfMat->setSidedness((sidedness==1)?MATERIAL_FACE_FRONT:MATERIAL_FACE_BOTH);

		/* BLOK Sub-chunks */
		int blokCount = 0;

		std::vector<unsigned short> layer_order_ref;

		IFFBlock *surfBlok = surfTemp.getBlock("BLOK");
		while ((surfBlok = surfTemp.getBlock("BLOK",blokCount)))
		{
			IFFReader blokData;
			blokData.processIFFBlock(surfBlok->data, surfBlok->size,2);

			/* IMAP Blok -- we only handle IMAPs (for now) */
			IFFBlock *imap = blokData.getBlock("IMAP");
			char chanHeader[5] = "COLR";

			if (imap)
			{
				string imapStr;
				imap->getString(imapStr); // ordinal string

				IFFReader imapData;
				imapData.processIFFBlock(imap->data_ptr(), imap->remainder(),2);
				IFFBlock *chan = imapData.getBlock("CHAN");

				chan->getHeader(chanHeader);

				if (strncmp(chanHeader,"REFL",4) == 0) layer_order_ref.push_back(CHAN_REFL);
				if (strncmp(chanHeader,"DIFF",4) == 0) layer_order_ref.push_back(CHAN_COLR);
				if (strncmp(chanHeader,"COLR",4) == 0) layer_order_ref.push_back(CHAN_COLR);
				if (strncmp(chanHeader,"BUMP",4) == 0) layer_order_ref.push_back(CHAN_BUMP);
				if (strncmp(chanHeader,"SPEC",4) == 0) layer_order_ref.push_back(CHAN_SPEC);
				if (strncmp(chanHeader,"LUMI",4) == 0) layer_order_ref.push_back(CHAN_LUMI);
				if (strncmp(chanHeader,"TRAN",4) == 0) layer_order_ref.push_back(CHAN_TRAN);
			}
			blokCount++;
		}
		
		// sort order for layers
		std::vector<unsigned short> layer_order_map;
		layer_order_map.push_back(CHAN_COLR);
		layer_order_map.push_back(CHAN_TRAN);
		layer_order_map.push_back(CHAN_REFL);
		layer_order_map.push_back(CHAN_BUMP);
		layer_order_map.push_back(CHAN_SPEC);
		layer_order_map.push_back(CHAN_LUMI);
		layer_order_map.push_back(CHAN_DIFF);
		
		
		// stack the layers based on the sort order
		std::vector<unsigned short> layer_order_sorted;
		
		for (i = 0; i < layer_order_map.size(); i++)
		{
			for (unsigned int j = 0; j < layer_order_ref.size(); j++)
			{
				if (layer_order_map[i] == layer_order_ref[j])
				{
					layer_order_sorted.push_back(j);
				}
			}
		}
		
		// assign the stacked layers their index in the stack
		std::vector<unsigned short> layer_order;
		
		layer_order.resize(layer_order_sorted.size());
		
		for (i = 0; i < layer_order_sorted.size(); i++)
		{
			layer_order[layer_order_sorted[i]] = i;
		}
		

		blokCount = 0;
	
		while ((surfBlok = surfTemp.getBlock("BLOK",blokCount)))
		{
			IFFReader blokData;
			blokData.processIFFBlock(surfBlok->data, surfBlok->size,2);

			unsigned long newTex = 0;

			/* IMAP Blok -- we only handle IMAPs (for now) */
			IFFBlock *imap = blokData.getBlock("IMAP");
			char chanHeader[5] = "COLR";
			int chanType = -1;

			if (imap)
			{
				string imapStr;
				imap->getString(imapStr); // ordinal string

				IFFReader imapData;
				imapData.processIFFBlock(imap->data_ptr(), imap->remainder(),2);
				IFFBlock *chan = imapData.getBlock("CHAN");
				
				chan->getHeader(chanHeader);

				if (strncmp(chanHeader,"REFL",4) == 0) chanType = CHAN_REFL;
				if (strncmp(chanHeader,"COLR",4) == 0) chanType = CHAN_COLR;
				if (strncmp(chanHeader,"BUMP",4) == 0) chanType = CHAN_BUMP;//{ blokCount++; continue; }
				if (strncmp(chanHeader,"SPEC",4) == 0) chanType = CHAN_SPEC;
				if (strncmp(chanHeader,"DIFF",4) == 0) chanType = CHAN_COLR;
				if (strncmp(chanHeader,"TRAN",4) == 0) chanType = CHAN_TRAN;
				if (strncmp(chanHeader,"LUMI",4) == 0) chanType = CHAN_LUMI;

//				if (chanType == -1) break;
				/* Texture IMAG block */
				UVMapper *mapper = new UVMapper();

				IFFBlock *imag = blokData.getBlock("IMAG");
				if (imag)
				{
					int temp;
					long clip_index = IFFBlock::vxbuf2vx(imag->data,temp);

					if (clip_index <= 0) break;
					if (clips[clip_index] == "") break;					
					
					string texFn;
					
					if (mapStr)
					{			
						texFn.append(mapStr->getString(string(strrchr(clips[clip_index].c_str(),'/')+1).c_str()));
					}
					else
					{
						texFn = baseDir;
						
						texFn.append(string(strrchr(clips[clip_index].c_str(),'/')+1).c_str());
					}

					Logger::log("Clip Index: %li : %s\n",clip_index,texFn.c_str());

					newTex = Texture::getTextureId(texFn);					
					
					Logger::log("Loading clip image file..\n");
					if (!newTex) newTex = Texture::create(texFn,texFn);

					Logger::log("Loading surface parameters..\n");

					if (!newTex) Logger::log(LOG_ERROR,"Error loading texture %s\n",texFn.c_str());
					if (!newTex) break;
					
					texLayer = layer_order[texCount];
					surfMat->addLayer(texLayer);

					switch (chanType)
					{
						case CHAN_BUMP:
							if (bumpCount)
							{
								Logger::log("Channel type: BUMP-parallaxHeight\n");
								surfMat->bindTexture(texLayer,newTex,TEXTURE_BUMP);
							}
							else
							{
								Logger::log("Channel type: BUMP-normal\n");
								surfMat->bindTexture(texLayer,newTex,TEXTURE_NORM);
								bumpCount++;
							}
						break;
						case CHAN_SPEC:
							Logger::log("Channel type: SPECULAR\n");
							surfMat->bindTexture(texLayer,newTex,TEXTURE_SPEC);
						break;
						case CHAN_COLR:
							Logger::log("Channel type: COLOR\n");
							surfMat->bindTexture(texLayer,newTex,TEXTURE_DIFF);
						break;
						case CHAN_LUMI:
							Logger::log("Channel type: LUMI\n");
							surfMat->bindTexture(texLayer,newTex,TEXTURE_LUMI);
						break;
						case CHAN_REFL:
							Logger::log("Channel type: REFL\n");

							if (reflCount)
							{
								Logger::log("Channel type: REFL-material\n");

								surfMat->bindTexture(texLayer,newTex,TEXTURE_REFL);
							}
							else
							{
								Logger::log("Channel type: REFL-map\n");

								surfMat->bindTexture(texLayer,newTex,TEXTURE_ENVSPHERE);
							}
							
//							surfMat->layer[texLayer].map_mode = MATERIAL_MAP_SPHERICAL;
//							surfMat->bindTexture(texLayer,newTex,TEXTURE_DIFF);
							reflCount++;
						break;
						case CHAN_TRAN:
//warning undef behavior //
							surfMat->bindTexture(texLayer,newTex,TEXTURE_ALPHA);
							Logger::log("Channel type: TRAN\n");
//warning undef behavior //
							surfMat->layer[texLayer].blend_mode = MATERIAL_BLEND_ALPHA;
						break;
					}
					
	/*				if (chanType == CHAN_BUMP)
					{
					}*/
					
					
					IFFBlock *opac = imapData.getBlock("OPAC");
					if (opac)
					{
						unsigned int blend_mode = opac->getShort();
						Logger::log("Layer %d blending mode: ",texLayer);

						switch (blend_mode)
						{
							case MATERIAL_BLEND_NORMAL:
								Logger::log("Normal\n");
							break;
							case MATERIAL_BLEND_SUBTRACTIVE:
								Logger::log("Subtractive\n");
							break;
							case MATERIAL_BLEND_DIFFERENCE:
								Logger::log("Difference\n");
							break;
							case MATERIAL_BLEND_MULTIPLY:
								Logger::log("Multiply\n");
							break;
							case MATERIAL_BLEND_DIVIDE:
								Logger::log("Divide\n");
							break;
							case MATERIAL_BLEND_ALPHA:
								Logger::log("Alpha\n");
							break;
							case MATERIAL_BLEND_DISPLACE:
								Logger::log("Displacement\n");
							break;
							case MATERIAL_BLEND_ADDITIVE:
								Logger::log("Additive\n");
							break;
						}
						
						if (chanType != CHAN_TRAN) surfMat->layer[texLayer].blend_mode = blend_mode;
					}
					else
					{
						surfMat->layer[texLayer].blend_mode = MATERIAL_BLEND_NORMAL;
					}
					
					
					texCount++;
				}

				
				/* TMAP Sub-Chunk */
				IFFBlock *tmap = blokData.getBlock("TMAP");
				if (tmap && chanType == CHAN_COLR)
				{
					Logger::log("Processing TMAP chunk..\n");
					
					IFFReader tmapData;
					tmapData.processIFFBlock(tmap->data, tmap->size,2);
					
					IFFBlock *cntr, *size, *rota;

					cntr = tmapData.getBlock("CNTR");
					size = tmapData.getBlock("SIZE");
					rota = tmapData.getBlock("ROTA");

					XYZ v_center, v_size, v_rota;

					if (cntr) 
					{
						cntr->getVector(v_center);
						mapper->center = v_center;
					}

					if (size) 
					{
						size->getVector(v_size);
						mapper->scale = v_size;
					}
					
					if (rota) 
					{
						rota->getVector(v_rota);
						mapper->rotation.x = v_rota.y;
						mapper->rotation.y = v_rota.x;
						mapper->rotation.z = v_rota.z;
					}
					
					Logger::log("tmap_cntr: %f, %f, %f\n",v_center.x,v_center.y,v_center.z);
					Logger::log("tmap_size: %f, %f, %f\n",v_size.x,v_size.y,v_size.z);
					Logger::log("tmap_rota: %f, %f, %f\n",v_rota.x,v_rota.y,v_rota.z);

					IFFBlock *oref = tmapData.getBlock("OREF");
					if (oref)
					{
						Logger::log("tmap_oref: %s\n",oref->data);
					}

					unsigned short coord_system = 0;

					IFFBlock *csys = tmapData.getBlock("CSYS");
					if (csys)
					{
						coord_system = csys->getShort();
						Logger::log("tmap_csys: %d\n",coord_system);
					}

					unsigned short falloff_type;
					XYZ v_falloff;

					IFFBlock *fall = tmapData.getBlock("FALL");
					if (fall)
					{
						falloff_type = fall->getShort();
						fall->getVector(v_falloff);

						Logger::log("tmap_fall: %d\n",falloff_type);
						Logger::log("tmap_fall_vector: %f, %f, %f\n",v_falloff.x,v_falloff.y,v_falloff.z);
					}
					else v_falloff = XYZ(0,0,0);
				} 
				/* End TMAP */

				/* PROJ Sub-chunk (projection) */
				unsigned short projection_axis;
				unsigned short projection_mode = 0;
				//unsigned short width_wrap, height_wrap;

				/* Projection axis */
				IFFBlock *axis = blokData.getBlock("AXIS");
				if (axis)
				{
					projection_axis = axis->getShort();
					
					Logger::log("Projection axis: ");
					
					switch (projection_axis)
					{
					case 0: Logger::log("X"); projection_axis = UV_AXIS_X; break; /* X */
					case 1: Logger::log("Y"); projection_axis = UV_AXIS_Y; break; /* Y */
					case 2: Logger::log("Z"); projection_axis = UV_AXIS_Z; break; /* Z */
					}

					mapper->setAxis(projection_axis);
					
					Logger::log("\n");
				}

				/* Wrap Type */
				IFFBlock *wrap = blokData.getBlock("WRAP");
				if (wrap)
				{
					unsigned short width_wrap, height_wrap;
					
					width_wrap = wrap->getShort();
					height_wrap = wrap->getShort();

					Logger::log("wrap_w: ");
					switch(width_wrap)
					{
						case 0: Logger::log("reset"); break;  // Reset 
						case 1: Logger::log("repeat"); break;  // Repeat 
						case 2: Logger::log("mirror"); break;  // Mirror 
						case 3: Logger::log("edge"); break;  // Edge 
					}

					Logger::log(", wrap_h: ");
					switch(height_wrap)
					{
						case 0: Logger::log("reset"); break;  // Reset 
						case 1: Logger::log("repeat"); break;  // Repeat 
						case 2: Logger::log("mirror"); break;  // Mirror 
						case 3: Logger::log("edge"); break;  // Edge 
					}
					Logger::log("\n");
				}

				/* Width and height wrap */
				float width_count = 1.0f, height_count = 1.0f;

				IFFBlock *wrapw = blokData.getBlock("WRPW");
				if (wrapw)
				{
					width_count = wrapw->getFloat();
				}

				IFFBlock *wraph = blokData.getBlock("WRPH");
				if (wraph)
				{
					height_count = wraph->getFloat();
				}
				
				mapper->setWrap(width_count,height_count);

				IFFBlock *proj = blokData.getBlock("PROJ");

				if (proj && chanType == CHAN_COLR)
				{
					unsigned int proj_temp;
					
					proj_temp = proj->getShort();

					Logger::log("Projection mode: ");

					switch (proj_temp)
					{
					case 0:	/* Planar */
						projection_mode = UV_PROJECTION_PLANAR;	
						Logger::log("planar");
						break;
					case 1: /* Cylindrical */
						projection_mode = UV_PROJECTION_CYLINDRICAL;	
						Logger::log("cylindrical");
						break;
					case 2: /* Spherical */
						projection_mode = UV_PROJECTION_SPHERICAL;	
						Logger::log("spherical");
						break;	
					case 3: /* Cubic */
						projection_mode = UV_PROJECTION_CUBIC;	
						Logger::log("cubic");
						break;	
	/*				case 4: // Front Projection
						//if (chanType == CHAN_REFL) projection_mode = TEX_PROJ_ENVFRONT;	
						if (chanType == CHAN_COLR) projection_mode = TEX_PROJ_FRONT;	
						Logger::log("front");
						break;	*/
					case 5: /* UV */
						projection_mode = UV_PROJECTION_UV;	
						Logger::log("uv");
						break;	

					}
					Logger::log("\n");

					mapper->setProjection(projection_mode);
					
#ifdef ARCH_PSP
					if (mappers.size()==0)
#endif	
					mappers.push_back(mapper);

					mapper_layer.push_back(texLayer);
					mapper_mat.push_back(surfMat);
				}
				
				
				int vmapCount = 0;
				
				IFFBlock *vmapData;
				
				while (vmapData = blokData.getBlock("VMAP",vmapCount))
				{
					string vmapName;
					vmapData->getString(vmapName);
					
					Logger::log("VMAP Loading: [%s]\n",vmapName.c_str());

					unsigned int subCount = 0,vLayer,startPt,endPt;

					while (subCount < vmadNamedIndex[vmapName].size())
					{
						vLayer = vmadNamedIndex[vmapName][subCount];
						startPt = pointSetOfs[vLayer];
						endPt = pointSetOfs[vLayer];
					
						
						if (vLayer+1 < pointSetOfs.size())
						{
							endPt = pointSetOfs[vLayer+1];
						}
						else
						{
							endPt = obj.points.size();
						}
						
						Logger::log("VMAP start,end,layer: [%d,%d,%d]\n",startPt,endPt,vLayer);
						
						for (unsigned int j = startPt; j < endPt; j++)
						{		
							unsigned int pointIndex = j-pointSetOfs[vLayer];
							
							for (unsigned int i = 0; i < point_mapref[j].size(); i++)
							{												
								unsigned int facenum,facepoint;
								
								facenum = point_mapref[j][i].faceref;
								facepoint = point_mapref[j][i].pointref;
								
								if (!(obj.faces[facenum]->uv.size()))
								{
									obj.faces[facenum]->uv.resize(1);
									obj.faces[facenum]->uv[0].resize(obj.faces[facenum]->points.size());
								}
								
								if (obj.faces[facenum]->pointref[facepoint] == j)
								{
									if (vmad_ref[vmapName][subCount][pointIndex].find(facenum-faceSetOfs[vLayer]) != vmad_ref[vmapName][subCount][pointIndex].end())
									{
										obj.faces[facenum]->uv[0][facepoint] = vmad_ref[vmapName][subCount][pointIndex][facenum-faceSetOfs[vLayer]];
									}
								}
							}							
								
						}
						subCount++;	
					}
					vmapCount++;
				}
			}
			/* End if IMAP */
			
			/* UV Map */
			int vmapCount = 0;

			IFFBlock *vmapData;
	
			while ((vmapData = lwo_data.getBlock("VMAP",vmapCount)))
			{
				vmapCount++;

				Logger::log("VMAP: [%s]\n",vmapData->data);
			
				char vmapTag[5];
				string vmapName;
				int dimension;

				vmapData->getHeader(vmapTag);
				vmapTag[4] = 0;

				dimension = vmapData->getShort();
				vmapData->getString(vmapName);

				Logger::log("VMAP type: [%s]\n",vmapTag);
				
				
				
				if (strncmp(vmapTag,"TXUV",4)==0)
				{
					Logger::log("VMAP: decoding [%s]\n",vmapData->data);

					while (!vmapData->finished())
					{
						unsigned int pointIndex;
						float u, v;

						pointIndex = vmapData->getVx();
						
						u = vmapData->getFloat();
						v = vmapData->getFloat();

						unsigned int subCount = 0,vLayer,startPt,endPt;
						
						while (subCount < vmadNamedIndex[vmapName].size())
						{
							vLayer = vmadNamedIndex[vmapName][subCount];
							startPt = pointSetOfs[vLayer];
							endPt = pointSetOfs[vLayer];							
							
							for (unsigned int i = 0; i < point_mapref[pointIndex+startPt].size(); i++)
							{												
								unsigned int facenum,facepoint;
								
								facenum = point_mapref[pointIndex+startPt][i].faceref;
								facepoint = point_mapref[pointIndex+startPt][i].pointref;
													
								if (!(obj.faces[point_mapref[pointIndex+startPt][i].faceref]->uv.size()))
								{
									obj.faces[facenum]->uv.resize(1);
									obj.faces[facenum]->uv[0].resize(obj.faces[facenum]->points.size());
								}

								if (obj.faces[facenum]->pointref[facepoint] == pointIndex+startPt)
								{
									if (vmad_ref[vmapName][subCount][pointIndex].find(facenum-faceSetOfs[vLayer]) != vmad_ref[vmapName][subCount][pointIndex].end())
									{
										obj.faces[facenum]->uv[0][facepoint] = vmad_ref[vmapName][subCount][pointIndex][facenum-faceSetOfs[vLayer]];
									}
									else
									{
										obj.faces[facenum]->uv[0][facepoint] = UV(u,v);
									}
								}
							}
							subCount++;
						}
					}
				}
				else
				if (strncmp(vmapTag,"MNVW",4)==0)
				{
					Logger::log("Loading subpatch weights..\n");
					
					while (!vmapData->finished())
					{
						unsigned int pointIndex;
						float w;
						
						pointIndex = vmapData->getVx();						
						w = vmapData->getFloat();
						
						Logger::log("Vertex: %d, Weight: %f\n",pointIndex,w);
						obj.setWeight(pointIndex, w);
					}
					
					
				}
				else
				{
					Logger::log(LOG_ERROR,"non TXUV vmap [%s, %s], can't apply..\n",vmapData->data,vmapTag);
				}
			}
			/* END VMAP */
			
			
			blokCount++;
		}
		/* End BLOK */

		Logger::log("\n");
		surfCount++;
	} 
	/* End Surfaces */


	
	/* Patches (NURBS) */
	IFFBlock *patchData = lwo_data.getBlock("PTCH");
	if (patchData)
	{
		Logger::log("Found Patches\n");
//		while (!tagsData.finished())
//		{
//			string tagn;
//			tagsData->getString(tagn);
//			taglist.push_back(tagn);
//			Logger::log("Tag List [%s:%d]\n",tagn.c_str(),taglist.size());
//		}
	}


	
	

	/* Tags (names) */
	IFFBlock *tagsData = lwo_data.getBlock("TAGS");
	if (tagsData)
	{
		while (!tagsData->finished())
		{
			string tagn;
			tagsData->getString(tagn);
			taglist.push_back(tagn);
			Logger::log("Tag List [%s:%d]\n",tagn.c_str(),taglist.size());
		}
	}


	/* Surface PTAGs */
	int ptagCount = 0;
	int ptagSurfCount = 0;
	
	IFFBlock *ptagData;
			
	while (ptagData = lwo_data.getBlock("PTAG",ptagCount))
	{
		char ptagHeader[4];
		ptagData->getHeader(ptagHeader);

		if (strncmp(ptagHeader,"SURF", 4) == 0)
		{
			while (!ptagData->finished())
			{
				unsigned long polyIndex;
				unsigned short pTag;

				polyIndex = ptagData->getVx();
				pTag = ptagData->getShort();
				
				obj.bindFaceMaterial(polyIndex+faceSetOfs[ptagSurfCount],surftags[taglist[pTag]]);
			}
			ptagSurfCount++;
		}
		else if (strncmp(ptagHeader,"PART", 4) == 0)
		{
			string strVal;
			
			Logger::log(LOG_WARNING,"Part Name: %s\n");
//			while (!ptagData->finished())
//			{
//				unsigned long polyIndex;
//				unsigned short pTag;
//				
//				polyIndex = ptagData->getVx();
//				pTag = ptagData->getShort();
//				
//				obj.bindFaceMaterial(polyIndex+faceSetOfs[ptagSurfCount],surftags[taglist[pTag]]);
//			}
//			ptagSurfCount++;
		}
		else
		{
			Logger::log(LOG_WARNING,"Unhandled PTAG: %s\n",ptagHeader);
		}

		ptagCount++;
	}

	obj.calcNormals();

	for (unsigned int j = 0; j < mappers.size(); j++)
	{
		mappers[j]->apply(obj,mapper_mat[j],mapper_layer[j]);
		if (mappers_out && mapper_layer[j]==0)
		{
			(*mappers_out)[mapper_mat[j]] = mappers[j];
		}
		else
		{
			delete mappers[j];
		}
	}
	
}
Exemplo n.º 7
0
void makeCube(GeometryBatch &b, float w, 
    bool normals, bool uvs, const LColor *color)
{

  b.init(GL_TRIANGLES, "cube");
  b.ps.resize(36);
  b.ns.resize(b.ps.size());
  b.uvs[0].resize(b.ps.size());
  b.ps[0] = LPoint(-w, -w, w);  b.ns[0] = LNormal(0,0,1); b.uvs[0][0] = UV(0,0);
  b.ps[1] = LPoint(w, -w, w);   b.ns[1] = LNormal(0,0,1); b.uvs[0][1] = UV(1,0);
  b.ps[2] = LPoint(-w, w, w);   b.ns[2] = LNormal(0,0,1); b.uvs[0][2] = UV(0,1);
  b.ps[3] = LPoint(-w, w, w);   b.ns[3] = LNormal(0,0,1); b.uvs[0][3] = UV(0,1);
  b.ps[4] = LPoint(w, -w, w);   b.ns[4] = LNormal(0,0,1); b.uvs[0][4] = UV(1,0);
  b.ps[5] = LPoint(w, w, w);    b.ns[5] = LNormal(0,0,1); b.uvs[0][5] = UV(1,1);

  b.ps[6] = LPoint(w, -w, w);   b.ns[6] =  LNormal(1,0,0); b.uvs[0][6] = UV(0,0); 
  b.ps[7] = LPoint(w, -w, -w);  b.ns[7] =  LNormal(1,0,0); b.uvs[0][7] = UV(1,0);
  b.ps[8] = LPoint(w, w, w);    b.ns[8] =  LNormal(1,0,0); b.uvs[0][8] = UV(0,1);
  b.ps[9] = LPoint(w, w, w);    b.ns[9] =  LNormal(1,0,0); b.uvs[0][9] = UV(0,1);
  b.ps[10] = LPoint(w, -w, -w); b.ns[10] = LNormal(1,0,0); b.uvs[0][10] = UV(1,0); 
  b.ps[11] = LPoint(w, w, -w);  b.ns[11] = LNormal(1,0,0); b.uvs[0][11] = UV(1,1);

  b.ps[12] = LPoint(w, -w, -w);  b.ns[12] = LNormal(0,0,-1); b.uvs[0][12] = UV(0,0);
  b.ps[13] = LPoint(-w, -w, -w); b.ns[13] = LNormal(0,0,-1); b.uvs[0][13] = UV(1,0);
  b.ps[14] = LPoint(w, w, -w);   b.ns[14] = LNormal(0,0,-1); b.uvs[0][14] = UV(0,1);
  b.ps[15] = LPoint(w, w, -w);   b.ns[15] = LNormal(0,0,-1); b.uvs[0][15] = UV(0,1);
  b.ps[16] = LPoint(-w, -w, -w); b.ns[16] = LNormal(0,0,-1); b.uvs[0][16] = UV(1,0);
  b.ps[17] = LPoint(-w, w, -w);  b.ns[17] = LNormal(0,0,-1); b.uvs[0][17] = UV(1,1);

  b.ps[18] = LPoint(-w, -w, -w); b.ns[18] = LNormal(0,0,-1); b.uvs[0][18] = UV(0,0);
  b.ps[19] = LPoint(-w, -w, w);  b.ns[19] = LNormal(0,0,-1); b.uvs[0][19] = UV(1,0);
  b.ps[20] = LPoint(-w, w, -w);  b.ns[20] = LNormal(0,0,-1); b.uvs[0][20] = UV(0,1);
  b.ps[21] = LPoint(-w, w, -w);  b.ns[21] = LNormal(0,0,-1); b.uvs[0][21] = UV(0,1);
  b.ps[22] = LPoint(-w, -w, w);  b.ns[22] = LNormal(0,0,-1); b.uvs[0][22] = UV(1,0);
  b.ps[23] = LPoint(-w, w, w);   b.ns[23] = LNormal(0,0,-1); b.uvs[0][23] = UV(1,1);

  b.ps[24] = LPoint(-w, w, w);  b.ns[24] = LNormal(0,1,0); b.uvs[0][24] = UV(0,0);
  b.ps[25] = LPoint(w, w, w);   b.ns[25] = LNormal(0,1,0); b.uvs[0][25] = UV(1,0);
  b.ps[26] = LPoint(-w, w, -w); b.ns[26] = LNormal(0,1,0); b.uvs[0][26] = UV(0,1);
  b.ps[27] = LPoint(-w, w, -w); b.ns[27] = LNormal(0,1,0); b.uvs[0][27] = UV(0,1);
  b.ps[28] = LPoint(w, w, w);   b.ns[28] = LNormal(0,1,0); b.uvs[0][28] = UV(1,0);
  b.ps[29] = LPoint(w, w, -w);  b.ns[29] = LNormal(0,1,0); b.uvs[0][29] = UV(1,1);

  b.ps[30] = LPoint(-w, -w, -w); b.ns[30] = LNormal(0,-1,0); b.uvs[0][30] = UV(0,0);
  b.ps[31] = LPoint(w, -w, -w);  b.ns[31] = LNormal(0,-1,0); b.uvs[0][31] = UV(1,0);
  b.ps[32] = LPoint(-w, -w, w);  b.ns[32] = LNormal(0,-1,0); b.uvs[0][32] = UV(0,1);
  b.ps[33] = LPoint(-w, -w, w);  b.ns[33] = LNormal(0,-1,0); b.uvs[0][33] = UV(0,1);
  b.ps[34] = LPoint(w, -w, -w);  b.ns[34] = LNormal(0,-1,0); b.uvs[0][34] = UV(1,0);
  b.ps[35] = LPoint(w, -w, w);   b.ns[35] = LNormal(0,-1,0); b.uvs[0][35] = UV(1,1);

  if (!normals) b.ns.clear();
  if (!uvs) b.uvs[0].clear();
  if (color)
  {
    b.cs.assign(b.ps.size(), *color);
  }
}
Exemplo n.º 8
0
void makePyramid(GeometryBatch &batch, bool normals, bool uvs, const LColor *color)
{
  float h = 2.0f;
  batch.init(GL_TRIANGLES, "pyramid");
  batch.ps.resize(12);
  batch.ps[0] = LPoint(-h,-h,h);
  batch.ps[1] = LPoint(h,-h,h);
  batch.ps[2] = LPoint(0,h,0);
  batch.ps[3] = LPoint(h,-h,h);
  batch.ps[4] = LPoint(h,-h,-h);
  batch.ps[5] = LPoint(0,h,0);
  batch.ps[6] = LPoint(h,-h,-h);
  batch.ps[7] = LPoint(-h,-h,-h);
  batch.ps[8] = LPoint(0,h,0);
  batch.ps[9] = LPoint(-h,-h,-h);
  batch.ps[10] = LPoint(-h,-h,h);
  batch.ps[11] = LPoint(0,h,0);

  if (uvs)
  {
    batch.uvs[0].resize(12);
    batch.uvs[0][0] = UV(0, 0);
    batch.uvs[0][1] = UV(1, 0);
    batch.uvs[0][2] = UV(.5, 1);
    batch.uvs[0][3] = UV(0, 0);
    batch.uvs[0][4] = UV(1, 0);
    batch.uvs[0][5] = UV(.5, 1);
    batch.uvs[0][6] = UV(0, 0);
    batch.uvs[0][7] = UV(1, 0);
    batch.uvs[0][8] = UV(.5, 1);
    batch.uvs[0][9] = UV(0, 0);
    batch.uvs[0][10] = UV(1, 0);
    batch.uvs[0][11] = UV(.5, 1);
  }

  if (color)
  {
    batch.cs.assign(batch.ps.size(), *color);
  }

  if (normals)
  {
  }

  //  ostream_iterator<LPoint> osi(cout, "\n");
  //  copy(b.ps.begin(), b.ps.end(), osi);
  //  ostream_iterator<UV> osi(cout, "\n");
  //  copy(batch.uvs[0].begin(), batch.uvs[0].end(), osi);
}
Exemplo n.º 9
0
PxGeometry* BoxGeometry::ToUnmanaged()
{
	PxVec3 v = UV(this->HalfExtents);

	return new PxBoxGeometry(v);
}
Exemplo n.º 10
0
IGL_INLINE bool igl::lu_lagrange(
  const Eigen::SparseMatrix<T> & ATA,
  const Eigen::SparseMatrix<T> & C,
  Eigen::SparseMatrix<T> & L,
  Eigen::SparseMatrix<T> & U)
{
#if EIGEN_VERSION_AT_LEAST(3,0,92)
#if defined(_WIN32)
  #pragma message("lu_lagrange has not yet been implemented for your Eigen Version")
#else
  #warning lu_lagrange has not yet been implemented for your Eigen Version
#endif

  return false;
#else
  // number of unknowns
  int n = ATA.rows();
  // number of lagrange multipliers
  int m = C.cols();

  assert(ATA.cols() == n);
  if(m != 0)
  {
    assert(C.rows() == n);
    if(C.nonZeros() == 0)
    {
      // See note above about empty columns in C
      fprintf(stderr,"Error: lu_lagrange() C has columns but no entries\n");
      return false;
    }
  }

  // Check that each column of C has at least one entry
  std::vector<bool> has_entry; has_entry.resize(C.cols(),false);
  // Iterate over outside
  for(int k=0; k<C.outerSize(); ++k)
  {
    // Iterate over inside
    for(typename Eigen::SparseMatrix<T>::InnerIterator it (C,k); it; ++it)
    {
      has_entry[it.col()] = true;
    }
  }
  for(int i=0;i<(int)has_entry.size();i++)
  {
    if(!has_entry[i])
    {
      // See note above about empty columns in C
      fprintf(stderr,"Error: lu_lagrange() C(:,%d) has no entries\n",i);
      return false;
    }
  }



  // Cholesky factorization of ATA
  //// Eigen fails if you give a full view of the matrix like this:
  //Eigen::SparseLLT<SparseMatrix<T> > ATA_LLT(ATA);
  Eigen::SparseMatrix<T> ATA_LT = ATA.template triangularView<Eigen::Lower>();
  Eigen::SparseLLT<Eigen::SparseMatrix<T> > ATA_LLT(ATA_LT);

  Eigen::SparseMatrix<T> J = ATA_LLT.matrixL();

  //if(!ATA_LLT.succeeded())
  if(!((J*0).eval().nonZeros() == 0))
  {
    fprintf(stderr,"Error: lu_lagrange() failed to factor ATA\n");
    return false;
  }

  if(m == 0)
  {
    // If there are no constraints (C is empty) then LU decomposition is just L
    // and L' from cholesky decomposition
    L = J;
    U = J.transpose();
  }else
  {
    // Construct helper matrix M
    Eigen::SparseMatrix<T> M = C;
    J.template triangularView<Eigen::Lower>().solveInPlace(M);

    // Compute cholesky factorizaiton of M'*M
    Eigen::SparseMatrix<T> MTM = M.transpose() * M;

    Eigen::SparseLLT<Eigen::SparseMatrix<T> > MTM_LLT(MTM.template triangularView<Eigen::Lower>());

    Eigen::SparseMatrix<T> K = MTM_LLT.matrixL();

    //if(!MTM_LLT.succeeded())
    if(!((K*0).eval().nonZeros() == 0))
    {
      fprintf(stderr,"Error: lu_lagrange() failed to factor MTM\n");
      return false;
    }

    // assemble LU decomposition of Q
    Eigen::Matrix<int,Eigen::Dynamic,1> MI;
    Eigen::Matrix<int,Eigen::Dynamic,1> MJ;
    Eigen::Matrix<T,Eigen::Dynamic,1> MV;
    igl::find(M,MI,MJ,MV);

    Eigen::Matrix<int,Eigen::Dynamic,1> KI;
    Eigen::Matrix<int,Eigen::Dynamic,1> KJ;
    Eigen::Matrix<T,Eigen::Dynamic,1> KV;
    igl::find(K,KI,KJ,KV);

    Eigen::Matrix<int,Eigen::Dynamic,1> JI;
    Eigen::Matrix<int,Eigen::Dynamic,1> JJ;
    Eigen::Matrix<T,Eigen::Dynamic,1> JV;
    igl::find(J,JI,JJ,JV);

    int nnz = JV.size()  + MV.size() + KV.size();

    Eigen::Matrix<int,Eigen::Dynamic,1> UI(nnz);
    Eigen::Matrix<int,Eigen::Dynamic,1> UJ(nnz);
    Eigen::Matrix<T,Eigen::Dynamic,1> UV(nnz);
    UI << JJ,                        MI, (KJ.array() + n).matrix();
    UJ << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix(); 
    UV << JV,                        MV,                     KV*-1;
    igl::sparse(UI,UJ,UV,U);

    Eigen::Matrix<int,Eigen::Dynamic,1> LI(nnz);
    Eigen::Matrix<int,Eigen::Dynamic,1> LJ(nnz);
    Eigen::Matrix<T,Eigen::Dynamic,1> LV(nnz);
    LI << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix();
    LJ << JJ,                        MI, (KJ.array() + n).matrix(); 
    LV << JV,                        MV,                        KV;
    igl::sparse(LI,LJ,LV,L);
  }

  return true;
  #endif
}
Exemplo n.º 11
0
void BSP::buildSingleCluster()
{
	Material *faceMat;
//	unsigned long newFace;
	std::map<long, bool, ltulong> face_visit;	
	std::map<long, bool, ltulong> curvesurf_visit;	
	std::map<long, bool, ltulong> meshface_visit;	
	std::map<long, long, ltulong> vertex_map;
	std::map<long, long, ltulong> patch_map;
	std::map<long, std::map<long, std::map<long, unsigned int, ltulong> , ltulong> , ltulong> segRef;
	std::map<long, std::map<cvrIndex, Material *, ltindex>, ltulong> matRef;
	std::map<long, std::map<cvrIndex, Material *, ltindex>, ltulong> meshRef;
	std::map<float, std::map<float, std::map<float, cvrIndex, ltufloat>, ltufloat>, ltufloat> pointRef;
	
	XYZ segPt;
	cvrIndex newFace, p1, p2, p3;
	XYZ xyz1, xyz2, xyz3;

	int segCount = 1;
	int segIndex = 1;
	
	nullMat = new Material();
	nullMat->color=RGB(0.5f,0.5f,0.5f);
	
//	SectorMap segTest(XYZ(-10000,-10000,-10000),XYZ(10000,10000,10000),25);
	
	//loop through the leaves
	for(int i=0; i<numLeaves; ++i)
	{				
		if(leaves[i].numFaces)
		{
			segIndex = segCount;
			segCount++;
			clusterObject.setSegment(segIndex);
			
			for(int j=0; j<leaves[i].numFaces; ++j)
			{
				int faceNumber = leafFaces[leaves[i].firstLeafFace+j];
				int polygonFaceNumber = faceDirectory[faceNumber].typeFaceNumber;

//				SectorLoc secRef;
				int patchNumber;

				// todo: implement other face types.
				switch (faceDirectory[faceNumber].faceType)
				{
				case bspPolygonFace:
					if (face_visit.find(polygonFaceNumber) != face_visit.end()) continue;
					face_visit[polygonFaceNumber] = true;
					
					faceMat = NULL;
//					segIndex = -1;
					
					segPt = XYZ(vertices[polygonFaces[polygonFaceNumber].firstVertexIndex+2].position.x,vertices[polygonFaces[polygonFaceNumber].firstVertexIndex+2].position.y,vertices[polygonFaces[polygonFaceNumber].firstVertexIndex+2].position.z);

					segPt *= 100.0f;
						
//					secRef = segTest.getSector(segPt);
					
	
					// Generate a material
					if (polygonFaces[polygonFaceNumber].textureIndex>=0 && (polygonFaces[polygonFaceNumber].lightmapIndex>=0)) 
					if (matRef.find(polygonFaces[polygonFaceNumber].textureIndex) != matRef.end())
					if (matRef[polygonFaces[polygonFaceNumber].textureIndex].find(polygonFaces[polygonFaceNumber].lightmapIndex) != matRef[polygonFaces[polygonFaceNumber].textureIndex].end())
					{
						faceMat = matRef[polygonFaces[polygonFaceNumber].textureIndex][polygonFaces[polygonFaceNumber].lightmapIndex];
					}
					
					if ((polygonFaces[polygonFaceNumber].lightmapIndex>=0) && faceMat == NULL) 
					{
						faceMat = new Material();
						faceMat->color=RGB(1,1,1);
						faceMat->setMaxSmooth(80);

						// Apply the textures as layer 0, 1
						faceMat->bindTexture(0,(polygonFaces[polygonFaceNumber].lightmapIndex>=0)?lightmapTextures[polygonFaces[polygonFaceNumber].lightmapIndex]:0,TEXTURE_LIGHTMAP);
						if (polygonFaces[polygonFaceNumber].textureIndex>=0) 
						{
							faceMat->bindTexture(1,(polygonFaces[polygonFaceNumber].textureIndex>=0)?decalTextures[polygonFaces[polygonFaceNumber].textureIndex]:0,TEXTURE_DIFF);
						}
						
						// parallax test
//						faceMat->bindTexture(2,(polygonFaces[polygonFaceNumber].textureIndex>=0)?decalTextures[polygonFaces[polygonFaceNumber].textureIndex]:0,TEXTURE_BUMP);

//						if ((polygonFaces[polygonFaceNumber].textureIndex>=0) && isTextureTGA[polygonFaces[polygonFaceNumber].textureIndex])
//						{
//							faceMat->bindTexture(2,(polygonFaces[polygonFaceNumber].textureIndex>=0)?decalTextures[polygonFaces[polygonFaceNumber].textureIndex]:0,TEXTURE_ALPHA);
//						}
						matRef[polygonFaces[polygonFaceNumber].textureIndex][polygonFaces[polygonFaceNumber].lightmapIndex] = faceMat;
					}
					else if (faceMat == NULL)
					{
						faceMat = nullMat;
					}
					
//					if (segRef.find(secRef.x) != segRef.end())
//					if (segRef[secRef.x].find(secRef.y) != segRef[secRef.x].end())
//					if (segRef[secRef.x][secRef.y].find(secRef.z) != segRef[secRef.x][secRef.y].end())
//					{
//						segIndex = segRef[secRef.x][secRef.y][secRef.z];
//					}
//						
//					if (segIndex == -1)
//					{
//						segRef[secRef.x][secRef.y][secRef.z] = segIndex = segCount;
//						segCount++;
//					}
						
//					clusterObject.setSegment(segIndex);					
					
					polygonFaces[polygonFaceNumber].segmentIndex = segIndex;
					
					//decode triangle fan
					for (int k = polygonFaces[polygonFaceNumber].firstVertexIndex+2; k <  polygonFaces[polygonFaceNumber].numVertices+polygonFaces[polygonFaceNumber].firstVertexIndex; k++)
					{			
						newFace = clusterObject.addFace();
						
						clusterObject.bindFaceMaterial(faceMat);
						
						int v1, v2, v3;
						v1 = k;
						v2 = k-1;
						v3 = polygonFaces[polygonFaceNumber].firstVertexIndex;
						
//						xyz2 = XYZ(vertices[v2].position.x,vertices[v2].position.y,vertices[v2].position.z);
//						xyz3 = XYZ(vertices[v3].position.x,vertices[v3].position.y,vertices[v3].position.z);
						
						if (vertex_map.find(v1)!=vertex_map.end())
						{
							p1 = vertex_map[v1];
						}
						else
						{
							xyz1 = XYZ(vertices[v1].position.x,vertices[v1].position.y,vertices[v1].position.z);
							p1 = vertex_map[v1] = clusterObject.addPoint(xyz1);
						}

						if (vertex_map.find(v2)!=vertex_map.end())
						{
							p2 = vertex_map[v2];
						}
						else
						{
							xyz2 = XYZ(vertices[v2].position.x,vertices[v2].position.y,vertices[v2].position.z);
							p2 = vertex_map[v2] = clusterObject.addPoint(xyz2);
						}
				
						if (vertex_map.find(v3)!=vertex_map.end())
						{
							p3 = vertex_map[v3];
						}
						else
						{
							xyz3 = XYZ(vertices[v3].position.x,vertices[v3].position.y,vertices[v3].position.z);
							p3 = vertex_map[v3] = clusterObject.addPoint(xyz3);
						}
						
						
//						p1 = (pointRef[xyz1.x][xyz1.y].find(xyz1.z) != pointRef[xyz1.x][xyz1.y].end())?pointRef[xyz1.x][xyz1.y][xyz1.z]:clusterObject.addPoint(xyz1);
//						p2 = (pointRef[xyz2.x][xyz2.y].find(xyz2.z) != pointRef[xyz2.x][xyz2.y].end())?pointRef[xyz2.x][xyz2.y][xyz2.z]:clusterObject.addPoint(xyz2);
//						p3 = (pointRef[xyz3.x][xyz3.y].find(xyz3.z) != pointRef[xyz3.x][xyz3.y].end())?pointRef[xyz3.x][xyz3.y][xyz3.z]:clusterObject.addPoint(xyz3);						
						
						clusterObject.addFacePoint(p1);
						clusterObject.addFacePoint(p2);
						clusterObject.addFacePoint(p3);
						
						clusterObject.faces[newFace]->setUV(0,UV(vertices[v1].decalS,vertices[v1].decalT),0);
						clusterObject.faces[newFace]->setUV(1,UV(vertices[v2].decalS,vertices[v2].decalT),0);
						clusterObject.faces[newFace]->setUV(2,UV(vertices[v3].decalS,vertices[v3].decalT),0);
						
						//if (polygonFaces[polygonFaceNumber].lightmapIndex>=0)
						{
							clusterObject.faces[newFace]->setUV(0,UV(vertices[v1].lightmapS,vertices[v1].lightmapT),1);
							clusterObject.faces[newFace]->setUV(1,UV(vertices[v2].lightmapS,vertices[v2].lightmapT),1);
							clusterObject.faces[newFace]->setUV(2,UV(vertices[v3].lightmapS,vertices[v3].lightmapT),1);
						}
					}
				break;
				case bspPatch:	
					patchNumber = polygonFaceNumber;

					if (curvesurf_visit.find(patchNumber) != curvesurf_visit.end()) continue;
					curvesurf_visit[patchNumber] = true;
	
					faceMat = new Material();
					
					// Apply the textures as layer 0, 1
					faceMat->bindTexture(0,(patches[patchNumber].textureIndex>=0)?decalTextures[patches[patchNumber].textureIndex]:0,TEXTURE_DIFF);
					faceMat->bindTexture(1,(patches[patchNumber].lightmapIndex>=0)?lightmapTextures[patches[patchNumber].lightmapIndex]:0,TEXTURE_LIGHTMAP);
					faceMat->setMaxSmooth(80);
					// parallax test
//					faceMat->bindTexture(2,(patches[patchNumber].textureIndex>=0)?decalTextures[patches[patchNumber].textureIndex]:0,TEXTURE_BUMP);
					
					patches[patchNumber].segmentIndex=segIndex;	
//					clusterObject.setSegment(segCount);					
//					segCount++;
												
					for(int j=0; j<patches[patchNumber].numQuadraticPatches; ++j)
					{
						BSP_BIQUADRATIC_PATCH *qp = &patches[patchNumber].quadraticPatches[j];

						int v1, v2, v3;
						float ofs = 0;
						
						patch_map.clear();
						
						for(int row=0; row < qp->tesselation; ++row)
						{
							bool flip = false;

							v2 = qp->indices[(row*2*(qp->tesselation+1))];
							v3 = qp->indices[(row*2*(qp->tesselation+1))+1];																				
							
							if (patch_map.find(v2)!=patch_map.end())
							{
								p2 = patch_map[v2];
							}
							else
							{
								xyz2 = XYZ(qp->vertices[v2].position.x,qp->vertices[v2].position.y,qp->vertices[v2].position.z);
								p2 = patch_map[v2] = clusterObject.addPoint(xyz2);
							}
							
							if (patch_map.find(v3)!=patch_map.end())
							{
								p3 = patch_map[v3];
							}
							else
							{
								xyz3 = XYZ(qp->vertices[v3].position.x,qp->vertices[v3].position.y,qp->vertices[v3].position.z);
								p3 = patch_map[v3] = clusterObject.addPoint(xyz3);
							}
							
							// decode triangle strip
							for (int k = (row*2*(qp->tesselation+1))+2; k < ((row+1)*2*(qp->tesselation+1)); k++)
							{
								newFace = clusterObject.addFace();
								
								clusterObject.bindFaceMaterial(faceMat);

								v1 = v2;
								v2 = v3;
								v3 = qp->indices[k];

//								printf("vert: %d, %d, %d\n",v1,v2,v3);
//								continue;

								p1 = p2;
								p2 = p3;
//								p3 = clusterObject.addPoint(xyz3);
												
								if (patch_map.find(v3)!=patch_map.end())
								{
									p3 = patch_map[v3];
								}
								else
								{
									xyz3 = XYZ(qp->vertices[v3].position.x,qp->vertices[v3].position.y,qp->vertices[v3].position.z);
									p3 = patch_map[v3] = clusterObject.addPoint(xyz3);
								}
								
								
								if (flip) 
								{									
									clusterObject.addFacePoint(p1);
									clusterObject.addFacePoint(p2);
									clusterObject.addFacePoint(p3);

									clusterObject.faces[newFace]->setUV(0,UV(qp->vertices[v1].decalS,qp->vertices[v1].decalT+ofs),0);
									clusterObject.faces[newFace]->setUV(1,UV(qp->vertices[v2].decalS,qp->vertices[v2].decalT+ofs),0);
									clusterObject.faces[newFace]->setUV(2,UV(qp->vertices[v3].decalS,qp->vertices[v3].decalT+ofs),0);
									
									//if (polygonFaces[polygonFaceNumber].lightmapIndex>=0)
									{
										clusterObject.faces[newFace]->setUV(0,UV(qp->vertices[v1].lightmapS,qp->vertices[v1].lightmapT+ofs),1);
										clusterObject.faces[newFace]->setUV(1,UV(qp->vertices[v2].lightmapS,qp->vertices[v2].lightmapT+ofs),1);
										clusterObject.faces[newFace]->setUV(2,UV(qp->vertices[v3].lightmapS,qp->vertices[v3].lightmapT+ofs),1);
									}
								}
								else
								{
									clusterObject.addFacePoint(p3);
									clusterObject.addFacePoint(p2);
									clusterObject.addFacePoint(p1);									

									clusterObject.faces[newFace]->setUV(2,UV(qp->vertices[v1].decalS,qp->vertices[v1].decalT+ofs),0);
									clusterObject.faces[newFace]->setUV(1,UV(qp->vertices[v2].decalS,qp->vertices[v2].decalT+ofs),0);
									clusterObject.faces[newFace]->setUV(0,UV(qp->vertices[v3].decalS,qp->vertices[v3].decalT+ofs),0);
									
									//if (polygonFaces[polygonFaceNumber].lightmapIndex>=0)
									{
										clusterObject.faces[newFace]->setUV(2,UV(qp->vertices[v1].lightmapS,qp->vertices[v1].lightmapT+ofs),1);
										clusterObject.faces[newFace]->setUV(1,UV(qp->vertices[v2].lightmapS,qp->vertices[v2].lightmapT+ofs),1);
										clusterObject.faces[newFace]->setUV(0,UV(qp->vertices[v3].lightmapS,qp->vertices[v3].lightmapT+ofs),1);
									}
								}
								
								flip = !flip;
							}
						}
					}
						break;
					case bspMeshFace:
						
						if (meshface_visit.find(polygonFaceNumber) != meshface_visit.end()) continue;
						meshface_visit[polygonFaceNumber] = true;
						
						faceMat = NULL;
						
						// Generate a material
						if (meshFaces[polygonFaceNumber].textureIndex>=0 && (meshFaces[polygonFaceNumber].lightmapIndex>=0)) 
							if (meshRef[meshFaces[polygonFaceNumber].textureIndex].find(meshFaces[polygonFaceNumber].lightmapIndex) != meshRef[meshFaces[polygonFaceNumber].textureIndex].end())
							{
								faceMat = meshRef[meshFaces[polygonFaceNumber].textureIndex][meshFaces[polygonFaceNumber].lightmapIndex];
							}
						
						if (faceMat == NULL)
						{
							faceMat = new Material();
							
							// Apply the textures as layer 0, 1
							
							faceMat->bindTexture(0,(meshFaces[polygonFaceNumber].textureIndex>=0)?decalTextures[meshFaces[polygonFaceNumber].textureIndex]:0,TEXTURE_DIFF);
							faceMat->bindTexture(1,(meshFaces[polygonFaceNumber].lightmapIndex>=0)?lightmapTextures[meshFaces[polygonFaceNumber].lightmapIndex]:0,TEXTURE_LIGHTMAP);
							faceMat->setMaxSmooth(80);
//							printf("contents: %d, flags: %d\n",loadTextures[meshFaces[polygonFaceNumber].textureIndex].contents,loadTextures[meshFaces[polygonFaceNumber].textureIndex].flags);

								
							int flags = loadTextures[meshFaces[polygonFaceNumber].textureIndex].flags;
//							int contents = loadTextures[meshFaces[polygonFaceNumber].textureIndex].contents;

							
//							printf("Material %d\n",faceMat);
//
//							if (contents & CONTENTS_TRANSLUCENT) printf("flag: CONTENTS_TRANSLUCENT\n");							
//							if (flags & SURF_TRANS33) printf("flag: SURF_TRANS33\n");							
//							if (flags & SURF_TRANS66) printf("flag: SURF_TRANS66\n");							
							
							
							
							if (meshFaces[polygonFaceNumber].textureIndex>=0)
							{
								if (Texture::textures[decalTextures[meshFaces[polygonFaceNumber].textureIndex]]->img.bpp>24)
								{
									faceMat->bindTexture(2,decalTextures[meshFaces[polygonFaceNumber].textureIndex],TEXTURE_ALPHA);
								}
								else 
								if ((flags & SURF_TRANS66)) // (contents & CONTENTS_TRANSLUCENT) && 
								{
									faceMat->colorMask(true);
								}
							}
						}
						
						
						meshRef[meshFaces[polygonFaceNumber].textureIndex][meshFaces[polygonFaceNumber].lightmapIndex] = faceMat;
						meshFaces[polygonFaceNumber].segmentIndex = segIndex;
//						clusterObject.setSegment(segCount);
//						segCount++;
						
						
						
						//decode triangles
						for (int k = 0; k < meshFaces[polygonFaceNumber].numMeshIndices; k+=3)
						{			
							
							newFace = clusterObject.addFace();
							
							clusterObject.bindFaceMaterial(faceMat);
							
							int v1, v2, v3;
							v1 = meshFaces[polygonFaceNumber].firstVertexIndex+meshIndices[meshFaces[polygonFaceNumber].firstMeshIndex+k+2];
							v2 = meshFaces[polygonFaceNumber].firstVertexIndex+meshIndices[meshFaces[polygonFaceNumber].firstMeshIndex+k+1];
							v3 = meshFaces[polygonFaceNumber].firstVertexIndex+meshIndices[meshFaces[polygonFaceNumber].firstMeshIndex+k];
							
//							xyz1 = XYZ(vertices[v1].position.x,vertices[v1].position.y,vertices[v1].position.z);
//							xyz2 = XYZ(vertices[v2].position.x,vertices[v2].position.y,vertices[v2].position.z);
//							xyz3 = XYZ(vertices[v3].position.x,vertices[v3].position.y,vertices[v3].position.z);
//							
//							
//							p1 = (pointRef[xyz1.x][xyz1.y].find(xyz1.z) != pointRef[xyz1.x][xyz1.y].end())?pointRef[xyz1.x][xyz1.y][xyz1.z]:clusterObject.addPoint(xyz1);
//							p2 = (pointRef[xyz2.x][xyz2.y].find(xyz2.z) != pointRef[xyz2.x][xyz2.y].end())?pointRef[xyz2.x][xyz2.y][xyz2.z]:clusterObject.addPoint(xyz2);
//							p3 = (pointRef[xyz3.x][xyz3.y].find(xyz3.z) != pointRef[xyz3.x][xyz3.y].end())?pointRef[xyz3.x][xyz3.y][xyz3.z]:clusterObject.addPoint(xyz3);						

							
							
							if (vertex_map.find(v1)!=vertex_map.end())
							{
								p1 = vertex_map[v1];
							}
							else
							{
								xyz1 = XYZ(vertices[v1].position.x,vertices[v1].position.y,vertices[v1].position.z);
								p1 = vertex_map[v1] = clusterObject.addPoint(xyz1);
							}
							
							if (vertex_map.find(v2)!=vertex_map.end())
							{
								p2 = vertex_map[v2];
							}
							else
							{
								xyz2 = XYZ(vertices[v2].position.x,vertices[v2].position.y,vertices[v2].position.z);
								p2 = vertex_map[v2] = clusterObject.addPoint(xyz2);
							}
							
							if (vertex_map.find(v3)!=vertex_map.end())
							{
								p3 = vertex_map[v3];
							}
							else
							{
								xyz3 = XYZ(vertices[v3].position.x,vertices[v3].position.y,vertices[v3].position.z);
								p3 = vertex_map[v3] = clusterObject.addPoint(xyz3);
							}
							
							
							
							clusterObject.addFacePoint(p1);
							clusterObject.addFacePoint(p2);
							clusterObject.addFacePoint(p3);
							
							clusterObject.faces[newFace]->setUV(0,UV(vertices[v1].decalS,vertices[v1].decalT),0);
							clusterObject.faces[newFace]->setUV(1,UV(vertices[v2].decalS,vertices[v2].decalT),0);
							clusterObject.faces[newFace]->setUV(2,UV(vertices[v3].decalS,vertices[v3].decalT),0);
							
							//if (meshFaces[polygonFaceNumber].lightmapIndex>=0)
							{
								clusterObject.faces[newFace]->setUV(0,UV(vertices[v1].lightmapS,vertices[v1].lightmapT),1);
								clusterObject.faces[newFace]->setUV(1,UV(vertices[v2].lightmapS,vertices[v2].lightmapT),1);
								clusterObject.faces[newFace]->setUV(2,UV(vertices[v3].lightmapS,vertices[v3].lightmapT),1);
							}
						}

						break;
				}
			}
		}
		else
		{
			//clusterObjects[i] = NULL;
		}
		
	}
	
	
//	clusterObject.setMaterialMask(true);
	Logger::log(LOG_NOTICE,"\n\nNum Segments: %d\n",clusterObject.numSegments);
	Logger::log(LOG_NOTICE,"\n\nNum Faces: %d\n",clusterObject.faces.size());
//	Logger::log(LOG_NOTICE,"\n\nNum Materials: %d\n",Material::materials.size());
	clusterObject.calcNormals();
	clusterObject.cache(true);
	
	single_cluster = true;
}
Exemplo n.º 12
0
void Database::SaverLoader::load()
{
    tUV.clear();
    tEtudiant.clear();
    tFormation.clear();
    tCategorie.clear();
    tNote.clear();
    tSaison.clear();
    tSemestre.clear();
    //load Notes
    string q="SELECT note, description, rang, eliminatoire FROM Note;";
    QSqlQuery res=db.query(q);
    while(res.next())
    {
        Note note(res.value(0).toString(),res.value(1).toString(),res.value(2).toUInt(),res.value(3).toUInt());
    }

    //load Saisons
     q="SELECT nom, description FROM Saison;";
     res=db.query(q);
    while(res.next())
    {
        Saison Sais(res.value(0).toString(),res.value(1).toString());
    }

    //load Semestres
     q="SELECT code, saison, year FROM Semestre;";
     res=db.query(q);
    while(res.next())
    {
        Semestre sem(tSaison.getElement(res.value(1).toString()),res.value(2).toInt());
    }
    qDebug()<<"test";

    //load Catégories

    q="SELECT code, description FROM Categorie;";
    res=db.query(q);
    while(res.next())
    {
        Categorie cat(res.value(0).toString(),res.value(1).toString());
    }
    qDebug()<<"test";
    //Mise en place des sous Catégories
    for(std::vector<Categorie>::iterator it_cat=tCategorie.getIterator();it_cat!=tCategorie.end();it_cat++)
    {
        q="SELECT codeParent, codeFille FROM SousCategorie where codeParent='"+it_cat->getCode().toStdString()+"';";
        res=db.query(q);
        while(res.next())
        {
            tCategorie.getElement(res.value(0).toString()).addSousCategorie(tCategorie.getElement(res.value(1).toString()));
        }
    }
    qDebug()<<"test";

    //load UVS
    q="SELECT code, titre, automne, printemps FROM UV;";
    res=db.query(q);
    while(res.next())
    {
       map<Categorie, unsigned int> uvcre=map<Categorie, unsigned int>();
       string q1="SELECT code, categorie, nbCredits FROM CreditsUV WHERE code='"+res.value(0).toString().toStdString()+"';";
       QSqlQuery res1=db.query(q1);
       while(res1.next())
       {
           uvcre[StringToCategorie(res1.value(1).toString())]=res1.value(2).toInt();
       }
       UV(res.value(0).toString().toStdString(), res.value(1).toString().toStdString(), uvcre, res.value(2).toBool(), res.value(3).toBool());

    }
    //load Formation
    q="SELECT nom, description FROM Formation;";
    res=db.query(q);
    while(res.next())
    {
        map<UV*, bool> uvs=map<UV*, bool>();
        string q1="SELECT formation, uv, obligatoire FROM FormationUV where formation='"+res.value(0).toString().toStdString()+"';";
        QSqlQuery res1=db.query(q1);
        while(res1.next())
        {
            UV& uv=tUV.getElement(res1.value(1).toString().toStdString());
            uvs[&uv]=res1.value(2).toBool();
        }
        map<Categorie, unsigned int> Cat=map<Categorie, unsigned int>();
        q1="SELECT formation, categorie, nbCredits FROM CreditsFormation where formation='"+res.value(0).toString().toStdString()+"';";
        res1=db.query(q1);
        while(res1.next())
        {
            Cat[StringToCategorie(res1.value(1).toString())]=res1.value(2).toInt();
        }

        std::vector<Condition> conds;
        q1="SELECT formation, condition FROM conditionsFormation where formation='"+res.value(0).toString().toStdString()+"';";
        res1=db.query(q1);
        while(res1.next())
        {
           conds.push_back(Condition(res1.value(1).toString()));
        }
        Formation(res.value(0).toString(), res.value(1).toString(), uvs, Cat,conds);
    }

    //load Etudiants
    q="SELECT ine, login, nom, prenom, dateNaissance from Etudiant;";
    res=db.query(q);
    while(res.next())
    {
        vector<Inscription> insc= vector<Inscription>();
        string q1="SELECT login, code, saison, annee, resultat FROM Inscription WHERE login='******';";
        QSqlQuery res1=db.query(q1);
        while(res1.next())
        {
            //Semestre s=Semestre(StringToSaison(res1.value(2).toString()), res1.value(3).toInt());
            string code=res1.value(1).toString().toStdString();
            const UV& uv=tUV.getElement(code);
            Inscription inscription=Inscription(uv, tSemestre.getElement(res1.value(2).toString()+res1.value(3).toString()), StringToNote(res1.value(4).toString()));
            insc.push_back(inscription);
        }
        vector<Formation*> form= vector<Formation*>();
        q1="SELECT login, formation FROM FormationEtudiant WHERE login='******';";
        res1=db.query(q1);
        while(res1.next())
        {
            Formation& F=tFormation.getElement(res1.value(1).toString().toStdString());
            form.push_back(&F);
        }
        Dossier dos=Dossier(insc, form);
        Etudiant etu=Etudiant(dos, res.value(0).toInt(), res.value(2).toString(), res.value(3).toString(), res.value(4).toDate(), res.value(1).toString());
        qDebug()<<"fin load";
    }
}
Exemplo n.º 13
0
void BoxObstacle::HalfExtents::set(Vector3 value)
{
	this->UnmanagedPointer->mHalfExtents = UV(value);
}
Exemplo n.º 14
0
void UVEditorController::uvToUpdate_dataChanged(QModelIndex x ,QModelIndex y){
    const std::vector<UV*>* uvs = uv_accessDB->getAll();
    bool modified;

    // column 0 : code isn't modifiable
    if(x.column() == 1){
        QString title = x.data().toString();
        if(title.size() <= 50){
            modified = true;
        }
        else
            UTProfilerException(uiUVEditor->exceptionLabel_main, "Maximum length is 50 characters.");
    }
    else if(x.column() == 2){
        QString descr = x.data().toString();
        if(descr.size() <= 500){
            modified = true;
        }
        else
            UTProfilerException(uiUVEditor->exceptionLabel_main, "Maximum length is 500 characters.");
    }
    else if(x.column() == 3){
        bool ok;
        int nbCredits = x.data().toString().toInt(&ok,10);
        if(ok && nbCredits <= 60){
            modified = true;
        }
        else
            UTProfilerException(uiUVEditor->exceptionLabel_main, "Maximum credits for one UV is 60.");
    }
    else if(x.column() == 4){
        std::string category = x.data().toString().toStdString();
        // get category
        int i=-1;
        while(category != CategoryNames[++i] && i<=3);
        if(i<=3){
            modified = true;
        }
        else
            UTProfilerException(uiUVEditor->exceptionLabel_main, "Categories are CS, TM, TSH or SP.");
    }

    if(!modified){
        QObject::disconnect(uv_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(uvToUpdate_dataChanged(QModelIndex,QModelIndex)) );

        if(x.row() < uvs->size()){ // existing UV in DB
            uv_model->item(x.row(), 0)->setText(uvs->at(x.row())->getCode().c_str());
            uv_model->item(x.row(), 1)->setText(uvs->at(x.row())->getTitle().c_str());
            uv_model->item(x.row(), 2)->setText(uvs->at(x.row())->getDescription().c_str());
            uv_model->item(x.row(), 3)->setText(QString::number(uvs->at(x.row())->getNbCredits()));
            uv_model->item(x.row(), 4)->setText(CategoryNames[uvs->at(x.row())->getCategory()]);
        }
        else{ // New UV in DB
            uv_model->item(x.row(), 0)->setText(uvs->at(x.row()-uvs->size())->getCode().c_str());
            uv_model->item(x.row(), 1)->setText(uvs->at(x.row()-uvs->size())->getTitle().c_str());
            uv_model->item(x.row(), 2)->setText(uvs->at(x.row()-uvs->size())->getDescription().c_str());
            uv_model->item(x.row(), 3)->setText(QString::number(uvs->at(x.row()-uvs->size())->getNbCredits()));
            uv_model->item(x.row(), 4)->setText(CategoryNames[uvs->at(x.row()-uvs->size())->getCategory()]);
        }

        QObject::connect(uv_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(uvToUpdate_dataChanged(QModelIndex,QModelIndex)));
    }
    else{
        std::string category = uv_model->item(x.row(), 4)->text().toStdString();
        int i=-1;
        while(category != CategoryNames[++i] && i<=3);
        Category cat = static_cast<Category>(i);

        // Is the UV already modified ?
        std::vector<UV>::iterator it;
        for(it = modifiedUVs->begin(); it != modifiedUVs->end() && it->getCode() != uv_model->item(x.row(), 0)->text().toStdString(); ++it){
        }
        if(it == modifiedUVs->end())
            modifiedUVs->push_back(UV(uv_model->item(x.row(), 0)->text().toStdString(), uv_model->item(x.row(), 1)->text().toStdString(), uv_model->item(x.row(), 2)->text().toStdString(), uv_model->item(x.row(), 3)->text().toInt(), cat ));
        else
        {
            it->setTitle(uv_model->item(x.row(), 1)->text().toStdString());
            it->setDescription(uv_model->item(x.row(), 2)->text().toStdString());
            it->setNbCredits(uv_model->item(x.row(), 3)->text().toInt());
            it->setCategory(uv_model->item(x.row(), 4)->text().toStdString());
        }
    }


}
Exemplo n.º 15
0
  void initialize( float radius,
                   float segmentsWidth,
                   float segmentsHeight,
                   float phiStart,
                   float phiLength,
                   float thetaStart,
                   float thetaLength ) {

    const auto segmentsX = Math::max( 3, ( int )Math::floor( segmentsWidth ) );
    const auto segmentsY = Math::max( 2, ( int )Math::floor( segmentsHeight ) );

    std::vector<std::vector<int>> indices;
    std::vector<std::vector<UV>> uvs;

    for ( int y = 0; y <= segmentsY; y ++ ) {

      std::vector<int> indicesRow;
      std::vector<UV> uvsRow;

      for ( int x = 0; x <= segmentsX; x ++ ) {

        const auto u = ( float )x / segmentsX;
        const auto v = ( float )y / segmentsY;

        Vertex vertex;
        vertex.x = - radius * Math::cos( phiStart + u * phiLength ) * Math::sin( thetaStart + v * thetaLength );
        vertex.y = radius * Math::cos( thetaStart + v * thetaLength );
        vertex.z = radius * Math::sin( phiStart + u * phiLength ) * Math::sin( thetaStart + v * thetaLength );

        vertices.push_back( vertex );

        indicesRow.push_back( ( int )vertices.size() - 1 );
        uvsRow.push_back( UV( u, 1 - v ) );

      }

      indices.push_back( indicesRow );
      uvs.push_back( uvsRow );

    }

    for ( int y = 0; y < segmentsY; y ++ ) {

      for ( int x = 0; x < segmentsX; x ++ ) {

        const auto v1 = indices[ y ][ x + 1 ];
        const auto v2 = indices[ y ][ x ];
        const auto v3 = indices[ y + 1 ][ x ];
        const auto v4 = indices[ y + 1 ][ x + 1 ];

        const auto n1 = vertices[ v1 ].clone().normalize();
        const auto n2 = vertices[ v2 ].clone().normalize();
        const auto n3 = vertices[ v3 ].clone().normalize();
        const auto n4 = vertices[ v4 ].clone().normalize();

        const auto& uv1 = uvs[ y ][ x + 1 ];
        const auto& uv2 = uvs[ y ][ x ];
        const auto& uv3 = uvs[ y + 1 ][ x ];
        const auto& uv4 = uvs[ y + 1 ][ x + 1 ];

        if ( Math::abs( vertices[ v1 ].y ) == radius ) {

          faces.push_back( Face3( v1, v3, v4, n1, n3, n4 ) );
          faceVertexUvs[ 0 ].push_back( toArray( uv1, uv3, uv4 ) );

        } else if ( Math::abs( vertices[ v3 ].y ) ==  radius ) {

          faces.push_back( Face3( v1, v2, v3, n1, n2, n3 ) );
          faceVertexUvs[ 0 ].push_back( toArray( uv1, uv2, uv3 ) );

        } else {

          faces.push_back( Face4( v1, v2, v3, v4, n1, n2, n3, n4 ) );
          faceVertexUvs[ 0 ].push_back( toArray( uv1, uv2, uv3, uv4 ) );

        }

      }

    }

    computeCentroids();
    computeFaceNormals();

    boundingSphere.radius = radius;

  }