Last active
August 12, 2024 16:29
-
-
Save ashwanirathee/50d4a5c27fdbeed688b0a32a8186c3c5 to your computer and use it in GitHub Desktop.
VTK Notes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vtkCamera.h> | |
#include <vtkColorTransferFunction.h> | |
#include <vtkFixedPointVolumeRayCastMapper.h> | |
#include <vtkNamedColors.h> | |
#include <vtkNew.h> | |
#include <vtkPiecewiseFunction.h> | |
#include <vtkRenderWindow.h> | |
#include <vtkRenderWindowInteractor.h> | |
#include <vtkRenderer.h> | |
#include <vtkVolume.h> | |
#include <vtkVolumeProperty.h> | |
#include <vtkImageData.h> | |
#include <vtkFloatArray.h> | |
#include <vtkPointData.h> | |
#include <vtkCommand.h> | |
#include <cstdlib> // For rand() | |
#include <ctime> // For time() | |
#include <math.h> | |
#include <vtkSmartPointer.h> | |
#include <vtkVolume.h> | |
#include <vtkRenderer.h> | |
#include <vtkRenderWindow.h> | |
#include <vtkRenderWindowInteractor.h> | |
#include <vtkOutlineFilter.h> | |
#include <vtkPolyDataMapper.h> | |
#include <vtkActor.h> | |
#include <vtkNamedColors.h> | |
#include <vtkCamera.h> | |
#include <vtkCommand.h> | |
#include <vtkProperty.h> | |
#include <algorithm> | |
#include <vtkMultiBlockDataSet.h> | |
#include <vtkMultiBlockVolumeMapper.h> | |
#include <random> | |
using namespace std; | |
int N = 50; | |
#define IX(x, y, z) ((x) + (y) * N + (z) * N * N) | |
struct FluidCube { | |
int size; | |
float dt; | |
float diff; | |
float visc; | |
float *s; | |
float *density; | |
float *Vx; | |
float *Vy; | |
float *Vz; | |
float *Vx0; | |
float *Vy0; | |
float *Vz0; | |
}; | |
FluidCube *FluidCubeCreate(int size, float diffusion, float viscosity, float dt) | |
{ | |
FluidCube *cube = static_cast<FluidCube*>(malloc(sizeof(*cube))); | |
int N = size; | |
cube->size = size; | |
cube->dt = dt; | |
cube->diff = diffusion; | |
cube->visc = viscosity; | |
cube->s = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->density = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vx = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vy = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vz = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vx0 = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vy0 = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
cube->Vz0 = static_cast<float*>(calloc(N * N * N, sizeof(float))); | |
return cube; | |
} | |
void FluidCubeFree(FluidCube *cube) | |
{ | |
free(cube->s); | |
free(cube->density); | |
free(cube->Vx); | |
free(cube->Vy); | |
free(cube->Vz); | |
free(cube->Vx0); | |
free(cube->Vy0); | |
free(cube->Vz0); | |
free(cube); | |
} | |
static void set_bnd(int b, float *x, int N) | |
{ | |
for(int j = 1; j < N - 1; j++) { | |
for(int i = 1; i < N - 1; i++) { | |
x[IX(i, j, 0 )] = b == 3 ? -x[IX(i, j, 1 )] : x[IX(i, j, 1 )]; | |
x[IX(i, j, N-1)] = b == 3 ? -x[IX(i, j, N-2)] : x[IX(i, j, N-2)]; | |
} | |
} | |
for(int k = 1; k < N - 1; k++) { | |
for(int i = 1; i < N - 1; i++) { | |
x[IX(i, 0 , k)] = b == 2 ? -x[IX(i, 1 , k)] : x[IX(i, 1 , k)]; | |
x[IX(i, N-1, k)] = b == 2 ? -x[IX(i, N-2, k)] : x[IX(i, N-2, k)]; | |
} | |
} | |
for(int k = 1; k < N - 1; k++) { | |
for(int j = 1; j < N - 1; j++) { | |
x[IX(0 , j, k)] = b == 1 ? -x[IX(1 , j, k)] : x[IX(1 , j, k)]; | |
x[IX(N-1, j, k)] = b == 1 ? -x[IX(N-2, j, k)] : x[IX(N-2, j, k)]; | |
} | |
} | |
x[IX(0, 0, 0)] = 0.33f * (x[IX(1, 0, 0)] | |
+ x[IX(0, 1, 0)] | |
+ x[IX(0, 0, 1)]); | |
x[IX(0, N-1, 0)] = 0.33f * (x[IX(1, N-1, 0)] | |
+ x[IX(0, N-2, 0)] | |
+ x[IX(0, N-1, 1)]); | |
x[IX(0, 0, N-1)] = 0.33f * (x[IX(1, 0, N-1)] | |
+ x[IX(0, 1, N-1)] | |
+ x[IX(0, 0, N)]); | |
x[IX(0, N-1, N-1)] = 0.33f * (x[IX(1, N-1, N-1)] | |
+ x[IX(0, N-2, N-1)] | |
+ x[IX(0, N-1, N-2)]); | |
x[IX(N-1, 0, 0)] = 0.33f * (x[IX(N-2, 0, 0)] | |
+ x[IX(N-1, 1, 0)] | |
+ x[IX(N-1, 0, 1)]); | |
x[IX(N-1, N-1, 0)] = 0.33f * (x[IX(N-2, N-1, 0)] | |
+ x[IX(N-1, N-2, 0)] | |
+ x[IX(N-1, N-1, 1)]); | |
x[IX(N-1, 0, N-1)] = 0.33f * (x[IX(N-2, 0, N-1)] | |
+ x[IX(N-1, 1, N-1)] | |
+ x[IX(N-1, 0, N-2)]); | |
x[IX(N-1, N-1, N-1)] = 0.33f * (x[IX(N-2, N-1, N-1)] | |
+ x[IX(N-1, N-2, N-1)] | |
+ x[IX(N-1, N-1, N-2)]); | |
} | |
static void lin_solve(int b, float *x, float *x0, float a, float c, int iter, int N) | |
{ | |
float cRecip = 1.0 / c; | |
for (int k = 0; k < iter; k++) { | |
for (int m = 1; m < N - 1; m++) { | |
for (int j = 1; j < N - 1; j++) { | |
for (int i = 1; i < N - 1; i++) { | |
x[IX(i, j, m)] = | |
(x0[IX(i, j, m)] | |
+ a*( x[IX(i+1, j , m )] | |
+x[IX(i-1, j , m )] | |
+x[IX(i , j+1, m )] | |
+x[IX(i , j-1, m )] | |
+x[IX(i , j , m+1)] | |
+x[IX(i , j , m-1)] | |
)) * cRecip; | |
} | |
} | |
} | |
set_bnd(b, x, N); | |
} | |
} | |
static void diffuse (int b, float *x, float *x0, float diff, float dt, int iter, int N) | |
{ | |
float a = dt * diff * (N - 2) * (N - 2); | |
lin_solve(b, x, x0, a, 1 + 6 * a, iter, N); | |
} | |
static void advect(int b, float *d, float *d0, float *velocX, float *velocY, float *velocZ, float dt, int N) | |
{ | |
float i0, i1, j0, j1, k0, k1; | |
float dtx = dt * (N - 2); | |
float dty = dt * (N - 2); | |
float dtz = dt * (N - 2); | |
float s0, s1, t0, t1, u0, u1; | |
float tmp1, tmp2, tmp3, x, y, z; | |
float Nfloat = N; | |
float ifloat, jfloat, kfloat; | |
int i, j, k; | |
for(k = 1, kfloat = 1; k < N - 1; k++, kfloat++) { | |
for(j = 1, jfloat = 1; j < N - 1; j++, jfloat++) { | |
for(i = 1, ifloat = 1; i < N - 1; i++, ifloat++) { | |
tmp1 = dtx * velocX[IX(i, j, k)]; | |
tmp2 = dty * velocY[IX(i, j, k)]; | |
tmp3 = dtz * velocZ[IX(i, j, k)]; | |
x = ifloat - tmp1; | |
y = jfloat - tmp2; | |
z = kfloat - tmp3; | |
if(x < 0.5f) x = 0.5f; | |
if(x > Nfloat + 0.5f) x = Nfloat + 0.5f; | |
i0 = floorf(x); | |
i1 = i0 + 1.0f; | |
if(y < 0.5f) y = 0.5f; | |
if(y > Nfloat + 0.5f) y = Nfloat + 0.5f; | |
j0 = floorf(y); | |
j1 = j0 + 1.0f; | |
if(z < 0.5f) z = 0.5f; | |
if(z > Nfloat + 0.5f) z = Nfloat + 0.5f; | |
k0 = floorf(z); | |
k1 = k0 + 1.0f; | |
s1 = x - i0; | |
s0 = 1.0f - s1; | |
t1 = y - j0; | |
t0 = 1.0f - t1; | |
u1 = z - k0; | |
u0 = 1.0f - u1; | |
int i0i = i0; | |
int i1i = i1; | |
int j0i = j0; | |
int j1i = j1; | |
int k0i = k0; | |
int k1i = k1; | |
d[IX(i, j, k)] = | |
s0 * ( t0 * (u0 * d0[IX(i0i, j0i, k0i)] | |
+u1 * d0[IX(i0i, j0i, k1i)]) | |
+( t1 * (u0 * d0[IX(i0i, j1i, k0i)] | |
+u1 * d0[IX(i0i, j1i, k1i)]))) | |
+s1 * ( t0 * (u0 * d0[IX(i1i, j0i, k0i)] | |
+u1 * d0[IX(i1i, j0i, k1i)]) | |
+( t1 * (u0 * d0[IX(i1i, j1i, k0i)] | |
+u1 * d0[IX(i1i, j1i, k1i)]))); | |
} | |
} | |
} | |
set_bnd(b, d, N); | |
} | |
static void project(float *velocX, float *velocY, float *velocZ, float *p, float *div, int iter, int N) | |
{ | |
for (int k = 1; k < N - 1; k++) { | |
for (int j = 1; j < N - 1; j++) { | |
for (int i = 1; i < N - 1; i++) { | |
div[IX(i, j, k)] = -0.5f*( | |
velocX[IX(i+1, j , k )] | |
-velocX[IX(i-1, j , k )] | |
+velocY[IX(i , j+1, k )] | |
-velocY[IX(i , j-1, k )] | |
+velocZ[IX(i , j , k+1)] | |
-velocZ[IX(i , j , k-1)] | |
)/N; | |
p[IX(i, j, k)] = 0; | |
} | |
} | |
} | |
set_bnd(0, div, N); | |
set_bnd(0, p, N); | |
lin_solve(0, p, div, 1, 6, iter, N); | |
for (int k = 1; k < N - 1; k++) { | |
for (int j = 1; j < N - 1; j++) { | |
for (int i = 1; i < N - 1; i++) { | |
velocX[IX(i, j, k)] -= 0.5f * ( p[IX(i+1, j, k)] | |
-p[IX(i-1, j, k)]) * N; | |
velocY[IX(i, j, k)] -= 0.5f * ( p[IX(i, j+1, k)] | |
-p[IX(i, j-1, k)]) * N; | |
velocZ[IX(i, j, k)] -= 0.5f * ( p[IX(i, j, k+1)] | |
-p[IX(i, j, k-1)]) * N; | |
} | |
} | |
} | |
set_bnd(1, velocX, N); | |
set_bnd(2, velocY, N); | |
set_bnd(3, velocZ, N); | |
} | |
void FluidCubeStep(FluidCube *cube) | |
{ | |
int N = cube->size; | |
float visc = cube->visc; | |
float diff = cube->diff; | |
float dt = cube->dt; | |
float *Vx = cube->Vx; | |
float *Vy = cube->Vy; | |
float *Vz = cube->Vz; | |
float *Vx0 = cube->Vx0; | |
float *Vy0 = cube->Vy0; | |
float *Vz0 = cube->Vz0; | |
float *s = cube->s; | |
float *density = cube->density; | |
diffuse(1, Vx0, Vx, visc, dt, 4, N); | |
diffuse(2, Vy0, Vy, visc, dt, 4, N); | |
diffuse(3, Vz0, Vz, visc, dt, 4, N); | |
project(Vx0, Vy0, Vz0, Vx, Vy, 4, N); | |
advect(1, Vx, Vx0, Vx0, Vy0, Vz0, dt, N); | |
advect(2, Vy, Vy0, Vx0, Vy0, Vz0, dt, N); | |
advect(3, Vz, Vz0, Vx0, Vy0, Vz0, dt, N); | |
project(Vx, Vy, Vz, Vx0, Vy0, 4, N); | |
diffuse(0, s, density, diff, dt, 4, N); | |
advect(0, density, s, Vx, Vy, Vz, dt, N); | |
} | |
void FluidCubeAddDensity(FluidCube *cube, int x, int y, int z, float amount) | |
{ | |
int N = cube->size; | |
cube->density[IX(x, y, z)] += amount; | |
} | |
void FluidCubeAddVelocity(FluidCube *cube, int x, int y, int z, float amountX, float amountY, float amountZ) | |
{ | |
int N = cube->size; | |
int index = IX(x, y, z); | |
cube->Vx[index] += amountX; | |
cube->Vy[index] += amountY; | |
cube->Vz[index] += amountZ; | |
} | |
class AnimationCallback : public vtkCommand | |
{ | |
public: | |
static AnimationCallback *New() | |
{ | |
return new AnimationCallback; | |
} | |
~AnimationCallback() { | |
FluidCubeFree(this->cube); | |
} | |
void Execute(vtkObject *caller, unsigned long eventId, void *callData) override | |
{ | |
std::mt19937 gen(rd()); // Seed the generator | |
std::uniform_int_distribution<> distr(min2, max2); // Define the ran | |
if (vtkCommand::TimerEvent == eventId) | |
{ | |
// std::cout << "Animation callback" << std::endl; | |
FluidCubeStep(this->cube); | |
if(this->cube->density[IX(25,49,25)] <= 0) { | |
// FluidCubeAddDensity(this->cube, 24,1,22,20); | |
FluidCubeAddDensity(this->cube, 25,1,25,30); | |
// FluidCubeAddDensity(this->cube, 25,1,22,10); | |
// FluidCubeAddDensity(this->cube, 25,1,22,20); | |
} | |
// if(this->cube->density[IX(25,49,25)] <= 0) FluidCubeAddDensity(this->cube, 25,25,1,50); | |
// if(this->cube->density[IX(25,49,25)] <= 0) FluidCubeAddVelocity(this->cube, 25,25,2,0,0,1); | |
if(this->cube->density[IX(25,49,25)] <= 0) { | |
FluidCubeAddVelocity(this->cube, 25,2,25,0.5,0.9,0.2); | |
} | |
if(countAnimate %500 == 0 ) FluidCubeAddVelocity(this->cube, 25,distr(gen),25,distr(gen),distr(gen),distr(gen)); | |
// Generate new random values for the volume | |
for (int z = 0; z < this->dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < this->dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < this->dimensions[0]; ++x) | |
{ | |
this->imageData->SetScalarComponentFromFloat(x, y, z, 0, this->cube->density[IX(x,y,z)]*1000000000); | |
} | |
} | |
} | |
if(this->cube->density[IX(2,49,25)] > 0){ | |
for (int z = 0; z < this->dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < this->dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < this->dimensions[0]; ++x) | |
{ | |
this->cube->density[IX(x,y,z)] = 0; | |
} | |
} | |
} | |
} | |
// Update the volume data | |
this->imageData->Modified(); | |
// Request render update | |
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor *>(caller); | |
iren->GetRenderWindow()->Render(); | |
this->currentFrame++; | |
if (this->currentFrame >= this->totalFrames) | |
{ | |
iren->DestroyTimer(this->timerId); // Stop the timer after the total duration | |
} | |
} | |
} | |
void SetImageData(vtkImageData *data) | |
{ | |
this->imageData = data; | |
} | |
void SetDimensions(const int dims[3]) | |
{ | |
this->dimensions[0] = dims[0]; | |
this->dimensions[1] = dims[1]; | |
this->dimensions[2] = dims[2]; | |
} | |
void SetTotalFrames(int frames) | |
{ | |
this->totalFrames = frames; | |
} | |
void SetTimerId(int id) | |
{ | |
this->timerId = id; | |
} | |
private: | |
vtkImageData *imageData; | |
int dimensions[3]; | |
int totalFrames = 0; | |
int currentFrame = 0; | |
int timerId; | |
int countAnimate = 0; | |
FluidCube* cube = FluidCubeCreate(50, 0.0, 0.0000001f, 0.2); | |
int min2 = 1; | |
int max2 = N-1; | |
std::random_device rd; // Obtain a random number from hardware | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
std::srand(std::time(nullptr)); // Initialize random seed | |
const int dimensions[3] = {50, 50, 50}; // Dimensions of the volume | |
// Create an image data object to hold the volume data | |
vtkNew<vtkImageData> imageData; | |
imageData->SetDimensions(dimensions); | |
imageData->AllocateScalars(VTK_FLOAT, 1); | |
// Fill the image data with random values | |
vtkFloatArray *scalars = vtkFloatArray::SafeDownCast(imageData->GetPointData()->GetScalars()); | |
for (int z = 0; z < dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < dimensions[0]; ++x) | |
{ | |
float value = static_cast<float>(std::rand()) / RAND_MAX; | |
imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
} | |
} | |
} | |
vtkNew<vtkNamedColors> colors; | |
vtkNew<vtkRenderer> ren1; | |
vtkNew<vtkRenderWindow> renWin; | |
renWin->AddRenderer(ren1); | |
vtkNew<vtkRenderWindowInteractor> iren; | |
iren->SetRenderWindow(renWin); | |
// Create transfer mapping scalar value to opacity | |
vtkNew<vtkPiecewiseFunction> opacityTransferFunction; | |
opacityTransferFunction->AddPoint(0.0, 0.0); | |
opacityTransferFunction->AddPoint(0.5, 0.1); | |
opacityTransferFunction->AddPoint(1.0, 0.2); | |
// Create transfer mapping scalar value to color | |
vtkNew<vtkColorTransferFunction> colorTransferFunction; | |
// The property describes how the data will look | |
vtkNew<vtkVolumeProperty> volumeProperty; | |
volumeProperty->SetColor(colorTransferFunction); | |
volumeProperty->SetScalarOpacity(opacityTransferFunction); | |
volumeProperty->ShadeOn(); | |
volumeProperty->SetInterpolationTypeToLinear(); | |
// The mapper / ray cast function know how to render the data | |
// vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper; | |
// volumeMapper->SetInputData(imageData); | |
vtkNew<vtkMultiBlockVolumeMapper> volumeMapper; | |
volumeMapper->SetInputDataObject(imageData); | |
vtkNew<vtkOutlineFilter> outlineFilter; | |
outlineFilter->SetInputData(imageData); // Use the image data as the input | |
vtkNew<vtkPolyDataMapper> outlineMapper; | |
outlineMapper->SetInputConnection(outlineFilter->GetOutputPort()); | |
vtkNew<vtkActor> outlineActor; | |
outlineActor->SetMapper(outlineMapper); | |
outlineActor->GetProperty()->SetColor(0, 0, 0); // Set the outline color to black | |
// Add the outline actor to the renderer | |
ren1->AddActor(outlineActor); | |
// The volume holds the mapper and the property and | |
// can be used to position/orient the volume | |
vtkNew<vtkVolume> volume; | |
volume->SetMapper(volumeMapper); | |
volume->SetProperty(volumeProperty); | |
ren1->AddVolume(volume); | |
ren1->SetBackground(colors->GetColor3d("Wheat").GetData()); | |
// ren1->GetActiveCamera()->Azimuth(45); | |
// ren1->GetActiveCamera()->Elevation(30); | |
ren1->ResetCameraClippingRange(); | |
ren1->ResetCamera(); | |
renWin->SetSize(600, 600); | |
renWin->SetWindowName("Test"); | |
vtkNew<AnimationCallback> callback; | |
callback->SetImageData(imageData); | |
callback->SetDimensions(dimensions); | |
callback->SetTotalFrames(10000); // 10 seconds, 1 frame per second | |
iren->Initialize(); | |
int timerId = iren->CreateRepeatingTimer(10); // 1000ms = 1 second | |
callback->SetTimerId(timerId); | |
iren->AddObserver(vtkCommand::TimerEvent, callback); | |
iren->Start(); | |
return EXIT_SUCCESS; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vtkCamera.h> | |
#include <vtkColorTransferFunction.h> | |
#include <vtkFixedPointVolumeRayCastMapper.h> | |
#include <vtkNamedColors.h> | |
#include <vtkNew.h> | |
#include <vtkPiecewiseFunction.h> | |
#include <vtkRenderWindow.h> | |
#include <vtkRenderWindowInteractor.h> | |
#include <vtkRenderer.h> | |
#include <vtkVolume.h> | |
#include <vtkVolumeProperty.h> | |
#include <vtkImageData.h> | |
#include <vtkFloatArray.h> | |
#include <vtkPointData.h> | |
#include <vtkCommand.h> | |
#include <cstdlib> // For rand() | |
#include <ctime> // For time() | |
class AnimationCallback : public vtkCommand | |
{ | |
public: | |
static AnimationCallback *New() | |
{ | |
return new AnimationCallback; | |
} | |
void Execute(vtkObject *caller, unsigned long eventId, void *callData) override | |
{ | |
if (vtkCommand::TimerEvent == eventId) | |
{ | |
// Generate new random values for the volume | |
for (int z = 0; z < this->dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < this->dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < this->dimensions[0]; ++x) | |
{ | |
float value = static_cast<float>(std::rand()) / RAND_MAX; | |
this->imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
} | |
} | |
} | |
// Request render update | |
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor *>(caller); | |
iren->GetRenderWindow()->Render(); | |
this->currentFrame++; | |
if (this->currentFrame >= this->totalFrames) | |
{ | |
iren->DestroyTimer(this->timerId); // Stop the timer after the total duration | |
} | |
} | |
} | |
void SetImageData(vtkImageData *data) | |
{ | |
this->imageData = data; | |
} | |
void SetDimensions(const int dims[3]) | |
{ | |
this->dimensions[0] = dims[0]; | |
this->dimensions[1] = dims[1]; | |
this->dimensions[2] = dims[2]; | |
} | |
void SetTotalFrames(int frames) | |
{ | |
this->totalFrames = frames; | |
} | |
void SetTimerId(int id) | |
{ | |
this->timerId = id; | |
} | |
private: | |
vtkImageData *imageData; | |
int dimensions[3]; | |
int totalFrames = 0; | |
int currentFrame = 0; | |
int timerId; | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
std::srand(std::time(nullptr)); // Initialize random seed | |
const int dimensions[3] = {50, 50, 50}; // Dimensions of the volume | |
// Create an image data object to hold the volume data | |
vtkNew<vtkImageData> imageData; | |
imageData->SetDimensions(dimensions); | |
imageData->AllocateScalars(VTK_FLOAT, 1); | |
// Fill the image data with random values | |
vtkFloatArray *scalars = vtkFloatArray::SafeDownCast(imageData->GetPointData()->GetScalars()); | |
for (int z = 0; z < dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < dimensions[0]; ++x) | |
{ | |
float value = static_cast<float>(std::rand()) / RAND_MAX; | |
imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
} | |
} | |
} | |
vtkNew<vtkNamedColors> colors; | |
vtkNew<vtkRenderer> ren1; | |
vtkNew<vtkRenderWindow> renWin; | |
renWin->AddRenderer(ren1); | |
vtkNew<vtkRenderWindowInteractor> iren; | |
iren->SetRenderWindow(renWin); | |
// Create transfer mapping scalar value to opacity | |
vtkNew<vtkPiecewiseFunction> opacityTransferFunction; | |
opacityTransferFunction->AddPoint(0.0, 0.0); | |
opacityTransferFunction->AddPoint(1.0, 0.2); | |
// Create transfer mapping scalar value to color | |
vtkNew<vtkColorTransferFunction> colorTransferFunction; | |
colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); | |
colorTransferFunction->AddRGBPoint(0.5, 1.0, 0.0, 0.0); | |
colorTransferFunction->AddRGBPoint(1.0, 0.0, 0.0, 1.0); | |
// The property describes how the data will look | |
vtkNew<vtkVolumeProperty> volumeProperty; | |
volumeProperty->SetColor(colorTransferFunction); | |
volumeProperty->SetScalarOpacity(opacityTransferFunction); | |
volumeProperty->ShadeOn(); | |
volumeProperty->SetInterpolationTypeToLinear(); | |
// The mapper / ray cast function know how to render the data | |
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper; | |
volumeMapper->SetInputData(imageData); | |
// The volume holds the mapper and the property and | |
// can be used to position/orient the volume | |
vtkNew<vtkVolume> volume; | |
volume->SetMapper(volumeMapper); | |
volume->SetProperty(volumeProperty); | |
ren1->AddVolume(volume); | |
ren1->SetBackground(colors->GetColor3d("Wheat").GetData()); | |
ren1->ResetCameraClippingRange(); | |
ren1->ResetCamera(); | |
renWin->SetSize(600, 600); | |
renWin->SetWindowName("Random Data Volume Animation"); | |
vtkNew<AnimationCallback> callback; | |
callback->SetImageData(imageData); | |
callback->SetDimensions(dimensions); | |
callback->SetTotalFrames(10); // 10 seconds, 1 frame per second | |
iren->Initialize(); | |
int timerId = iren->CreateRepeatingTimer(100); // 1000ms = 1 second | |
callback->SetTimerId(timerId); | |
iren->AddObserver(vtkCommand::TimerEvent, callback); | |
iren->Start(); | |
return EXIT_SUCCESS; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #include <vtkCamera.h> | |
// #include <vtkColorTransferFunction.h> | |
// #include <vtkFixedPointVolumeRayCastMapper.h> | |
// #include <vtkNamedColors.h> | |
// #include <vtkNew.h> | |
// #include <vtkPiecewiseFunction.h> | |
// #include <vtkRenderWindow.h> | |
// #include <vtkRenderWindowInteractor.h> | |
// #include <vtkRenderer.h> | |
// #include <vtkStructuredPointsReader.h> | |
// #include <vtkVolume.h> | |
// #include <vtkVolumeProperty.h> | |
// #include <vtkImageData.h> | |
// #include <vtkFloatArray.h> | |
// #include <vtkPointData.h> | |
// #include <cstdlib> // For rand() | |
// #include <ctime> // For time() | |
// int main(int argc, char *argv[]) | |
// { | |
// std::srand(std::time(nullptr)); // Initialize random seed | |
// const int dimensions[3] = {50, 50, 50}; // Dimensions of the volume | |
// // Create an image data object to hold the volume data | |
// vtkNew<vtkImageData> imageData; | |
// imageData->SetDimensions(dimensions); | |
// imageData->AllocateScalars(VTK_FLOAT, 1); | |
// // Fill the image data with random values | |
// vtkFloatArray *scalars = vtkFloatArray::SafeDownCast(imageData->GetPointData()->GetScalars()); | |
// for (int z = 0; z < dimensions[2]; ++z) | |
// { | |
// for (int y = 0; y < dimensions[1]; ++y) | |
// { | |
// for (int x = 0; x < dimensions[0]; ++x) | |
// { | |
// float value = static_cast<float>(std::rand()) / RAND_MAX; | |
// imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
// } | |
// } | |
// } | |
// // Create the standard renderer, render window | |
// // and interactor | |
// vtkNew<vtkNamedColors> colors; | |
// vtkNew<vtkRenderer> ren1; | |
// vtkNew<vtkRenderWindow> renWin; | |
// renWin->AddRenderer(ren1); | |
// vtkNew<vtkRenderWindowInteractor> iren; | |
// iren->SetRenderWindow(renWin); | |
// // Create transfer mapping scalar value to opacity | |
// vtkNew<vtkPiecewiseFunction> opacityTransferFunction; | |
// opacityTransferFunction->AddPoint(0.0, 0.0); | |
// opacityTransferFunction->AddPoint(1.0, 0.2); | |
// // Create transfer mapping scalar value to color | |
// vtkNew<vtkColorTransferFunction> colorTransferFunction; | |
// colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); | |
// colorTransferFunction->AddRGBPoint(0.5, 1.0, 0.0, 0.0); | |
// colorTransferFunction->AddRGBPoint(1.0, 0.0, 0.0, 1.0); | |
// // The property describes how the data will look | |
// vtkNew<vtkVolumeProperty> volumeProperty; | |
// volumeProperty->SetColor(colorTransferFunction); | |
// volumeProperty->SetScalarOpacity(opacityTransferFunction); | |
// volumeProperty->ShadeOn(); | |
// volumeProperty->SetInterpolationTypeToLinear(); | |
// // The mapper / ray cast function know how to render the data | |
// vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper; | |
// // volumeMapper->SetInputConnection(reader->GetOutputPort()); | |
// volumeMapper->SetInputData(imageData); | |
// // The volume holds the mapper and the property and | |
// // can be used to position/orient the volume | |
// vtkNew<vtkVolume> volume; | |
// volume->SetMapper(volumeMapper); | |
// volume->SetProperty(volumeProperty); | |
// ren1->AddVolume(volume); | |
// ren1->SetBackground(colors->GetColor3d("Wheat").GetData()); | |
// // ren1->GetActiveCamera()->Azimuth(45); | |
// // ren1->GetActiveCamera()->Elevation(30); | |
// ren1->ResetCameraClippingRange(); | |
// ren1->ResetCamera(); | |
// renWin->SetSize(600, 600); | |
// renWin->SetWindowName("Fluid Simulation"); | |
// renWin->Render(); | |
// iren->Start(); | |
// return EXIT_SUCCESS; | |
// } | |
#include <vtkCamera.h> | |
#include <vtkColorTransferFunction.h> | |
#include <vtkFixedPointVolumeRayCastMapper.h> | |
#include <vtkNamedColors.h> | |
#include <vtkNew.h> | |
#include <vtkPiecewiseFunction.h> | |
#include <vtkRenderWindow.h> | |
#include <vtkRenderWindowInteractor.h> | |
#include <vtkRenderer.h> | |
#include <vtkVolume.h> | |
#include <vtkVolumeProperty.h> | |
#include <vtkImageData.h> | |
#include <vtkFloatArray.h> | |
#include <vtkPointData.h> | |
#include <vtkCommand.h> | |
#include <cstdlib> // For rand() | |
#include <ctime> // For time() | |
class AnimationCallback : public vtkCommand | |
{ | |
public: | |
static AnimationCallback *New() | |
{ | |
return new AnimationCallback; | |
} | |
void Execute(vtkObject *caller, unsigned long eventId, void *callData) override | |
{ | |
if (vtkCommand::TimerEvent == eventId) | |
{ | |
// Generate new random values for the volume | |
for (int z = 0; z < this->dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < this->dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < this->dimensions[0]; ++x) | |
{ | |
float value = static_cast<float>(std::rand()) / RAND_MAX; | |
this->imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
} | |
} | |
} | |
// Request render update | |
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor *>(caller); | |
iren->GetRenderWindow()->Render(); | |
this->currentFrame++; | |
if (this->currentFrame >= this->totalFrames) | |
{ | |
iren->DestroyTimer(this->timerId); // Stop the timer after the total duration | |
} | |
} | |
} | |
void SetImageData(vtkImageData *data) | |
{ | |
this->imageData = data; | |
} | |
void SetDimensions(const int dims[3]) | |
{ | |
this->dimensions[0] = dims[0]; | |
this->dimensions[1] = dims[1]; | |
this->dimensions[2] = dims[2]; | |
} | |
void SetTotalFrames(int frames) | |
{ | |
this->totalFrames = frames; | |
} | |
void SetTimerId(int id) | |
{ | |
this->timerId = id; | |
} | |
private: | |
vtkImageData *imageData; | |
int dimensions[3]; | |
int totalFrames = 0; | |
int currentFrame = 0; | |
int timerId; | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
std::srand(std::time(nullptr)); // Initialize random seed | |
const int dimensions[3] = {50, 50, 50}; // Dimensions of the volume | |
// Create an image data object to hold the volume data | |
vtkNew<vtkImageData> imageData; | |
imageData->SetDimensions(dimensions); | |
imageData->AllocateScalars(VTK_FLOAT, 1); | |
// Fill the image data with random values | |
vtkFloatArray *scalars = vtkFloatArray::SafeDownCast(imageData->GetPointData()->GetScalars()); | |
for (int z = 0; z < dimensions[2]; ++z) | |
{ | |
for (int y = 0; y < dimensions[1]; ++y) | |
{ | |
for (int x = 0; x < dimensions[0]; ++x) | |
{ | |
float value = static_cast<float>(std::rand()) / RAND_MAX; | |
imageData->SetScalarComponentFromFloat(x, y, z, 0, value); | |
} | |
} | |
} | |
vtkNew<vtkNamedColors> colors; | |
vtkNew<vtkRenderer> ren1; | |
vtkNew<vtkRenderWindow> renWin; | |
renWin->AddRenderer(ren1); | |
vtkNew<vtkRenderWindowInteractor> iren; | |
iren->SetRenderWindow(renWin); | |
// Create transfer mapping scalar value to opacity | |
vtkNew<vtkPiecewiseFunction> opacityTransferFunction; | |
opacityTransferFunction->AddPoint(0.0, 0.0); | |
opacityTransferFunction->AddPoint(1.0, 0.2); | |
// Create transfer mapping scalar value to color | |
vtkNew<vtkColorTransferFunction> colorTransferFunction; | |
colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); | |
colorTransferFunction->AddRGBPoint(0.5, 1.0, 0.0, 0.0); | |
colorTransferFunction->AddRGBPoint(1.0, 0.0, 0.0, 1.0); | |
// The property describes how the data will look | |
vtkNew<vtkVolumeProperty> volumeProperty; | |
volumeProperty->SetColor(colorTransferFunction); | |
volumeProperty->SetScalarOpacity(opacityTransferFunction); | |
volumeProperty->ShadeOn(); | |
volumeProperty->SetInterpolationTypeToLinear(); | |
// The mapper / ray cast function know how to render the data | |
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper; | |
volumeMapper->SetInputData(imageData); | |
// The volume holds the mapper and the property and | |
// can be used to position/orient the volume | |
vtkNew<vtkVolume> volume; | |
volume->SetMapper(volumeMapper); | |
volume->SetProperty(volumeProperty); | |
ren1->AddVolume(volume); | |
ren1->SetBackground(colors->GetColor3d("Wheat").GetData()); | |
ren1->ResetCameraClippingRange(); | |
ren1->ResetCamera(); | |
renWin->SetSize(600, 600); | |
renWin->SetWindowName("Random Data Volume Animation"); | |
vtkNew<AnimationCallback> callback; | |
callback->SetImageData(imageData); | |
callback->SetDimensions(dimensions); | |
callback->SetTotalFrames(10); // 10 seconds, 1 frame per second | |
iren->Initialize(); | |
int timerId = iren->CreateRepeatingTimer(100); // 1000ms = 1 second | |
callback->SetTimerId(timerId); | |
iren->AddObserver(vtkCommand::TimerEvent, callback); | |
iren->Start(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Week 1 video: https://drive.google.com/file/d/1aQzAKdB_kBxJ9ck0b5HD_ep9dPyg91W1/view?usp=sharing