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