Beispiel #1
0
void truncated_cone(const Mat4x4f& m, float l, float w0, float w1, vector<Vec3f>& strip)
{
    float len = sqrt(l*l + sqr(w0-w1));
    float a = l/len;
    float b = (w0-w1)/len;
    const int N = 10;
    for(int i=0;i<=N;++i)
    {
        float alpha = 2.0*M_PI*float(i)/N;
        Vec3f p0 = m.mul_3D_point(Vec3f(w0*cos(alpha), w0*sin(alpha), 0));
        Vec3f p1 = m.mul_3D_point(Vec3f(w1*cos(alpha), w1*sin(alpha), l));
        Vec3f n = m.mul_3D_vector(a*Vec3f(cos(alpha), sin(alpha), b));
        if(i==0){
            strip.push_back(n);
            strip.push_back(p0);
        }
        strip.push_back(n);
        strip.push_back(p0);
        strip.push_back(n);
        strip.push_back(p1);
        if(i==N){
            strip.push_back(n);
            strip.push_back(p1);
        }
    }
}
Beispiel #2
0
  void BSPTree::init(const TriMesh* mesh, Mat4x4f transform, 
             vector<int> &trilist, 
             int _max_objects, int _max_level) 
  {
    trimesh.push_back(mesh);
    transforms.push_back(transform);
    // Loop through all triangles and add them to intersection structure
    for(unsigned int j=0;j<trilist.size();j++) 
    {
      Vec3i face = mesh->geometry.face(trilist[j]);
      ISectTri new_tri;
      new_tri.point0 = transform.mul_3D_point(mesh->geometry.vertex(face[0]));
      new_tri.point1 = transform.mul_3D_point(mesh->geometry.vertex(face[1]));
      new_tri.point2 = transform.mul_3D_point(mesh->geometry.vertex(face[2]));
      new_tri.edge0 = new_tri.point1 - new_tri.point0;
      new_tri.edge1 = new_tri.point2 - new_tri.point0;
      new_tri.mesh_id = 0;
      new_tri.tri_id = trilist[j];
      isecttris.push_back(new_tri);
      TriAccel ta;
      create_tri_accel(new_tri.point0, new_tri.point1, new_tri.point2, ta);
      ta.mesh_id = 0;
      ta.tri_id = trilist[j];
      triaccel.push_back(ta);
    }

    max_objects = _max_objects;
    max_level = _max_level;
    init();
  }
Beispiel #3
0
	void Sphere::transform(const Mat4x4f& m)
	 {
	   Vec3f radius_vec = m.mul_3D_point(Vec3f(radius,0,0)+position);
	   position = m.mul_3D_point(position); 
	   // The radius is scaled by the X scaling factor.
	   // Not ideal, but the best we can do without elipsoids
	   radius_vec -= position;
	   radius = radius_vec.length();
	 }
void DebugVectorRenderer::Render()
{
	if (primitiveCount > 0)
	{
		if (meshesInitialized == false)
		{
			this->CreateMeshes();
		}

		Engine* engine = Engine::GetInstance();
		Camera* camera = this->activeCamera;

		Mat4x4f viewProjection = camera->GetProjectionMatrix() * camera->GetViewMatrix();

		ResourceManager* rm = engine->GetResourceManager();
		Shader* shader = rm->GetShader("res/shaders/debug_vector.shader.json");

		int colorUniformLocation = -1;
		for (unsigned int i = 0; i < shader->materialUniformCount; ++i)
		{
			if (shader->materialUniforms[i].type == ShaderUniformType::Vec4)
			{
				colorUniformLocation = shader->materialUniforms[i].location;
			}
		}

		glDisable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);

		// Use shader
		glUseProgram(shader->driverId);

		for (unsigned int i = 0; i < primitiveCount; ++i)
		{
			Primitive* primitive = primitives + i;
			Mat4x4f mvp = viewProjection * primitive->transform;

			unsigned int meshId = this->meshIds[static_cast<unsigned int>(primitive->type)];
			const Mesh& mesh = rm->GetMesh(meshId);

			// Set color uniform
			glUniform4fv(colorUniformLocation, 1, primitive->color.ValuePointer());

			// Bind vertex array object
			glBindVertexArray(mesh.vertexArrayObject);

			// Set transform matrix uniform
			glUniformMatrix4fv(shader->uniformMatMVP, 1, GL_FALSE, mvp.ValuePointer());

			// Draw
			glDrawElements(mesh.primitiveMode, mesh.indexCount, mesh.indexElementType, nullptr);
		}

		// Clear primitive count
		primitiveCount = 0;
	}
}
Beispiel #5
0
// Produce the mesh for a truncated cone
void truncated_cone(const Mat4x4f& m,           // transformation matrix used for the points
                    float l,                    // length of truncated cone
                    float w0,                   // width at base
                    float w1,                   // width at top
                    vector<Vec3f>& triangles,   // triangles (out)
                    vector<Vec3f>& normals)     // normals (out)
{
    float len = sqrt(l*l + sqr(w0-w1));
    float a = l/len;
    float b = (w0-w1)/len;
    const int N = 10;
    for(int i=0;i<=N;++i)
    {
        float alpha = 2.0*M_PI*float(i)/N;
        Vec3f p0 = m.mul_3D_point(Vec3f(w0*cos(alpha), w0*sin(alpha), 0));
        Vec3f p1 = m.mul_3D_point(Vec3f(w1*cos(alpha), w1*sin(alpha), l));
        Vec3f n0 = m.mul_3D_vector(a*Vec3f(cos(alpha), sin(alpha), b));
        Vec3f n1 = n0;

        alpha = 2.0*M_PI*float(i+1)/N;
        Vec3f p2 = m.mul_3D_point(Vec3f(w0*cos(alpha), w0*sin(alpha), 0));
        Vec3f p3 = m.mul_3D_point(Vec3f(w1*cos(alpha), w1*sin(alpha), l));
        Vec3f n2 = m.mul_3D_vector(a*Vec3f(cos(alpha), sin(alpha), b));
        Vec3f n3 = n2;

        normals.push_back(n0);
        triangles.push_back(p0);

        normals.push_back(n1);
        triangles.push_back(p1);

        normals.push_back(n3);
        triangles.push_back(p3);

        normals.push_back(n3);
        triangles.push_back(p3);

        normals.push_back(n2);
        triangles.push_back(p2);

        normals.push_back(n0);
        triangles.push_back(p0);
    }
}
void CollisionGeometry::updateUniforms()
{
  mModelMatrixInverse = mModelMatrix;
  mModelMatrixInverse.invert();
  mModelMatrixInverseTransposed =mModelMatrixInverse;
  mModelMatrixInverseTransposed.transpose();
  // Compute the normal matrix
  Mat4x4f normalMatrix = mModelMatrix.getInverse().transpose();

  // Upload the new geometry and material properties to the GPU
  glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
  glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float) * 16,mModelMatrix.ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 16, sizeof(float) * 16,normalMatrix.ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 32, sizeof(float) * 1,&mShininess);
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 33, sizeof(float) * 1,&mLineWidth);
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 36, sizeof(float) * 4,mColor.ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 40, sizeof(float) * 4,mLineColor.ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 44, sizeof(float) * 4,mLightPosition[0].ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 48, sizeof(float) * 4,mLightPosition[1].ptr());
  glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float) * 52, sizeof(float) * 4,mLightPosition[2].ptr());
  glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
Beispiel #7
0
	bool LDILayer::convert_to_points(const Mat4x4f& itransf, 
																	 vector<PointRecord>& points)
	{
		int points_num = 0;
		for(int j=0;j<normal_buffer.get_ydim();++j)
			for(int i=0;i<normal_buffer.get_xdim();++i)
				{
					float z = depth_buffer(i,j);
					if(z > 0.0f && z < 1.0f)
						{
							Vec3f n = 2.0f*(normal_buffer(i,j) - Vec3f(0.5));
							float x = (i+0.5f)/float(normal_buffer.get_xdim());
							float y = (j+0.5f)/float(normal_buffer.get_ydim());
							Vec3f p = itransf.mul_3D_point(Vec3f(x,y,1-z));
							Vec4f c = colour_buffer(i,j);
							PointRecord r = {c,n,p};
							points.push_back(r);
							++points_num;
						}
				}
		return points_num>0;
	}
Beispiel #8
0
  void mesh(vector<MyVertex*> inv, 
	    vector<MyPolygon*> inp, 
	    vector<MyVertex*> &outv, 
	    vector<MyPolygon*> &outp, 
	    float _size, float lightsize) {
		
    for (int i=0;i<inp.size();i++) {

      float size = _size;
			
      int vertices = inp[i]->vertices;
      
      // setup basis
      
      Vec3f opoint[4];
      
      {
	for (int j=0;j<vertices;j++) {
	  opoint[j] = inv[inp[i]->vertex[j]]->position;
	}
      }		
      
      Vec3f basisu = opoint[1] - opoint[0];
      Vec3f basisv = opoint[vertices-1] - opoint[0];
      
      basisu.normalize();
      basisv.normalize();
			
      Vec3f basisw = cross(basisu, basisv);
      Vec3f newbasisv = cross(basisw, basisu);

      Vec3f normal = basisw;
      normal.normalize();
				
      Mat4x4f mat = identity_Mat4x4f();
      
      identity_Mat4x4f();

      { for (int q=0;q<3;q++) {	mat[q][0] = basisu[q]; } }
      { for (int q=0;q<3;q++) {	mat[q][1] = newbasisv[q]; } }
      { for (int q=0;q<3;q++) {	mat[q][2] = basisw[q]; } }
      
      Mat4x4f imat = invert(mat);

      Vec3f point[4];
      
      // transform to 2D and find AABB
			
      float minx, miny, maxx, maxy;
      minx = miny = +1e+30f;
      maxx = maxy = -1e+30f;
				
      {
	for (int j=0;j<vertices;j++) {
	  
	  point[j] = imat.mul_3D_point(opoint[j]);
	  
	  if (point[j][0] < minx ) minx = point[j][0];
	  if (point[j][0] > maxx ) maxx = point[j][0];

	  if (point[j][1] < miny ) miny = point[j][1];
	  if (point[j][1] > maxy ) maxy = point[j][1];
	  
	}
      }

      // calculate imaginary "texture coordinates"
      
      int inverts = vertices;
      int outverts=0;
			
      int ymin, xmin, xmax, ymax;

      int max_subdivx = 10;
      int max_subdivy = 10;
			
      Vec3f crapx = opoint[1] - opoint[0];
      Vec3f crapy = opoint[vertices-1] - opoint[0];		
			
      if (0 != inp[i]->emissive.length()) {
	size = lightsize;
      }
			
      max_subdivx = (int)( crapy.length() / size +0.5f);
      max_subdivy = (int)( crapx.length() / size +0.5f);

      xmin = ymin = 0;
      xmax = max_subdivx;		
      ymax = max_subdivy;		
			
      Vec3f unclipped[10];  // unclipped polygon
      Vec3f clipped[10];

      float scalex = (1.0f/(maxx-minx));
      float scaley = (1.0f/(maxy-miny));
			
      {
	for (int j=0;j<vertices;j++) {				
	  unclipped[j][0] = (point[j][0] - minx) * scalex;
	  unclipped[j][1] = (point[j][1] - miny) * scaley;
	  unclipped[j][2] = point[j][2] ;
	  
	}
      }		
									
      // adjust bounding box (just to be sure every element is accounted for )
      ymin--; if (ymin<0) ymin = 0;
      xmin--; if (xmin<0) xmin = 0;
      xmax++; if (xmax>max_subdivx) xmax = max_subdivx; if (xmax<=0) xmax=1;
      ymax++; if (ymax>max_subdivy) ymax = max_subdivy; if (ymax<=0) ymax=1;
      
      Vec3f emissive = inp[i]->emissive;
      Vec3f diffuse  = inp[i]->diffuse;
      
      {
				
	MyPolygon* p;
	
	int vertexoffset = outv.size()-1; 
	if (vertexoffset<0) vertexoffset=0;
	
	for (int i=ymin;i<ymax;i++) {
	  for (int j=xmin;j<xmax;j++) {					
	    
	    Vec3f texel[10];  // texel boundary
	    Vec3f* pin = texel;
	    
	    float deltax = 1  *  1.0f/(float)max_subdivy;
	    float deltay = 1  *  1.0f/(float)max_subdivx;
	    float xx= 1  *  (float)i/(float)max_subdivy;
	    float yy= 1  *  (float)j/(float)max_subdivx;
	    
	    *pin++ = Vec3f(xx, yy, unclipped[0][2]);
	    *pin++ = Vec3f(xx+deltax,yy, unclipped[0][2]);
	    *pin++ = Vec3f(xx+deltax,yy+deltay, unclipped[0][2]);
	    *pin++ = Vec3f(xx,yy+deltay, unclipped[0][2]);
							
	    SutherlandHodgmanClipper clipper;
	    clipper.ClipToMyPolygon(unclipped, clipped, inverts, &outverts, texel, 4);
	    
	    // create polygon & vertices 
	    
	    p = NULL;
	    int verts = outverts;
	    Vec3f* vpoly = clipped;
	    int first=1;							
	    MyPolygonSplitter psplit;	
	    
	    if (outverts) while (true) {		
	      
	      if (outverts>4) {	// larger polygons
		
		Vec3f A = clipped[0] - clipped[2];
		Vec3f B = clipped[1] - clipped[3];									

		float a = A.length();
		float b = B.length();
		
		cout << a << "," << b << endl;
		
		if (a>=b-b && a<=b+b && outverts==4) {  // check if square quad 
		  first = -1;
		} else {			// split non-square quad into triangles									
		  if (first) psplit.Split(clipped, outverts);
		  first=0;
		  vpoly = psplit.NextTriangle();
		  verts = 3;										
		  if (!vpoly) break;
		}
		
	      } else first = -1;	
	      
	      p = new MyPolygon();
	      p->diffuse = Vec3f(-1,-1,-1);
	      
	      for (int q=0;q<verts;q++) {
		
		vpoly[q][0] = (((vpoly[q][0]/scalex)) + minx);
		vpoly[q][1] = (((vpoly[q][1]/scaley)) + miny);
		vpoly[q] = mat.mul_3D_point(vpoly[q]);	// transform back to 3D
		
#define EQ(a,b) (a>=b-0.001f && a<=b+0.001f)
		
		int found = -1;
		for(int i=vertexoffset;i<outv.size();i++) {
		  if (EQ(outv[i]->position[0],vpoly[q][0]) && 
		      EQ(outv[i]->position[1],vpoly[q][1]) && 
		      EQ(outv[i]->position[2],vpoly[q][2]) ) {
		    found = i;
		    break;
		  }
		}
		
		if (-1!=found) {
		  p->vertex[q] = found;
		} else {
		  MyVertex* v = new MyVertex();
		  v->position = vpoly[q];
		  p->vertex[q] = outv.size();
		  outv.push_back(v);
		}
		
	      }
	      
	      
	      Vec3f center;
	      float area = 0;				
	      
	      calcMyPolygonAreaAndCenter(vpoly, verts, area, center);
	      
	      if (area>0.001f) outp.push_back(p);
	      else p=NULL;
	      
	      if (p) {
		
		p->center     = center;
		p->area       = area;
		p->normal     = normal;
		p->rad        = emissive;
		p->diffuse    = diffuse;
		p->unshot_rad = p->rad;
		p->color	  = diffuse;
		p->vertices   = verts;

        /*
        if( emissive[0] > 0 || emissive[1] > 0 || emissive[2] > 0)
		cerr << " emissive : " << emissive <<
        " area : " << area << endl;
        */

	    }
	      
	      if (-1==first) break;
	      
	      
	    } // end while (true)
	    
	  } // end for (int j=xmin;j<xmax;j++) 

	}	// end for (int i=ymin;i<ymax;i++) 
	
      }
      
    } // end for (int i=0;i<inp.size();i++)
    
  }
Beispiel #9
0
int main(int argc, char** argv)
{
    bool normalize = false;
    bool flip = false;
    bool wnormals = false;
    bool rnormals = false;
    bool rtexcoords = false;
    bool closemesh = false;
    float closedist = 0.0f;
    float mergedist = -1.0f;
    Vec3f translation;
    Vec3f rotation;
    Vec3f scale(1,1,1);
    float dilate = 0.0f;
    int tesselate = 0;
    bool sphere = false;
    bool dist = false;
    int res = 16;
    int rx=0,ry=0,rz=0;
    float border = 0.25f;
    float vsize = 0.0f;
    ftl::CmdLine cmd("Usage: meshconv [options] mesh.input [mesh.output]");
    cmd.opt("normalize",'n',"transform points so that the center is at <0,0,0> and the max coodinate is 1",&normalize);
    cmd.opt("flip",'f',"flip normals",&flip);
    cmd.opt("wnormals",'N',"force writing of normals",&wnormals);
    cmd.opt("rnormals",'O',"remove normals",&rnormals);
    cmd.opt("rtexcoords",'T',"remove texcoords",&rtexcoords);
    cmd.opt("close",'c',"close mesh",&closemesh);
    cmd.opt("close2",'C',"close mesh creating intermediate vertices no further appart than given dist",&closedist);
    cmd.opt("merge",'m',"merge vertices closer than the given distance",&mergedist);
    cmd.opt("translate",'t',"translate the mesh",&translation);
    cmd.opt("rotate",'r',"rotate the mesh using euler angles in degree",&rotation);
    cmd.opt("scale",'s',"scale the mesh using 3 coefficients",&scale);
    cmd.opt("dilate",'d',"dilate (i.e. displace vertices of the given distance along their normals)",&dilate);
    cmd.opt("tesselate",'a',"tesselate (split each edge in 2 resursivly n times)",&tesselate);
    cmd.opt("sphere",'S',"consider the mesh as a sphere for tesselation",&sphere);
    cmd.opt("dist",'D',"compute distance field",&dist);
    cmd.opt("res",'R',"resolution of distance field",&res);
    cmd.opt("rx",'X',"X resolution of distance field",&rx);
    cmd.opt("ry",'Y',"Y resolution of distance field",&ry);
    cmd.opt("rz",'Z',"Z resolution of distance field",&rz);
    cmd.opt("vsize",'V',"size of each voxel in distance field",&vsize);
    cmd.opt("border",'B',"distance field border size relative to the object's BBox size (or negative for exact size)",&border);
    bool error=false;
    if (!cmd.parse(argc,argv,&error))
        return error?1:0;

    if (cmd.args.size()<1 || cmd.args.size()>2)
    {
        std::cerr << cmd.help() << std::endl;
        return 1;
    }

    std::string file_in = cmd.args[0];
    std::string file_out;
    if (cmd.args.size()>=2) file_out = cmd.args[1];

    Mesh obj;

    if (!obj.load(file_in.c_str()))
    {
        std::cerr << "Failed to read "<<file_in<<std::endl;
        return 1;
    }

    if (normalize)
    {
        BBox bb = obj.calcBBox();
        std::cout << "Mesh bbox="<<bb<<std::endl;
        std::cout << "Normalizing mesh..."<<std::endl;
        float size = 0;
        for (int i=0; i<3; i++)
        {
            float d = bb.b[i]-bb.a[i];
            if (d>size) size=d;
        }
        Vec3f center = (bb.a+bb.b)*0.5;
        float sc = 2/size;
        Mat4x4f m; m.identity();
        m(0,0)=sc; m(0,3) = -center[0]*sc;
        m(1,1)=sc; m(1,3) = -center[1]*sc;
        m(2,2)=sc; m(2,3) = -center[2]*sc;
        for (int i=0; i<obj.nbp(); i++)
            obj.PP(i) = transform(m,obj.getPP(i));
    }

    if (scale != Vec3f(1,1,1))
    {
        std::cout << "Scaling mesh..."<<std::endl;
        for (int i=0; i<obj.nbp(); i++)
        {
            Vec3f p = obj.getPP(i);
            p[0] *= scale[0];
            p[1] *= scale[1];
            p[2] *= scale[2];
            obj.PP(i) = p;
        }
    }

    Mat4x4f xform;
    bool hasXForm = false;
    xform.identity();

    if (rotation != Vec3f(0,0,0))
    {
        std::cout << "Rotating mesh..."<<std::endl;
        Mat3x3f mat;
        Quat qx,qy,qz;
        qx.fromDegreeAngAxis(rotation[0],Vec3f(1,0,0));
        qy.fromDegreeAngAxis(rotation[1],Vec3f(0,1,0));
        qz.fromDegreeAngAxis(rotation[2],Vec3f(0,0,1));
        Quat q = qx*qy*qz;
        q.toMatrix(&mat);
        std::cout << "mat = "<<mat<<std::endl;
        for (int i=0; i<obj.nbp(); i++)
        {
            obj.PP(i) = mat*obj.getPP(i);
            obj.PN(i) = mat*obj.getPN(i);
        }
        hasXForm = true;
        xform = mat;
    }

    if (translation != Vec3f(0,0,0))
    {
        std::cout << "Translating mesh..."<<std::endl;
        for (int i=0; i<obj.nbp(); i++)
        {
            obj.PP(i) = obj.getPP(i) + translation;
        }
        hasXForm = true;
        xform[0][3] = translation[0];
        xform[1][3] = translation[1];
        xform[2][3] = translation[2];
    }

    if (obj.distmap && hasXForm)
    {
        //Mat4x4f m; m.invert(xform);
        std::cout << "distmap mat = "<<xform <<" * " << obj.distmap->mat<<" = ";
        obj.distmap->mat = xform * obj.distmap->mat;
        std::cout << obj.distmap->mat<<std::endl;
    }
    {
        BBox bb = obj.calcBBox();
        std::cout << "Mesh bbox = "<<bb<<std::endl;
        std::cout << "Mesh center and radius = "<<(bb.a+bb.b)*0.5<<"  "<<(bb.b-bb.a)*0.5 << std::endl;
    }
    if (mergedist >= 0.0f)
    {
        std::cout << "Merging vertices closer than " << mergedist <<std::endl;
        obj.mergeVertices(mergedist);
    }
    if (flip)
    {
        std::cout << "Flipping mesh..."<<std::endl;
        obj.flipAll();
        //obj.calcFlip();
    }
    if (closemesh || closedist != 0.0f)
    {
        bool closed = obj.isClosed();
        std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
        if (!closed)
        {
            obj.calcFlip();
            std::cout << "Closing mesh..."<<std::endl;
            if (closedist != 0.0f)
            {
                obj.closeDist(closedist);
            }
            else //if (closemesh)
            {
                obj.close();
            }
            std::cout << "Mesh is "<<(obj.isClosed()?"":"NOT ")<<"closed."<<std::endl;

        }
    }

    if (dilate != 0.0f)
        obj.dilate(dilate);

    if (tesselate > 0 || sphere)
    {
        std::cout << "Tesselating mesh..."<<std::endl;
        tesselateMesh(obj, tesselate, sphere);
    }

    if (dist)
    {
        if (!rx) rx = res;
        if (!ry) ry = res;
        if (!rz) rz = res;
        std::cout << "Flipping mesh..."<<std::endl;
        obj.calcFlip();
        obj.calcEdges();
        bool closed = obj.isClosed();
        std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
        if (!closed)
        {
            std::cout << "Closing mesh..."<<std::endl;
            obj.close();
            std::cout << "Mesh is "<<(obj.isClosed()?"":"NOT ")<<"closed."<<std::endl;
        }
        BBox bb = obj.calcBBox();
        float bsize = (border<0 ? -border : bb.size()*border);
        Vec3f bbsize = bb.b-bb.a;
        bbsize[0] += 2*bsize;
        bbsize[1] += 2*bsize;
        bbsize[2] += 2*bsize;
        if (vsize > 0)
        {
            rx = (int)ceilf(bbsize[0]/vsize);
            ry = (int)ceilf(bbsize[1]/vsize);
            rz = (int)ceilf(bbsize[2]/vsize);
        }
        std::cout << "Computing "<<rx<<'x'<<ry<<'x'<<rz<<" DistMap..."<<std::endl;
        obj.calcDistMap(rx,ry,rz,bsize);
    }


    if (wnormals)
        obj.setAttrib(Mesh::MESH_POINTS_NORMAL,true);
    if (rnormals)
        obj.setAttrib(Mesh::MESH_POINTS_NORMAL,false);
    if (rtexcoords)
        obj.setAttrib(Mesh::MESH_POINTS_TEXCOORD,false);
    if (!file_out.empty())
    {
        std::cout << "Saving result..."<<std::endl;
        obj.save(file_out.c_str());
    }
    return 0;
}
Beispiel #10
0
int main(int argc, char** argv)
{

  flowvr::InputPort pRotX("rotX");
  flowvr::InputPort pRotY("rotY");
  flowvr::InputPort pTransX("transX");
  flowvr::InputPort pTransY("transY");
  flowvr::InputPort pZoom("zoom");
  SceneOutputPort pOut("scene");
  flowvr::OutputPort pOutMat("matrix");
  flowvr::OutputPort pTerrain("terrain");
  flowvr::OutputPort pOutFluid("fluidpos");
  flowvr::StampInfo  terrainN("N",flowvr::TypeArray::create(2,flowvr::TypeInt::create()));
  flowvr::StampInfo  terrainP("P",flowvr::TypeArray::create(2,flowvr::TypeFloat::create()));
  flowvr::StampInfo  terrainS("S",flowvr::TypeArray::create(2,flowvr::TypeFloat::create()));
  flowvr::StampInfo  terrainH("H",flowvr::TypeArray::create(2,flowvr::TypeFloat::create()));
  pTerrain.stamps->add(&terrainN);
  pTerrain.stamps->add(&terrainP);
  pTerrain.stamps->add(&terrainS);
  pTerrain.stamps->add(&terrainH);

  std::vector<flowvr::Port*> ports;
  ports.push_back(&pRotX);
  ports.push_back(&pRotY);
  ports.push_back(&pTransX);
  ports.push_back(&pTransY);
  ports.push_back(&pZoom);
  ports.push_back(&pOut);
  ports.push_back(&pOutMat);
  ports.push_back(&pOutFluid);
  ports.push_back(&pTerrain);

  flowvr::ModuleAPI* module = flowvr::initModule(ports);  
  if (module == NULL)
  {
    return 1;
  }

  flowvr::render::ChunkRenderWriter scene;

  ID idP = 0x300; //module->generateID();
  ID idT = 0x301; //module->generateID();
  ID idVB = 0x302; //module->generateID();
  ID idIB = 0x303; //module->generateID();
  ID idVS = 0x304; //module->generateID();
  ID idPS = 0x305; //module->generateID();

  std::cout << "idVS="<<idVS<<std::endl;
  std::cout << "idPS="<<idPS<<std::endl;

  std::string ftexture = "images/valley2.jpg";
  std::string fheight = "valley2.ter";
  if (argc>=2) ftexture = argv[1];
  if (argc>=3) fheight  = argv[2];
  int nx = 257; int ny = 257;

  TerragenTerrain terrain;
  if (!terrain.load(fheight))
  {
    module->close();
    return 2;
  }

  Vec3f position0;
  Vec3f position(-25,0,0);
  Vec3f rotation;
  float zoom = 1;

  if (cx >= terrain.nx) cx = terrain.nx/2;
  if (cy >= terrain.ny) cy = terrain.ny/2;
  if (cx-nx/2<0) nx = cx*2;
  if (cy-ny/2<0) ny = cy*2;
  if (cx-nx/2+nx>terrain.nx) nx = (terrain.nx-cx)*2-1;
  if (cy-ny/2+ny>terrain.ny) ny = (terrain.ny-cy)*2-1;

  terrain.scale = Vec3f(1.0f,1.0f,2.0f);
  //terrain.hbase -= 18.033f;
  terrain.hbase = -terrain.hscale*terrain.height[(cy)*terrain.nx+(cx-25)];

  std::cout << "Using data centered @ "<<cx<<"x"<<cy<<" size "<<nx<<"x"<<ny<<" scale "<<terrain.scale.x()<<"x"<<terrain.scale.y()<<"x"<<terrain.scale.z()<<" z="<<terrain.hbase<<"+h*"<<terrain.hscale<<std::endl;

  if (!scene.loadTexture(idT,ftexture))
    scene.addDefaultTexture(idT);

  int dataType[1] = { Type::Vec3s };

  short hmin = 0xffff;
  short hmax = 0;

  int xmin=0,xmax=1,ymin=0,ymax=1; // fluid interval

  {
    short* height = terrain.height+(cy-ny/2)*terrain.nx+(cx-nx/2);
    for (int y=0;y<ny;y++)
    {
      for (int x=0;x<nx;x++)
      {
	if (height[x] < hmin)
	{
	  hmin = height[x];
	  xmin=xmax=x;
	  ymin=ymax=y;
	}
	else if (height[x] == hmin)
	{
	  if (x<xmin) xmin=x; else if (x>xmax) xmax=x;
	  if (y<ymin) ymin=y; else if (y>ymax) ymax=y;
	}
	if (height[x] > hmax) hmax = height[x];
      }
      height+=terrain.nx;
    }
  }

  std::cout << "height min="<<hmin<<" max="<<hmax<<std::endl;

  ChunkVertexBuffer* vb = scene.addVertexBuffer(idVB, nx*ny, 1, dataType, BBox(Vec3f(0,0,hmin),Vec3f(nx-1,ny-1,hmax)));
  {
    Vec<3,short>* vertex = (Vec<3,short>*)vb->data();
    short* height = terrain.height+(cy-ny/2)*terrain.nx+(cx-nx/2);
    for (int y=0;y<ny;y++)
    {
      for (int x=0;x<nx;x++)
      {
	vertex->x() = x;
	vertex->y() = y;
	vertex->z() = height[x];
	++vertex;
      }
      height+=terrain.nx;
    }
  }

/*
  std::cout << "Primitive mode: QUAD\n";
  ChunkIndexBuffer* ib = scene.addIndexBuffer(idIB, 4*(nx-1)*(ny-1), Type::Int, ChunkIndexBuffer::Quad);
  {
    unsigned int* ind = (unsigned int*)ib->data();
    for (int y=0;y<ny-1;y++)
    {
      for (int x=0;x<nx-1;x++)
      {
	ind[0] = (y  )*nx+(x  );
	ind[1] = (y  )*nx+(x+1);
	ind[2] = (y+1)*nx+(x+1);
	ind[3] = (y+1)*nx+(x  );
	ind+=4;
      }
    }
  }
*/

/*
  std::cout << "Primitive mode: TRIANGLE STRIP\n";
  int restart = -1;
  ChunkIndexBuffer* ib = scene.addIndexBuffer(idIB, 2*(nx)*(ny-1)+(ny-2), Type::Int, ChunkIndexBuffer::TriangleStrip);
  ib->restart = restart;
  {
    unsigned int* ind = (unsigned int*)ib->data();
    for (int y=0;y<ny-1;y++)
    {
      if (y)
	*(ind++) = (unsigned int)restart; // start a new strip
      for (int x=0;x<nx;x++)
      {
	ind[0] = (y  )*nx+(x  );
	ind[1] = (y+1)*nx+(x  );
	ind+=2;
      }
    }
  }
*/

  std::cout << "Primitive mode: TRIANGLE FAN\n";
  int restart = -1;
  int nindex = 
      ((nx-1)/2)*((ny-1)/2)*(10+1) // full circles
      +((nx&1)?0:((ny-1)/2)*(6+1)) // half circles if nx is even
      +((ny&1)?0:((nx-1)/2)*(6+1)) // half circles if ny is even
      +((nx&1 || ny&1)?0:   (4+1)) // final quad if both nx and ny are even
      -1; // last fan does not need a restart index
  ChunkIndexBuffer* ib = scene.addIndexBuffer(idIB, nindex, Type::Int, ChunkIndexBuffer::TriangleFan);
  ib->restart = restart;
  {
    unsigned int* ind = (unsigned int*)ib->data();
    unsigned int* start=ind;
    for (int y=1;y<ny;y+=2)
    {
      for (int x=1;x<nx;x+=2)
      {
	if (ind!=start)
	    *(ind++) = (unsigned int)restart; // start a new fan
	*(ind++) = (y  )*nx+(x  );
	if (y<ny-1)
	*(ind++) = (y+1)*nx+(x  );
	if (y<ny-1)
	*(ind++) = (y+1)*nx+(x-1);
	*(ind++) = (y  )*nx+(x-1);
	*(ind++) = (y-1)*nx+(x-1);
	*(ind++) = (y-1)*nx+(x  );
	if (x<nx-1)
	*(ind++) = (y-1)*nx+(x+1);
	if (x<nx-1)
	*(ind++) = (y  )*nx+(x+1);
	if (x<nx-1 && y<ny-1)
	*(ind++) = (y+1)*nx+(x+1);
	if (x<nx-1 && y<ny-1)
	*(ind++) = (y+1)*nx+(x  );
      }
    }
  }

  scene.loadVertexShader(idVS, "shaders/terrain_v.cg");
  scene.loadPixelShader(idPS, "shaders/terrain_p.cg");

  scene.addPrimitive(idP,"Terrain");
  //scene.addParam(idP, ChunkPrimParam::ORDER,"",0);
  scene.addParamID(idP, ChunkPrimParam::VSHADER,"",idVS);
  scene.addParamID(idP, ChunkPrimParam::PSHADER,"",idPS);
  scene.addParamID(idP, ChunkPrimParam::VBUFFER_ID,"position",idVB);
  scene.addParamID(idP, ChunkPrimParam::IBUFFER_ID,"",idIB);
  scene.addParamEnum(idP, ChunkPrimParam::PARAMVSHADER, "ModelViewProj", ChunkPrimParam::ModelViewProjection);
  scene.addParam(idP, ChunkPrimParam::PARAMVSHADER, "TextureScale", Vec2f(1.0f/nx,-1.0f/ny));
  scene.addParamID(idP, ChunkPrimParam::TEXTURE, "texture", idT);
  scene.addParam(idP,ChunkPrimParam::TRANSFORM_SCALE,"",Vec3f(terrain.scale.x(),terrain.scale.y(),terrain.hscale*terrain.scale.z()));
  scene.addParam(idP,ChunkPrimParam::TRANSFORM_POSITION,"",Vec3f(-nx/2*terrain.scale.x(),-ny/2*terrain.scale.y(),terrain.hbase*terrain.scale.z()));

  scene.put(&pOut);

  flowvr::MessageWrite mt;
  mt.data = module->alloc(nx*ny*sizeof(short));
  mt.stamps.write(terrainN[0],nx);
  mt.stamps.write(terrainN[1],ny);
  mt.stamps.write(terrainP[0],-nx/2*terrain.scale.x());
  mt.stamps.write(terrainP[1],-ny/2*terrain.scale.y());
  mt.stamps.write(terrainS[0],terrain.scale.x());
  mt.stamps.write(terrainS[1],terrain.scale.y());
  mt.stamps.write(terrainH[0],terrain.scale.z()*terrain.hbase);
  mt.stamps.write(terrainH[1],terrain.scale.z()*terrain.hscale);
  {
    short* height = terrain.height+(cy-ny/2)*terrain.nx+(cx-nx/2);
    for (int y=0;y<ny;y++)
    {
      memcpy(mt.data.getWrite<short>(y*nx*sizeof(short)), height, nx*sizeof(short));
      height+=terrain.nx;
    }
  }

  module->put(&pTerrain, mt);

  // Fluid position
  {

    short fluidh = hmin+(short)(0.3f/terrain.hscale);

    short* height = terrain.height+(cy-ny/2)*terrain.nx+(cx-nx/2);
    for (int y=0;y<ny;y++)
    {
      for (int x=0;x<nx;x++)
      {
	if (height[x] <= fluidh)
	{
	  if (x<xmin) xmin=x; else if (x>xmax) xmax=x;
	  if (y<ymin) ymin=y; else if (y>ymax) ymax=y;
	}
      }
      height+=terrain.nx;
    }

    std::cout << "Fluid pos: <"<<xmin<<','<<ymin<<">-<"<<xmax<<','<<ymax<<") h="<<fluidh<<std::endl;
    flowvr::MessageWrite m;
    m.data = module->alloc(sizeof(Mat4x4f));
    Mat4x4f& fluid = *m.data.getWrite<Mat4x4f>();
    fluid.identity();
    // Scale
    fluid[0][0] = (xmax-xmin+1)*terrain.scale.x();
    fluid[1][1] = (ymax-ymin+1)*terrain.scale.y();
    fluid[2][2] = terrain.scale.z();
    // Position
    fluid[0][3] = (xmin-nx/2-0.5f)*terrain.scale.x();
    fluid[1][3] = (ymin-ny/2-0.5f)*terrain.scale.y();
    fluid[2][3] = (terrain.hbase+fluidh*terrain.hscale)*terrain.scale.z();
    module->put(&pOutFluid,m);
  }

  module->wait();

  flowvr::BufferPool pool;

  if (pRotX.isConnected())
  {
    float rotSpeed = 0.01f;
    float speed = 0.04f;
    do
    {
      Vec3f depl;
      depl.x() = getSum(pTransX,position0.x(),speed);
      depl.y() = -getSum(pTransY,position0.y(),speed);
      getSum(pRotX,rotation.x(),rotSpeed);
      getSum(pRotY,rotation.y(),rotSpeed);
      get(pZoom,zoom);

      Mat3x3f mrot;
      Quat qx,qy,qz;
      qx.fromAngAxis(M_PI/2*rotation.x(),Vec3f(0,0,1));
      qy.fromAngAxis(M_PI/2*rotation.y(),Vec3f(1,0,0));
      qz.fromAngAxis(M_PI/2*rotation.z(),Vec3f(0,1,0));
      Quat q = qz*qy*qx;

      q.toMatrix(&mrot);

      Vec3f newPos = position+mrot*depl;
      newPos.z() = terrain.getHeight(newPos.x(), newPos.y()); //+(zoom+1);

      position = newPos;

      Mat3x3f xrot;
      qx.toMatrix(&xrot);

      Vec3f pcam = position+xrot*(Vec3f(0,-2,0)*(1+zoom))+Vec3f(0,0,1.5);
      float zTer = terrain.getHeight(pcam.x(), pcam.y())+1;
      if (zTer > pcam.z()) pcam.z()=zTer;

      Mat4x4f m;
      m.identity();
      m = mrot;
      m(0,3) = pcam[0];
      m(1,3) = pcam[1];
      m(2,3) = pcam[2];

      Mat4x4f mcam; mcam.identity();

      Mat3x3f rotcam;
      Quat qcam; qcam.fromAngAxis(-M_PI/2,Vec3f(1,0,0));
      qcam.toMatrix(&rotcam);

      mcam = rotcam;
      m = m*mcam;

      scene.addParam(ID_CAMERA,ChunkPrimParam::TRANSFORM,"",m);

      mrot.identity();
      m = mrot;
      m(0,3) = position[0];
      m(1,3) = position[1];
      m(2,3) = position[2];

      flowvr::MessageWrite msg;
      msg.data = pool.alloc(module,sizeof(Mat4x4f));
      *msg.data.getWrite<Mat4x4f>() = m;
      module->put(&pOutMat, msg);

      scene.put(&pOut);

    }
    while (module->wait());
  }

  module->close();

  return 0;
}