VTK Volume Visualization Issue - c++

I am using vtk library with C++ to generate and visualize some synthetic voxel data with given color and transparency mapping. An example is shown below:
As shown in the figure, the data is 3D in general, and it works great. However, in specific cases when the data becomes 2D, the visualization windows shows nothing.
I am posting few lines of my code which may be helpful.
imageData = vtkSmartPointer<vtkImageData>::New();
imageData->SetDimensions(X1, X2, X3); //For 2D, one of X1,X2 & X3=1
imageData->AllocateScalars(VTK_INT, 1);
int* I = new int[X1X2X3](); //int X1X2X3 = X1*X2*X3
I = static_cast<int*>(imageData->GetScalarPointer());
Please note that for 2D, either X1=1 or X2=1 or X3=1.
Any suggestions?
EDIT:
I am adding an equivalent code, which will demonstrate the exact problem I am facing:
main.cpp
//#include <vtkAutoInit.h> // if not using CMake to compile, necessary to use this macro
//#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle, vtkRenderingFreeType, vtkRenderingOpenGL2)
//#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL2)
//#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2)
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkSampleFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkImageData.h>
#include <stdlib.h>
using namespace std;
int main()
{
//Declaring Variables
vtkSmartPointer<vtkImageData> imageData;
vtkSmartPointer<vtkVolumeProperty> volumeProperty;
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity;
vtkSmartPointer<vtkColorTransferFunction> color;
vtkSmartPointer<vtkVolume> volume;
vtkSmartPointer<vtkSmartVolumeMapper> mapper;
vtkSmartPointer<vtkActor> actor;
vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
vtkSmartPointer<vtkRenderWindow> renderWindow;
int* I;
int X1, X2, X3, X1X2X3;
//Assigning Values , Allocating Memory
X1 = 10;
X2 = 10;
X3 = 10;
X1X2X3 = X1*X2*X3;
I = new int[X1X2X3]();
imageData = vtkSmartPointer<vtkImageData>::New();
volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
color = vtkSmartPointer<vtkColorTransferFunction>::New();
volume = vtkSmartPointer<vtkVolume>::New();
mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
actor = vtkSmartPointer<vtkActor>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
volumeProperty->ShadeOff();
volumeProperty->SetInterpolationType(0);
volumeProperty->SetColor(color);
volumeProperty->SetScalarOpacity(compositeOpacity);
imageData->SetDimensions(X1, X2, X3);
imageData->AllocateScalars(VTK_INT, 1);
I = static_cast<int*>(imageData->GetScalarPointer());
renderWindow->AddRenderer(renderer);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->SetBackground(0.5, 0.5, 0.5);
renderWindow->SetSize(800, 800);
mapper->SetBlendModeToComposite();
imageData->UpdateCellGhostArrayCache();
mapper->SetRequestedRenderModeToRayCast();
mapper->SetInputData(imageData);
volume->SetMapper(mapper);
volume->SetProperty(volumeProperty);
renderer->AddViewProp(volume);
volumeProperty->ShadeOff();
//Setting Voxel Data and Its Properties
for (int i = 0; i < X1X2X3; i++)
{
I[i] = i;
compositeOpacity->AddPoint(i, 1);
color->AddRGBPoint(i, double( rand()) / RAND_MAX, double(rand()) / RAND_MAX, double(rand()) / RAND_MAX);
}
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
getchar();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(EvoSim)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_USE_RELATIVE_PATHS ON)
#GRABBING VTK
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(MAIN main.cpp)
target_link_libraries(MAIN ${VTK_LIBRARIES})
This leads to an output like below (for, X1=X2=X3=10)
However if I make X1=1, the output window is empty.
EDIT:
I just observed that the number of voxels along a certain dimension, displayed on the screen are always one less than the maximum number of voxels in that dimensions. For example, if X1=X2=X3=10, the number of voxels in each dimensions which are displayed on vtkwindow is 9. This is not what I would expect. I think this is the problem with X1=1, which makes 1-1=0 voxel display.
Any suggestions??

This remained unanswered for long. So I am adding my solution/workaround.
I had to add an extra dummy layer in each dimension of imagedata. [See this line in the code imageData->SetDimensions(X1 +1 , X2 + 1, X3 + 1);]. Rest is self explanatory.
#pragma once
//#include <vtkAutoInit.h> // if not using CMake to compile, necessary to use this macro
//#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle, vtkRenderingFreeType, vtkRenderingOpenGL2)
//#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL2)
//#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2)
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkSampleFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkImageData.h>
#include <stdlib.h>
#include <numeric> // std::iota
using namespace std;
int main()
{
//Declaring Variables
vtkSmartPointer<vtkImageData> imageData;
vtkSmartPointer<vtkVolumeProperty> volumeProperty;
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity;
vtkSmartPointer<vtkColorTransferFunction> color;
vtkSmartPointer<vtkVolume> volume;
vtkSmartPointer<vtkSmartVolumeMapper> mapper;
vtkSmartPointer<vtkActor> actor;
vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
vtkSmartPointer<vtkRenderWindow> renderWindow;
int X1, X2, X3, X1X2X3;
//Assigning Values , Allocating Memory
X1 = 10;
X2 = 10;
X3 = 10;
X1X2X3 = X1*X2*X3;
imageData = vtkSmartPointer<vtkImageData>::New();
imageData->SetDimensions(X1 + 1, X2 + 1, X3 + 1);
imageData->AllocateScalars(VTK_INT, 1);
volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
color = vtkSmartPointer<vtkColorTransferFunction>::New();
volume = vtkSmartPointer<vtkVolume>::New();
mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
actor = vtkSmartPointer<vtkActor>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
volumeProperty->ShadeOff();
volumeProperty->SetInterpolationType(0);
volumeProperty->SetColor(color);
volumeProperty->SetScalarOpacity(compositeOpacity);
imageData->AllocateScalars(VTK_INT, 1);
renderWindow->AddRenderer(renderer);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->SetBackground(0.5, 0.5, 0.5);
renderWindow->SetSize(800, 800);
mapper->SetBlendModeToComposite();
imageData->UpdateCellGhostArrayCache();
mapper->SetRequestedRenderModeToRayCast();
mapper->SetInputData(imageData);
volume->SetMapper(mapper);
volume->SetProperty(volumeProperty);
renderer->AddViewProp(volume);
volumeProperty->ShadeOff();
//I is supposed to store the 3D data which has to be shown as volume visualization. This 3D data is stored
//as a 1D array in which the order of iteration over 3 dimensions is x->y->z, this leads to the following
//3D to 1D index conversion farmula index1D = i + X1*j + X1*X2*k
vector<int> I(X1X2X3,0); // No need to use int* I = new int[X1X2X3] //Vectors are good
std::iota(&I[0], &I[0] + X1X2X3, 1); //Creating dummy data as 1,2,3...X1X2X3
//Setting Voxel Data and Its Properties
for (int k = 0; k < X3 + 1 ; k++)
{
for (int j = 0; j < X2 + 1 ; j++)
{
for (int i = 0; i < X1 + 1 ; i++)
{
int* voxel = static_cast<int*>(imageData->GetScalarPointer(i, j, k));
if (i==X1 || j== X2 || k==X3)
{
//Assigning zeros to dummy voxels, these will not be displayed anyways
voxel[0] = 0;
}
else
{
//copying data from I to imagedata voxel
voxel[0] = I[i + X1*j + X1*X2*k];
}
}
}
}
//Setting Up Display Properties
for (int i = 1; i < X1X2X3; i++)
{
compositeOpacity->AddPoint(i, 1);
color->AddRGBPoint(i, double(rand()) / RAND_MAX, double(rand()) / RAND_MAX, double(rand()) / RAND_MAX);
}
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
getchar();
return 0;
}
Now the expected number of voxels in each dimensions (10 as per the code above), are correctly seen

Related

How to tell VTK pipeline to use new vtkPolyData updated via TimerEvent?

Intention
I wrote a VTK application that generates a spiral using vtkPoints > vtkPolyLine > vtkPolyData > vtkPolyDataMapper and displays it. This works fine, if done static at the initialization of the program.
Now, I want to add new data points dynamically. The intention is to visualize measurements in real time, so new data will be added in certain intervals.
Issues
Currently, I just implemented a TimerEvent to update the vtkPoints and vtkPolyLine. But, the program just shows the static data generated before the vtkRenderWindowInteractor was started. I also tried to use "Modified()" and "Update()" calls to nearly all objects, tried to remove, regenerate and add a new actor to the renderer -- but without success! I added my C++ code below...
Related-Questions
The following mailing list question is about this issues, but the solution given doen't work for me:
http://public.kitware.com/pipermail/vtkusers/2006-November/038377.html
The following question seems to be related, but there are no useful answers:
VTK: update data points in renderWindow at every simulation timestep
Questions
How to tell VTK that the vtkPolyData object has changed?
Which of the VTK UsersGuide should I probably have a closer look at?
Details / Source Code
I'm using Visual Studio Community 2017 and VTK 8.0.0, both compiled as Win32 target.
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();
int numOfPoints = 0;
double t = 0;
void NextPoint() {
double x = t * cos(t);
double y = t * sin(t);
points->InsertNextPoint(x, y, t);
polyLine->GetPointIds()->InsertNextId(numOfPoints);
numOfPoints++;
t += 0.1;
}
vtkSmartPointer<vtkPolyData> generateEllipse() {
// Add some points so we actually see something at all...
for (int i = 0; i < 100; ++i) {
NextPoint();
}
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
return polyData;
}
class vtkTimerCallback : public vtkCommand
{
public:
static vtkTimerCallback *New()
{
vtkTimerCallback *cb = new vtkTimerCallback;
cb->TimerCount = 0;
return cb;
}
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId,
void *vtkNotUsed(callData))
{
if (vtkCommand::TimerEvent == eventId)
{
NextPoint(); // Add another point to polyData
++this->TimerCount;
cout << this->TimerCount << endl;
}
}
private:
int TimerCount;
};
int main(int argc, char** argv) {
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkPolyData> data = generateEllipse();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(data);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetDiffuseColor(255, 255, 0);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->ResetCamera();
renderWindow->Render();
// Add Timer Event...
rwi->Initialize();
vtkSmartPointer<vtkTimerCallback> cb = vtkSmartPointer<vtkTimerCallback>::New();
rwi->AddObserver(vtkCommand::TimerEvent, cb);
int timerId = rwi->CreateRepeatingTimer(100); // every 100ms
std::cout << "timerId: " << timerId << std::endl;
// Start Displaying...
rwi->Start();
return 0;
}
the problem is that the cells are not stored by pointer - when you call cells->InsertNextCell(polyLine); the data is copied, not pointed to, in order to create an efficient storage of the cells in an array (the whole implementation is actually in the header of vtkCellArray so you can check it out). So then when you update polyLine, it has no effect in the polydata, because the polydata have their own copy that you did not update. The following code works for me (you have to expose the polydata and the cellArray):
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId,
void *vtkNotUsed(callData))
{
if (vtkCommand::TimerEvent == eventId)
{
NextPoint(); // Add another point to polyData
cells->Initialize(); // reset the cells to remove the old spiral
cells->InsertNextCell(polyLine); // re-insert the updated spiral
cells->Modified(); // required to update
data->Modified(); // required to update
++this->TimerCount;
cout << polyLine->GetNumberOfPoints() << endl;
renderWindow->Render(); // refresh the render window after each update
}
}
Yesterday I worked out an alternative solution using a vtkProgrammableDataObjectSource as DataSource. Tomj's solution is the more direct and simple solution... However, there is no C++ Example Code at vtk.org that explains how to use vtkProgrammableDataObjectSource and I had to work it out by trial and error. So I'll post it here, as it might help others:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <vtkProgrammableFilter.h>
#include <vtkCallbackCommand.h>
#include <vtkPolyDataStreamer.h>
#include <vtkProgrammableDataObjectSource.h>
vtkSmartPointer<vtkProgrammableDataObjectSource> pDOS = vtkSmartPointer<vtkProgrammableDataObjectSource>::New();
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();
int numOfPoints = 0;
double t = 0;
void NextPoint() {
double x = t * cos(t);
double y = t * sin(t);
points->InsertNextPoint(x, y, t);
polyLine->GetPointIds()->InsertNextId(numOfPoints);
numOfPoints++;
t += 0.1;
}
void generateEllipse(void *caller) {
vtkProgrammableDataObjectSource *pDOS = vtkProgrammableDataObjectSource::SafeDownCast((vtkObjectBase*)caller);
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
pDOS->SetOutput(polyData);
}
int counter2 = 0;
void TimerCallbackFunction(vtkObject* caller, long unsigned int vtkNotUsed(eventId), void* clientData, void* vtkNotUsed(callData)) {
cout << "timer callback: " << counter2 << endl;
// To avoid globals we can implement this later...
// vtkSmartPointer<vtkProgrammableDataObjectSource> pDOS =
// static_cast<vtkProgrammableDataObjectSource*>(clientData);
vtkRenderWindowInteractor *rwi =
static_cast<vtkRenderWindowInteractor*>(caller);
NextPoint();
pDOS->Modified();
rwi->Render();
renderer->ResetCamera(); // Optional: Reposition Camera, so it displays the whole object
counter2++;
}
int main(int argc, char** argv) {
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(renderWindow);
pDOS->SetExecuteMethod(&generateEllipse, pDOS);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(pDOS->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetDiffuseColor(255, 255, 0);
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->ResetCamera();
renderWindow->Render();
// Add Timer Event...
vtkSmartPointer<vtkCallbackCommand> timerCallback = vtkSmartPointer<vtkCallbackCommand>::New();
timerCallback->SetCallback(TimerCallbackFunction);
rwi->Initialize();
rwi->CreateRepeatingTimer(100);
rwi->AddObserver(vtkCommand::TimerEvent, timerCallback);
// Start Displaying...
rwi->Start();
return 0;
}

c++ OpenGL terrain generation

Im trying to make a terrain from a grid of vertices and i have a bug and just cant find it.Im stuck with it for 3 hours.Im using c++ and opengl.Im plan to use a blendmap for texturing and a height map later.Anyway here's the code:
Heres how it should look like: http://postimg.org/image/9431kcvy7/
Heres how it looks:
http://postimg.org/image/xxsoesqkp/
As you can see the tringles are separated by a 1 unit rectagle and it look like all the bottom points form a triangle with the point that has coordinates (0,0,0)
I know this problem might seem easy to solve but ive lost already 3 hours trying.Please help:)
Map.h
#ifndef MAP_H
#define MAP_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
#include <windows.h>
using namespace std;
struct coordinate{
float x,y,z;
};
struct face{
int v[3];
int n[3];
};
struct uv{
float x;
float y;
};
class Map
{
private:
int mapX,mapY;
vector<coordinate> vertex;
vector<uv>textureCoordinates;
vector<coordinate>normals;
vector< vector<face> > faces;
string fileNameString;
sf::Image image[5];
sf::Color faceColor,blendPixel,p0,p1,p2;
sf::Image texture;
sf::Uint8 pixels[256*256*4];
unsigned int imageID[3],textureID;
public:
void load(const char *fileName);
void draw();
};
#endif // MAP_H
And Map.cpp
#include "Map.h"
#define blendMap 3
#define heightMap 4
void Map::load(const char *fileName)
{
int i,j;
fileNameString=fileName;
vector<face> F;
coordinate v;
face f;
image[0].loadFromFile(fileNameString+"/0.png");
image[1].loadFromFile(fileNameString+"/1.png");
image[2].loadFromFile(fileNameString+"/2.png");
image[blendMap].loadFromFile(fileNameString+"/blendMap.png");
image[heightMap].loadFromFile(fileNameString+"/heightMap.png");
mapX=image[blendMap].getSize().x;
mapY=image[blendMap].getSize().y;
for(i=-mapY/2;i<mapY/2;i++)
for(j=-mapX/2;j<mapX/2;j++)
{
v.x=j*0.5;
v.z=i*0.5;
vertex.push_back(v);
}
for(i=0;i<mapY-1;i++)
{
for(j=0;j<2*(mapX-1);j++)
F.push_back(f);
faces.push_back(F);
}
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
faces[i][j].v[0]=i*mapX+j;
faces[i][j].v[1]=i*mapX+j+1;
faces[i][j].v[2]=(i+1)*mapX+j;
faces[i][j+1].v[0]=i*mapX+j+1;
faces[i][j+1].v[1]=(i+1)*mapX+j+1;
faces[i][j+1].v[2]=(i+1)*mapX+j;
}
for(i=0;i<mapX*mapY;i++)
{
color=image[heightMap].getPixel(i/mapX,i%mapX);
vertex[i].y=0;//(float)color.r/25.5-10;
}
}
void Map::draw()
{
unsigned int i,j;
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
glBindTexture(GL_TEXTURE_2D,imageID[0]);
glBegin(GL_TRIANGLES);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j].v[0]].x , vertex[faces[i][j].v[0]].y , vertex[faces[i][j].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j].v[1]].x , vertex[faces[i][j].v[1]].y , vertex[faces[i][j].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j].v[2]].x , vertex[faces[i][j].v[2]].y , vertex[faces[i][j].v[2]].z);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j+1].v[0]].x , vertex[faces[i][j+1].v[0]].y , vertex[faces[i][j+1].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j+1].v[1]].x , vertex[faces[i][j+1].v[1]].y , vertex[faces[i][j+1].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j+1].v[2]].x , vertex[faces[i][j+1].v[2]].y , vertex[faces[i][j+1].v[2]].z);
glEnd();
}
}
A few things:
for(i=-mapY/2;i<mapY/2;i++)
This is dangerous and probably not the intention of the loop, anyway. You want to loop mapY times. However, if mapY is odd, you will loop only mapY - 1 times. E.g. if mapY = 3, then -mapY / 2 = -1; mapY / 2 = 1. So you will loop with the values -1 and 0. That's a first problem, which results in too few vertices in your buffer (this is probably the main problem). Instead do the shifting on the coordinate level:
for(i = 0; i < mapY; i++)
for(j = 0; j < mapX; j++)
{
v.x = j * 0.5 - mapY / 2.0;
v.z = i * 0.5 - mapX / 2.0;
vertex.push_back(v);
}
Is there a reason why you use a vector<vector<...>> for the faces? It will give you all kinds of problems regarding indexing as you already noticed. Just use a vector<Face> and put all your faces in there. Usually, you create this structure once and never touch it again. So the 2D indexing is probably not necessary. If you want to stay with the 2D indexing, this loop has wrong bounds:
for(j=0;j<(mapX-1)*2;j+=2)
This upper bound is an inclusive bound. Therefore, use
for(j = 0; j <= (mapX - 1) * 2; j += 2)

Read in .vtk binary file using vtkGenericDataObjectReader

I'm trying to read a legacy .vtk file in c++ and populate my data structures using vtkGenericDataObjectReader (for a Molecular Dynamics simulation). I've searched through the documentation and incorporated answers from similar SO questions, but I'm still misunderstanding something. Here's the file. Forgive the binary, I think it's written correctly but I wouldn't rule out it as the problem.
# vtk DataFile Version 3.0
vtk output
BINARY
DATASET POLYDATA
FIELD FieldData 2
TIME 1 1 double
\00\00\00\00\00\00\00\00CYCLE 1 1 int
\00\00\00\00POINTS 8 double
\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m \D3B2?\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2\BF\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2?\F0\ED\E4m\D3B2VERTICES 8 16
\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00POINT_DATA 8
SCALARS mass double
LOOKUP_TABLE default
#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00#H\00\00\00\00\00\00VECTORS velocity double
\BF\C0\9E b\D8_\BFp\B4Mz\8B\BF\C1\A3|9?\B5\81`\FA\CAk?\C7N\A4ig\BF\94\E5R,\BE瀿\C5wSbK\8E?\98l?\E0\AFϿ\CC3\81\EE\F1n*\BF\C3\DA6\EArf?\B5Ж\CD\EF\99?\C1\F1,\9E\F3\CF?\99=Aɕm"?\B2\87l\89\96eU?\A9\E9cA\A4[?\BD\D6\FD\A2Ϳ\C5\E9r}\93\B1\BF\B8X:a\B86\A4?\BDB\CE\DBV֓\BF\A4\AAa,~,?Č7\CCR{?\BC\F4\99L\B7Y\BF\C3\CD W\E4v(?\BFOS\D4f\8B
This is my code. It segfaults in vtkDataReader::ReadString(char*) from /usr/lib/libvtkIO.so.5.8 while trying to execute the line 'int rv = reader->ReadPoints(ps, int(num_particles));'
vtkSmartPointer<vtkGenericDataObjectReader> reader =
vtkSmartPointer<vtkGenericDataObjectReader>::New();
reader->SetFileName(in_rel_path.c_str());
reader->Update();
vtkPolyData* output = reader->GetPolyDataOutput();
vtkPointSet *ps = NULL;
size_t num_particles = output->GetNumberOfPoints();
int rv = reader->ReadPoints(ps, int(num_particles));
vtkPointData* pd = output->GetPointData();
vtkDoubleArray* vel_data = vtkDoubleArray::SafeDownCast(pd->GetVectors());
vtkDoubleArray* mass_data = vtkDoubleArray::SafeDownCast(pd->GetScalars());
vtkDoubleArray* time_data = vtkDoubleArray::SafeDownCast(pd->GetArray("TIME"));
vtkIntArray* cycle_data = vtkIntArray::SafeDownCast(pd->GetArray("CYCLE"));
tot_iters = cycle_data->GetValue(0);
particles.resize(0);
double* position = new double[3];
double* velocity = new double[3];
for( size_t i = 0; i < num_particles; i++ )
{
ps->GetPoint(int(i), position);
vel_data->GetTupleValue(int(i), velocity);
double pmass = mass_data->GetValue(int(i));
particles.push_back(Particle(vec3(position[0],position[1],position[2]),
vec3(velocity[0],velocity[1],velocity[2]),
pmass));
}
delete[] position;
delete[] velocity;
I admit I don't know much about VTK. If anyone can help explain what I'm doing wrong, or a better way to go about this, I'd really appreciate it.
The best option to read a PolyData is using the vtkPolyDataReader class.
But if you read the class documentation they give the following warning about BINARY files
"Binary files written on one system may not be readable on other systems."
Here is an example, taken from VTK Wiki that reads .vtk file
#include <vtkPolyDataReader.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
int main ( int argc, char *argv[] )
{
// Parse command line arguments
if(argc != 2)
{
std::cerr << "Usage: " << argv[0]
<< " Filename(.vtk)" << std::endl;
return EXIT_FAILURE;
}
std::string filename = argv[1];
// Read all the data from the file
vtkSmartPointer<vtkPolyDataReader> reader =
vtkSmartPointer<vtkPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
// Visualize
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(.3, .6, .3); // Background color green
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}

Video Stabilization

I 'm researching about Video Stabilization field. I implement a application using OpenCV.
My progress such as:
Surf points extraction
Matching
estimateRigidTransform
warpAffine
But the result video is not be stable. Can anyone help me this problem or provide me some source code link to improve?
Sample video: Hippo video
Here is my code [EDIT]
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/opencv.hpp>
const double smooth_level = 0.7;
using namespace cv;
using namespace std;
struct TransformParam
{
TransformParam() {}
TransformParam(double _dx, double _dy, double _da) {
dx = _dx;
dy = _dy;
da = _da;
}
double dx; // translation x
double dy; // translation y
double da; // angle
};
int main( int argc, char** argv )
{
VideoCapture cap ("test12.avi");
Mat cur, cur_grey;
Mat prev, prev_grey;
cap >> prev;
cvtColor(prev, prev_grey, COLOR_BGR2GRAY);
// Step 1 - Get previous to current frame transformation (dx, dy, da) for all frames
vector <TransformParam> prev_to_cur_transform; // previous to current
int k=1;
int max_frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
VideoWriter writeVideo ("stable.avi",0,30,cvSize(prev.cols,prev.rows),true);
Mat last_T;
double avg_dx = 0, avg_dy = 0, avg_da = 0;
Mat smooth_T(2,3,CV_64F);
while(true) {
cap >> cur;
if(cur.data == NULL) {
break;
}
cvtColor(cur, cur_grey, COLOR_BGR2GRAY);
// vector from prev to cur
vector <Point2f> prev_corner, cur_corner;
vector <Point2f> prev_corner2, cur_corner2;
vector <uchar> status;
vector <float> err;
goodFeaturesToTrack(prev_grey, prev_corner, 200, 0.01, 30);
calcOpticalFlowPyrLK(prev_grey, cur_grey, prev_corner, cur_corner, status, err);
// weed out bad matches
for(size_t i=0; i < status.size(); i++) {
if(status[i]) {
prev_corner2.push_back(prev_corner[i]);
cur_corner2.push_back(cur_corner[i]);
}
}
// translation + rotation only
Mat T = estimateRigidTransform(prev_corner2, cur_corner2, false);
// in rare cases no transform is found. We'll just use the last known good transform.
if(T.data == NULL) {
last_T.copyTo(T);
}
T.copyTo(last_T);
// decompose T
double dx = T.at<double>(0,2);
double dy = T.at<double>(1,2);
double da = atan2(T.at<double>(1,0), T.at<double>(0,0));
prev_to_cur_transform.push_back(TransformParam(dx, dy, da));
avg_dx = (avg_dx * smooth_level) + (dx * (1- smooth_level));
avg_dy = (avg_dy * smooth_level) + (dy * (1- smooth_level));
avg_da = (avg_da * smooth_level) + (da * (1- smooth_level));
smooth_T.at<double>(0,0) = cos(avg_da);
smooth_T.at<double>(0,1) = -sin(avg_da);
smooth_T.at<double>(1,0) = sin(avg_da);
smooth_T.at<double>(1,1) = cos(avg_da);
smooth_T.at<double>(0,2) = avg_dx;
smooth_T.at<double>(1,2) = avg_dy;
Mat stable;
warpAffine(prev,stable,smooth_T,prev.size());
Mat canvas = Mat::zeros(cur.rows, cur.cols*2+10, cur.type());
prev.copyTo(canvas(Range::all(), Range(0, prev.cols)));
stable.copyTo(canvas(Range::all(), Range(prev.cols+10, prev.cols*2+10)));
imshow("before and after", canvas);
waitKey(20);
writeVideo.write(stable);
cur.copyTo(prev);
cur_grey.copyTo(prev_grey);
k++;
}
}
First, you can just blur you image. It will helps a bit. Second, you can easily smooth your matrix by simplest implementation of exponential smooth A(t+1) = a*A(t)+(1-a)*A(t+1) and play with a-value in [0;1] range. Third, you can turn off some type of transformations like rotation, shift etc.
Here is code example:
t = estimateRigidTransform(new, old, 0); // 0 means not all transformations (5 of 6)
if(!t.empty()){
// t(Range(0,2), Range(0,2)) = Mat::eye(2, 2, CV_64FC1); // turning off rotation
// t.at<double>(0,2) = 0; t.at<double>(1,2) = 0; // turning off shift dx and dy
tAvrg = tAvrg*a + t*(1-a); // a - smooth level in [0;1] range, play with it
warpAffine(new, stable, tAvrg, Size(new.cols, new.rows));
}

Using a custom C++ extension with python

I have a problem with this code:
#include "PolyVoxCore/MaterialDensityPair.h"
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
#include "PolyVoxCore/SurfaceMesh.h"
#include "PolyVoxCore/SimpleVolume.h"
#include "geomVertexData.h"
#include "geomVertexWriter.h"
#include "geomTriangles.h"
#include "py_panda.h"
#include "pandaNode.h"
#include "geomNode.h"
//Use the PolyVox namespace
using namespace PolyVox;
using namespace std;
static void createSphereInVolume(SimpleVolume<MaterialDensityPair44>& volData, float fRadius)
{
//This vector hold the position of the center of the volume
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
//This three-level for loop iterates over every voxel in the volume
for (int z = 0; z < volData.getWidth(); z++)
{
for (int y = 0; y < volData.getHeight(); y++)
{
for (int x = 0; x < volData.getDepth(); x++)
{
//Store our current position as a vector...
Vector3DFloat v3dCurrentPos(x,y,z);
//And compute how far the current position is from the center of the volume
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
uint8_t uDensity = 0;
uint8_t uMaterial = 0;
//If the current voxel is less than 'radius' units from the center then we make it solid.
if(fDistToCenter <= fRadius)
{
//Our new density value
uDensity = VoxelTypeTraits<MaterialDensityPair44>::maxDensity();
uMaterial = 1;
}
//Get the old voxel
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
//Modify the density and material
voxel.setDensity(uDensity);
voxel.setMaterial(uMaterial);
//Write the voxel value into the volume
volData.setVoxelAt(x, y, z, voxel);
}
}
}
}
static PyObject* CreateSphere(PyObject* self, PyObject* args)
{
PyObject* pandaNodeWrapper;
if (!PyArg_ParseTuple(args, "0", &pandaNodeWrapper))
return NULL;
//Create an empty volume and then place a sphere in it
SimpleVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
createSphereInVolume(volData, 30);
//Extract the surface
SurfaceMesh<PositionMaterialNormal> mesh;
CubicSurfaceExtractorWithNormals<SimpleVolume, MaterialDensityPair44 > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
surfaceExtractor.execute();
const vector<PositionMaterialNormal>& vertices = mesh.getVertices();
const vector<uint32_t>& indices = mesh.getIndices();
CPT(GeomVertexFormat) vertexFormat = GeomVertexFormat::get_v3n3();
PT(GeomVertexData) vertexData = new GeomVertexData("ProceduralMesh", vertexFormat, GeomEnums::UH_static);
GeomVertexWriter vertex, normal;
vertex = GeomVertexWriter(vertexData, "vertex");
normal = GeomVertexWriter(vertexData, "normal");
for(vector<PositionMaterialNormal>::const_iterator it = vertices.begin(); it != vertices.end(); ++it)
{
vertex.add_data3f(it->position.getX(), it->position.getY(), it->position.getZ());
normal.add_data3f(it->normal.getX(), it->position.getY(), it->position.getZ());
}
PT(GeomTriangles) chunk = new GeomTriangles(GeomEnums::UH_static);
for(int i = 0; i < indices.size(); ++i)
{
chunk->add_vertex(indices[i]);
}
PT(Geom) geom = new Geom(vertexData);
geom->add_primitive(chunk);
PT(GeomNode) geomNode = new GeomNode("chunk");
PandaNode* node = ((PandaNode*)((Dtool_PyInstDef*)pandaNodeWrapper)->_ptr_to_object);
node->add_child(geomNode);
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{"CreateSphere", CreateSphere, METH_VARARGS, "CreateSphere"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initpolyvox(void)
{
(void) Py_InitModule("polyvox", module_methods);
}
It's a c++ extension module i'm trying to write, i used the setup.py method to compile it and install it, the problem is that when i import it in python and run it, python says "SystemError: dynamic module not initialized properly".
I know that this error should be that module name doesn't correspond with the init function name, but it isn't like that if you see the code. So what could be the problem?
I'm on Windows 7, using python 2.7.2, the module is compiled on VS2008 but it requires some .lib i had to compile with vs2010 since some modern c++ features are required.