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