Ejemplo n.º 1
0
void terrain::setTerrainSize(btVector3 size)
{
	if(size == m_terrainSize) return;
	
	btVector3 modscale = (size - m_terrainSize) / m_terrainSize;	// the difference between the new and old size divided by the old size
	
	if(m_terrainSize.z() == 0) modscale.setZ(size.z());				// incase of NAN
	
	m_terrainMinHeight = m_terrainMaxHeight = 0;
    for(int i=0; i<m_terrainVertexCount; i++){
        m_terrainVerts[i].x += modscale.x() * m_terrainVerts[i].x;
        m_terrainVerts[i].y += modscale.y() * m_terrainVerts[i].y;
        
		if(m_terrainSize.z() == 0)
			m_terrainVerts[i].z = size.z();
		else
			m_terrainVerts[i].z += modscale.z() * m_terrainVerts[i].z;

		if(m_terrainVerts[i].z > m_terrainMaxHeight)
			m_terrainMaxHeight = m_terrainVerts[i].z;
		else if(m_terrainVerts[i].z < m_terrainMinHeight)
			m_terrainMinHeight = m_terrainVerts[i].z;
    }
    buildNormals();

	m_terrainSize = size;
	tTool->setSize(m_terrainSize);
	
	m_parent->printText(QString("Terrain Resized %1,%2,%3").arg(m_terrainSize.x()).arg(m_terrainSize.y()).arg(m_terrainSize.z()));

    this->terrainRefresh();
	emit newTerrain();
}
Ejemplo n.º 2
0
void MD5Model::animate(float dt) {
	// sanity check #1
	if (currAnim < 0 || currAnim >= int(anims.size()) || !anims[currAnim])
		throw Exception("MD5Model::animate(): currAnim is invalid");

	Anim *anim = anims[currAnim];

	// sanity check #2
	if (currFrame < 0 || currFrame >= int(anim->numFrames))
		throw Exception("MD5Model::animate(): currFrame is invalid");

	// compute index of next frame
	int nextFrameIndex = currFrame >= anim->numFrames - 1 ? 0 : currFrame + 1;

	// update animation time
	animTime += dt*float(anim->frameRate);
	if (animTime > 1.0f) {
		while (animTime > 1.0f)
			animTime -= 1.0f;
		//setFrame(nextFrameIndex);
		currFrame = nextFrameIndex;
		nextFrameIndex = currFrame >= anim->numFrames - 1 ? 0 : currFrame + 1;
	}

	// make sure size of storage for interpolated frame is correct
	if (int(interpFrame.joints.size()) != numJoints)
		interpFrame.joints.resize(numJoints);

	///// now interpolate between the two frames /////

	Frame &frame = anim->frames[currFrame],
		&nextFrame = anim->frames[nextFrameIndex];

	// interpolate between the joints of the current frame and those of the next
	// frame and store them in interpFrame
	for (int i = 0; i < numJoints; i++) {
		Joint &interpJoint = interpFrame.joints[i];

		// linearly interpolate between joint positions
		float *pos1 = frame.joints[i].pos,
			*pos2 = nextFrame.joints[i].pos;
		interpJoint.pos[0] = pos1[0] + animTime*(pos2[0] - pos1[0]);
		interpJoint.pos[1] = pos1[1] + animTime*(pos2[1] - pos1[1]);
		interpJoint.pos[2] = pos1[2] + animTime*(pos2[2] - pos1[2]);

		interpJoint.quat = slerp(frame.joints[i].quat, nextFrame.joints[i].quat, animTime);
	}

	buildVerts(interpFrame);
	buildNormals();
	calculateRenderData();
}
Ejemplo n.º 3
0
// the center of editing takes place at HERE
// raise terrain DIR = 1, lower terrain DIR = -1
void terrain::terrainEdit(btVector3 here, int dir)
{
	float area = tTool->diameter();
	float amount = tTool->increment();
	
	if(area <= 0 || amount <= 0) return;
	
	amount *= dir;															// determine the direction of editing, up or down
	
	float xp = here.x();													// make sure the X location of the edit is over the terrain
    if(xp < 0) xp = 0;
    else if(xp > m_terrainSize.x()) xp = m_terrainSize.x();
	
	float yp = here.y();													// make sure the Y location of the edit is over the terrain
    if(yp < 0) yp = 0;
    else if(yp > m_terrainSize.y()) yp = m_terrainSize.y();
	
	for(int i=0; i<m_terrainVertexCount; i++)								// loop through the terrain vertex array
	{
        float x = (i % m_pixelSize.width()) * m_terrainSize.x()/m_pixelSize.width();// get the X and Y incides of the terrain vertices
        float y = (i / m_pixelSize.width()) * m_terrainSize.y()/m_pixelSize.height();

		float xd = xp - x;
		float yd = yp - y;

		float d = (float)sqrt((xd*xd) + (yd*yd));							// calculate the diameter of the area
		float a = (m_terrainVerts[i].z + amount) - (amount*(d / area));		// calculate the new height of the vertex
		
		if((dir == 1 && a > m_terrainVerts[i].z) || (dir == -1 && a < m_terrainVerts[i].z)) {
			m_terrainVerts[i].z = a;
			
			if(a > m_terrainMaxHeight) 
				m_terrainMaxHeight = a;
			else if(a < m_terrainMinHeight)
				m_terrainMinHeight = a;
			
			float avgheight = (m_terrainMaxHeight + m_terrainMinHeight)/2.0;
			
			if(a > avgheight) m_terrainColors[i].x = 0.8;			// set red color
			else m_terrainColors[i].x = 0.;
			m_terrainColors[i].y = 0.;								// set green color
			if(a < avgheight) m_terrainColors[i].z = 0.8;			// set blue color
			else m_terrainColors[i].z = 0.;
		}
	}
	
	buildNormals();

    this->terrainRefresh();
	m_terrainModified = true;
}
Ejemplo n.º 4
0
void RMesh::mesh::cube(QString filename, mesh &m)
{
    assert( &m != NULL );

//    float plus  = 0.5;
//    float minus = -plus;
    float plus  = 2.5;
    float minus = 1.0;

    m.vertices.reserve(8);
    m.polygons.reserve(12);

    // initialize points
    m.vertices.push_back( Primitives::Point3d( minus, plus, plus   ));
    m.vertices.push_back( Primitives::Point3d( minus, plus, minus  ));
    m.vertices.push_back( Primitives::Point3d( plus, plus, minus   ));
    m.vertices.push_back( Primitives::Point3d( plus, plus, plus    ));
    m.vertices.push_back( Primitives::Point3d( minus, minus, plus  ));
    m.vertices.push_back( Primitives::Point3d( minus, minus, minus ));
    m.vertices.push_back( Primitives::Point3d( plus, minus, minus  ));
    m.vertices.push_back( Primitives::Point3d( plus, minus, plus   ));


    m.polygons.push_back( MeshPolygon( 2, 1, 3 ));
    m.polygons.push_back( MeshPolygon( 3, 1, 0 ));
    m.polygons.push_back( MeshPolygon( 1, 5, 0 ));
    m.polygons.push_back( MeshPolygon( 0, 5, 4 ));
    m.polygons.push_back( MeshPolygon( 1, 2, 5 ));
    m.polygons.push_back( MeshPolygon( 5, 2, 6 ));
    m.polygons.push_back( MeshPolygon( 3, 0, 7 ));
    m.polygons.push_back( MeshPolygon( 7, 0, 4 ));
    m.polygons.push_back( MeshPolygon( 7, 2, 3 ));
    m.polygons.push_back( MeshPolygon( 2, 7, 6 ));
    m.polygons.push_back( MeshPolygon( 7, 5, 6 ));
    m.polygons.push_back( MeshPolygon( 5, 7, 4 ));

    buildNormals(m);

    vector < Primitives::Point3d > points_for_bbox;
    for (int i = 0; i < m.vertices.size(); ++i)
    {
        points_for_bbox.push_back( Primitives::Point3d( m.vertices[i][0], m.vertices[i][1], m.vertices[i][2] ));
    }
    m.bbox = Primitives::BBoxD();
    m.bbox.Set(points_for_bbox);
    std::cout << "bbox center : " << m.bbox.Center()[0] << ", " << m.bbox.Center()[1] << ", " << m.bbox.Center()[1]  << endl;
}
Ejemplo n.º 5
0
void MD5Model::loadMesh(const char *filename) {
	// sanity check
	if (!filename)
		throw Exception("MD5Model::loadMesh(): filename is NULL");

	// attempt to open file for reading
	std::ifstream fin(filename, std::ifstream::in);

	// was open successful?
	if (!fin.is_open()) {
		std::string msg = std::string("MD5Model::loadMesh(): unable to open ") +
			std::string(filename) + std::string(" for reading");
		throw Exception(msg);
	}

	// read in file version
	std::string str;
	getNextToken(fin, &str);

	// token must read "MD5Version"
	if (str != "MD5Version")
		throw Exception("MD5Model::loadMesh(): expected 'MD5Version'");

	// get version #
	int ver = readInt(fin);
	// must be version 10
	if (ver != 10)
		throw Exception("MD5Model::loadMesh(): MD5Version must be 10");

	// clear any data before reading file
	clear();

	// read in all of the MD5Model elements
	readElements(fin);

	// close input file (should be done destructor anyway...)
	fin.close();

	// calculate vertex positions and normals from information in joints
	// 模型pose姿势中,多个骨骼节点初始位置+连续weight位置变换(骨骼节点开始的位置 + weightPos经过joint四元数旋转的位置)* 权重 的结果作为顶点的位置。
	buildVerts();
	// 直接叉乘,规范化,将单位面法向量作为每个顶点的法向量
	buildNormals();

	createRenderData();
}
Ejemplo n.º 6
0
void MD5Model::setFrame(int frameIndex) {
	// sanity check #1
	if (anims.size() == 0 || currAnim < 0)
		throw Exception("MD5Model::setFrame(): no animation has beens set");

	// sanity check #2
	if (frameIndex < 0 || !anims[currAnim] ||
		anims[currAnim]->numFrames <= 0 ||
		anims[currAnim]->numFrames <= frameIndex)
		throw Exception("MD5Model::setFrame(): frame index is invalid");

	buildVerts(anims[currAnim]->frames[frameIndex]);
	buildNormals();
	calculateRenderData();
	currFrame = frameIndex;
	animTime = 0.0f;
}
Ejemplo n.º 7
0
// creates a new triangle based terrain mesh, be sure heightData is large enough
// to fit the world which must be set prior. This function fills the proper arrays
// for both OpenGL and Bullet.
void terrain::terrainCreateMesh(unsigned int *heightData)
{
    int i,j,k;
	btVector3 scale;
    int xWorld = m_pixelSize.width();
    int yWorld = m_pixelSize.height();
	
	scale.setX(m_terrainSize.x() / m_pixelSize.width());
	scale.setY(m_terrainSize.y() / m_pixelSize.height());
	if(heightData != NULL) scale.setZ(m_terrainSize.z() / (float)heightData[m_terrainVertexCount]);
	else scale.setZ(1);
	
    m_terrainVertexCount = xWorld * yWorld;   				// calculate the number of verticies
    m_terrainTriangleCount = (xWorld-1) * (yWorld-1)*2; 	// calculate the number of triangles
	
    // allocate new data arrays
    m_terrainVerts = new Vertex[m_terrainVertexCount];
    m_terrainColors = new Vertex[m_terrainVertexCount];
    m_terrainNormals = new Vertex[m_terrainVertexCount];
    m_terrainTriangles = new Triangle[m_terrainTriangleCount];
	m_terrainMaxHeight = m_terrainSize.z();
	m_terrainMinHeight = 0;
	
    // generate the vertices for the triangle mesh
    // This sets the proper coordinates for the vertices that
    // will make up the terrain triangle mesh. The color of
    // each vertex is based on the height of from the BMP
    for(i=0; i<m_terrainVertexCount; i++)
    {
        m_terrainVerts[i].x = (i % xWorld) * scale.x();
        m_terrainVerts[i].y = (i / xWorld) * scale.y();

		if(heightData != NULL) 
			m_terrainVerts[i].z = heightData[i] * scale.z();	// get the height from the image data and scale it
		else 
			m_terrainVerts[i].z = m_terrainSize.z();
			
        m_terrainColors[i].x = 0.7 * m_terrainVerts[i].z / m_terrainMaxHeight;		// set the color based on the terrain height
        m_terrainColors[i].y = 0.7 * m_terrainVerts[i].z / m_terrainMaxHeight;
        m_terrainColors[i].z = 0.7 * m_terrainVerts[i].z / m_terrainMaxHeight;
    }
	
    // generate the indices which point to the vertices of the triangle mesh
    // the m_terrainTriangle array is used to tell OpenGL and Bullet
    // what vertices make up each triangle. This is done so the same vertices
    // can be re-used for different triangles
    k=0;
    for(j=1;j<yWorld;j++)
    {
        for(i=1;i<xWorld;i++)
        {
            int ind1 = ((j-1) * xWorld) + (i-1);
            int ind2 = (j * xWorld) + (i-1);
            int ind3 = ((j-1) * xWorld) + i;
            int ind4 = (j * xWorld) + i;
			
            // low triangle
            m_terrainTriangles[k].v1 = ind1;
            m_terrainTriangles[k].v2 = ind3;
            m_terrainTriangles[k].v3 = ind2;
            // high triangle
            m_terrainTriangles[k+1].v1 = ind2;
            m_terrainTriangles[k+1].v2 = ind3;
            m_terrainTriangles[k+1].v3 = ind4;
            k += 2;
        }
    }
    buildNormals();
}
Ejemplo n.º 8
0
// Main function for fast curving
void HighOrderMeshFastCurving(GModel *gm, FastCurvingParameters &p)
{
  double t1 = Cpu();

  Msg::StatusBar(true, "Optimizing high order mesh...");
  std::vector<GEntity*> allEntities;
  gm->getEntities(allEntities);

  // Compute vert. -> elt. connectivity
  Msg::Info("Computing connectivity...");
  std::map<MVertex*, std::vector<MElement *> > vertex2elements;
  for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt)
    calcVertex2Elements(p.dim, allEntities[iEnt], vertex2elements);

  // Get BL field (if any)
  BoundaryLayerField *blf = getBLField(gm);

  // Build multimap of each geometric entity to its boundaries
  std::multimap<GEntity*,GEntity*> entities;
  if (blf) {                                                                                    // BF field?
    for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) {
      GEntity* &entity = allEntities[iEnt];
      if (entity->dim() == p.dim && (!p.onlyVisible || entity->getVisibility()))                // Consider only "domain" entities
        if (p.dim == 2) {                                                                       // "Domain" face?
          std::list<GEdge*> edges = entity->edges();
          for (std::list<GEdge*>::iterator itEd = edges.begin(); itEd != edges.end(); itEd++)   // Loop over model boundary edges
            if (blf->isEdgeBL((*itEd)->tag()))                                                  // Already skip model edge if no BL there
              entities.insert(std::pair<GEntity*,GEntity*>(entity, *itEd));
        }
        else if (p.dim == 3) {                                                                  // "Domain" region?
          std::list<GFace*> faces = entity->faces();
          for (std::list<GFace*>::iterator itF = faces.begin(); itF != faces.end(); itF++)      // Loop over model boundary faces
            if (blf->isFaceBL((*itF)->tag()))                                                   // Already skip model face if no BL there
              entities.insert(std::pair<GEntity*,GEntity*>(entity, *itF));
        }
    }
  }
  else {                                                                                        // No BL field
    for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) {
      GEntity* &entity = allEntities[iEnt];
      if (entity->dim() == p.dim-1 && (!p.onlyVisible || entity->getVisibility()))              // Consider boundary entities
        entities.insert(std::pair<GEntity*,GEntity*>(0, entity));
    }
  }

  // Build normals if necessary
  std::map<GEntity*, std::map<MVertex*, SVector3> > normVertEnt;                                // Normal to each vertex for each geom. entity
  if (!blf) {
    Msg::Warning("Boundary layer data not found, trying to detect columns");
    buildNormals(vertex2elements, entities, p, normVertEnt);
  }

  // Loop over geometric entities
  for (std::multimap<GEntity*,GEntity*>::iterator itBE = entities.begin();
       itBE != entities.end(); itBE++) {
    GEntity *domEnt = itBE->first, *bndEnt = itBE->second;
    BoundaryLayerColumns *blc = 0;
    if (blf) {
      Msg::Info("Curving elements for entity %d bounding entity %d...",
                bndEnt->tag(), domEnt->tag());
      if (p.dim == 2)
        blc = domEnt->cast2Face()->getColumns();
      else if (p.dim == 3)
        blc = domEnt->cast2Region()->getColumns();
      else
        Msg::Error("Fast curving implemented only in dim. 2 and 3");
    }
    else
      Msg::Info("Curving elements for boundary entity %d...", bndEnt->tag());
    std::map<MVertex*, SVector3> &normVert = normVertEnt[bndEnt];
    curveMeshFromBnd(vertex2elements, normVert, blc, bndEnt, p);
  }

  double t2 = Cpu();

  Msg::StatusBar(true, "Done curving high order mesh (%g s)", t2-t1);
}