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); } } }
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(); }
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; } }
// 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); }
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; }
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++) }
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; }
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; }