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 #include "volume.h"
00026
00027 class VolumeGrid : public DensityRegion {
00028 public:
00029
00030 VolumeGrid(const Spectrum &sa, const Spectrum &ss, float gg,
00031 const Spectrum &emit, const BBox &e, const Transform &v2w,
00032 int nx, int ny, int nz, const float *d);
00033 ~VolumeGrid() { delete[] density; }
00034 BBox WorldBound() const { return WorldToVolume.GetInverse()(extent); }
00035 bool IntersectP(const Ray &r, float *t0, float *t1) const {
00036 Ray ray = WorldToVolume(r);
00037 return extent.IntersectP(ray, t0, t1);
00038 }
00039 float Density(const Point &Pobj) const;
00040 float D(int x, int y, int z) const {
00041 x = Clamp(x, 0, nx-1);
00042 y = Clamp(y, 0, ny-1);
00043 z = Clamp(z, 0, nz-1);
00044 return density[z*nx*ny + y*nx + x];
00045 }
00046 private:
00047
00048 float *density;
00049 const int nx, ny, nz;
00050 const BBox extent;
00051 };
00052
00053 VolumeGrid::VolumeGrid(const Spectrum &sa,
00054 const Spectrum &ss, float gg,
00055 const Spectrum &emit, const BBox &e,
00056 const Transform &v2w,
00057 int x, int y, int z, const float *d)
00058 : DensityRegion(sa, ss, gg, emit, v2w),
00059 nx(x), ny(y), nz(z), extent(e) {
00060 density = new float[nx*ny*nz];
00061 memcpy(density, d, nx*ny*nz*sizeof(float));
00062 }
00063 float VolumeGrid::Density(const Point &Pobj) const {
00064 if (!extent.Inside(Pobj)) return 0;
00065
00066 float voxx = (Pobj.x - extent.pMin.x) /
00067 (extent.pMax.x - extent.pMin.x) * nx - .5f;
00068 float voxy = (Pobj.y - extent.pMin.y) /
00069 (extent.pMax.y - extent.pMin.y) * ny - .5f;
00070 float voxz = (Pobj.z - extent.pMin.z) /
00071 (extent.pMax.z - extent.pMin.z) * nz - .5f;
00072 int vx = Floor2Int(voxx);
00073 int vy = Floor2Int(voxy);
00074 int vz = Floor2Int(voxz);
00075 float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz;
00076
00077 float d00 = Lerp(dx, D(vx, vy, vz), D(vx+1, vy, vz));
00078 float d10 = Lerp(dx, D(vx, vy+1, vz), D(vx+1, vy+1, vz));
00079 float d01 = Lerp(dx, D(vx, vy, vz+1), D(vx+1, vy, vz+1));
00080 float d11 = Lerp(dx, D(vx, vy+1, vz+1),D(vx+1, vy+1, vz+1));
00081 float d0 = Lerp(dy, d00, d10);
00082 float d1 = Lerp(dy, d01, d11);
00083 return Lerp(dz, d0, d1);
00084 }
00085 extern "C" DLLEXPORT VolumeRegion *CreateVolumeRegion(const Transform &volume2world,
00086 const ParamSet ¶ms) {
00087
00088 Spectrum sigma_a = params.FindOneSpectrum("sigma_a", 0.);
00089 Spectrum sigma_s = params.FindOneSpectrum("sigma_s", 0.);
00090 float g = params.FindOneFloat("g", 0.);
00091 Spectrum Le = params.FindOneSpectrum("Le", 0.);
00092 Point p0 = params.FindOnePoint("p0", Point(0,0,0));
00093 Point p1 = params.FindOnePoint("p1", Point(1,1,1));
00094 int nitems;
00095 const float *data = params.FindFloat("density", &nitems);
00096 if (!data) {
00097 Error("No \"density\" values provided for volume grid?");
00098 return NULL;
00099 }
00100 int nx = params.FindOneInt("nx", 1);
00101 int ny = params.FindOneInt("ny", 1);
00102 int nz = params.FindOneInt("nz", 1);
00103 if (nitems != nx*ny*nz) {
00104 Error("VolumeGrid has %d density values but nx*ny*nz = %d",
00105 nitems, nx*ny*nz);
00106 return NULL;
00107 }
00108 return new VolumeGrid(sigma_a, sigma_s, g, Le, BBox(p0, p1),
00109 volume2world, nx, ny, nz, data);
00110 }