00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include "stdafx.h"
00027 #include "shapes/heightfield.h"
00028 #include "shapes/trianglemesh.h"
00029 #include "paramset.h"
00030 
00031 
00032 Heightfield::Heightfield(const Transform *o2w, const Transform *w2o,
00033         bool ro, int x, int y, const float *zs)
00034     : Shape(o2w, w2o, ro) {
00035     nx = x;
00036     ny = y;
00037     z = new float[nx*ny];
00038     memcpy(z, zs, nx*ny*sizeof(float));
00039 }
00040 
00041 
00042 Heightfield::~Heightfield() {
00043     delete[] z;
00044 }
00045 
00046 
00047 BBox Heightfield::ObjectBound() const {
00048     float minz = z[0], maxz = z[0];
00049     for (int i = 1; i < nx*ny; ++i) {
00050         if (z[i] < minz) minz = z[i];
00051         if (z[i] > maxz) maxz = z[i];
00052     }
00053     return BBox(Point(0,0,minz), Point(1,1,maxz));
00054 }
00055 
00056 
00057 bool Heightfield::CanIntersect() const {
00058     return false;
00059 }
00060 
00061 
00062 void Heightfield::Refine(vector<Reference<Shape> > &refined) const {
00063     int ntris = 2*(nx-1)*(ny-1);
00064     refined.reserve(ntris);
00065     int *verts = new int[3*ntris];
00066     Point *P = new Point[nx*ny];
00067     float *uvs = new float[2*nx*ny];
00068     int nverts = nx*ny;
00069     int x, y;
00070     
00071     int pos = 0;
00072     for (y = 0; y < ny; ++y) {
00073         for (x = 0; x < nx; ++x) {
00074             P[pos].x = uvs[2*pos]   = (float)x / (float)(nx-1);
00075             P[pos].y = uvs[2*pos+1] = (float)y / (float)(ny-1);
00076             P[pos].z = z[pos];
00077             ++pos;
00078         }
00079     }
00080 
00081     
00082     int *vp = verts;
00083     for (y = 0; y < ny-1; ++y) {
00084         for (x = 0; x < nx-1; ++x) {
00085 #define VERT(x,y) ((x)+(y)*nx)
00086             *vp++ = VERT(x, y);
00087             *vp++ = VERT(x+1, y);
00088             *vp++ = VERT(x+1, y+1);
00089     
00090             *vp++ = VERT(x, y);
00091             *vp++ = VERT(x+1, y+1);
00092             *vp++ = VERT(x, y+1);
00093         }
00094 #undef VERT
00095     }
00096     ParamSet paramSet;
00097     paramSet.AddInt("indices", verts, 3*ntris);
00098     paramSet.AddFloat("uv", uvs, 2 * nverts);
00099     paramSet.AddPoint("P", P, nverts);
00100     refined.push_back(CreateTriangleMeshShape(ObjectToWorld, WorldToObject, ReverseOrientation, paramSet));
00101     delete[] P;
00102     delete[] uvs;
00103     delete[] verts;
00104 }
00105 
00106 
00107 Heightfield *CreateHeightfieldShape(const Transform *o2w, const Transform *w2o,
00108         bool reverseOrientation, const ParamSet ¶ms) {
00109     int nu = params.FindOneInt("nu", -1);
00110     int nv = params.FindOneInt("nv", -1);
00111     int nitems;
00112     const float *Pz = params.FindFloat("Pz", &nitems);
00113     Assert(nitems == nu*nv);
00114     Assert(nu != -1 && nv != -1 && Pz != NULL);
00115     return new Heightfield(o2w, w2o, reverseOrientation, nu, nv, Pz);
00116 }
00117 
00118