I want to publish a 3D array as a std_msgs::Float32MultiArray in ROS. It should have the dimensions [1920,1080,10], which corresponds to [image_width, image_height, depth].
However, I didn't find a clear documentation on how to initialize and fill this multi-array. Here is what I did so far:
std_msgs::Float32MultiArray my_array;
my_array.layout.dim.push_back(std_msgs::MultiArrayDimension());
my_array.layout.dim[0].label = "width";
my_array.layout.dim[0].size = 1920;
my_array.layout.dim.push_back(std_msgs::MultiArrayDimension());
my_array.layout.dim[1].label = "height";
my_array.layout.dim[1].size = 1080;
my_array.layout.dim.push_back(std_msgs::MultiArrayDimension());
my_array.layout.dim[2].label = "depth";
my_array.layout.dim[2].size = 10;
my_array.layout.data_offset = 0;
my_array.data.clear();
// Initialize the data with 0
// ???
// Fill in values from a list to this array
// PSEUDOCODE
for (point &p : 3d_points_buffer)
{
// Fill the array like this:
//my_array[p.x, p.y, p.z] = p.value;
//???
}
Unfortunately, this is as far as I get. Could anyone show me how I could initialize the whole data array with zeros and how to set a specific entry my_array[x,y,z] to a certain value?
Thank you very much!
Related
I want to use ITK to Filter a 3D volume that is in a contiguous float array. I want to apply the Curvature Flow Filter as shown in this example.
I don't know how to interface my float array with ITK and then to get a float array out on the other side. Will it modify the data in place? How does it work?
Here is some code to demonstrate what I am trying to do.
#include "itkCurvatureFlowImageFilter.h"
int main(int argc, char *argv[])
{
float *my_array; // I have an array I have generated elsewhere
// This is a 3D volume in order XYZ with these dimensions along each axis
size_t num_x = 125;
size_t num_y = 250;
size_t num_z = 125;
size_t num_elements = num_x * num_y * num_z;
float voxel_size = 8e-3; // 8 mm voxels
constexpr unsigned int Dimension = 3;
// convert to an itk image
// itkimage = ???
using InputPixelType = float;
using InputImageType = itk::Image<InputPixelType, Dimension>;
const int numberOfIterations = 10;
const InputPixelType timeStep = 0.05;
using FilterType = itk::CurvatureFlowImageFilter<InputImageType, InputImageType>;
FilterType::Pointer filter = FilterType::New();
filter->SetInput(itkimage);
filter->SetNumberOfIterations(numberOfIterations);
filter->SetTimeStep(timeStep);
// now I want to put the filter result back in th array
filter->GetOutput();
// Is the data modified in place? How can I get a regular float array out??
return EXIT_SUCCESS;
}
itk::ImportImageFilter is used for the purpose of representing some array as an image. Look at the examples linked in the documentation.
As CurvatureFlowImageFilter derives from InPlaceImageFilter, and both your input and output pixel type are same (float), it can run in-place. But you still need to request that:
itkimage = import...;
...
filter->SetInput(itkimage );
// set other parameters
filter->SetInPlace(true);
filter->Update();
itkimage = filter->GetOutput();
I am working in C++ SDL lib. And I am trying to dynamically create a number of rectangles. But it doesn't work. The only solution I found over searching stackoverflow.com been to create a constant value, which I don't want to.
Can anyone help me?
This is my code:
void lvl001(){
max_score = 20;
count_enemies = 2;
SDL_Surface *enemie;
SDL_Rect enemies_sources[no] , enemies[no];
enemie = SDL_LoadBMP("player.bmp");
for( int count = 1; count <= no ; count++ ){
enemies_sources[count].x = 0;
}
}
And one more thing. If there would be an solution to this, then how should I proceed if I want to blit it (SDL_Blit...)?
In C++, dynamic arrays are created using std::vector<T>, and looped through using the range-based for when you don't care about the indices:
std::vector<SDL_Rect> enemies_sources(no);
std::vector<SDL_Rect> enemies(no);
for (auto& source : enemies_sources)
{
source.x = 0;
}
In C++, I have an uint8 buffer of the length [len]. When allocating a single buffer I do this:
uint8 *buffer= new uint8[len];
What's the syntax for allocating an array of such buffers? This gives me a syntax error:
uint8** buffers = new uint8[len]*[bufferCount];
The way you initialize a 2d array is as follows:
uint8** buffers = new uint8*[bufferCount];
for (int i = 0; i < bufferCount; i++)
buffers[i] = new uint8[len];
#include <vector>
using byte_vector = std::vector<uint8_t>;
using byte_vector_vector = std::vector<byte_vector>;
// example of a 1-dimension vector
auto v1 = byte_vector(len, inital_value);
// example of a [2, len] vector
auto v_of_v = byte_vector_vector {
byte_vector(len, initial_value),
byte_vector(len, initial_value)
};
// print the uint8 at (0,1)
std::cout << v_ov_v[0][1] << std::endl;
You asked
What's the syntax for allocating an array of such buffers?
You can use:
uint8** buffers = new uint8*[bufferCount];
However, use this only if std::vector is absolutely not an option for some reason.
Lately, I have been working to resurrect an old open source game. My main problem is it uses a custom format: VW3D. The following code snippet is used to load the model from its File System. Is it possible to reconstruct the model format (and convert it) from the below snippet? I have no idea how I would go about this and would appreciate any pointers. My hope is to be able to construct a script to convert to/from this format (Planning for vw3d to obj and vice versa)
void eModel3D::ReadVW3D(const char *nName)
{
eFILE *file = 0;
file = vw_fopen(nName);
if (file == 0) return;
size_t SizeB = strlen(nName)+1;
Name = new char[SizeB];
strcpy(Name, nName);
// пропускаем заголовок / skip header
file->fread(&DrawObjectCount, 4, 1);
// читаем, сколько объектов read how many objects
file->fread(&DrawObjectCount, sizeof(int), 1);
DrawObjectList = new eObjectBlock[DrawObjectCount];
unsigned int GlobalRangeStart = 0;
// для каждого объекта for each object
for (int i=0; i<DrawObjectCount; i++)
{
DrawObjectList[i].RangeStart = GlobalRangeStart;
// FVF_Format
file->fread(&(DrawObjectList[i].FVF_Format),sizeof(int),1);
// Stride
file->fread(&(DrawObjectList[i].Stride),sizeof(int),1);
// VertexCount на самом деле, это кол-во индексов на объект In fact, this count of the index on an object
file->fread(&(DrawObjectList[i].VertexCount),sizeof(int),1);
GlobalRangeStart += DrawObjectList[i].VertexCount;
// Location
file->fread(&(DrawObjectList[i].Location),sizeof(float)*3,1);
// Rotation
file->fread(&(DrawObjectList[i].Rotation),sizeof(float)*3,1);
// рисуем нормально, не прозрачным draw a fine, not transparent
DrawObjectList[i].DrawType = 0;
// вертексный буфер Vertex Buffer
DrawObjectList[i].VertexBufferDestrType = 0;
DrawObjectList[i].VertexBuffer = 0;
DrawObjectList[i].VertexBufferVBO = 0;
// индексный буфер Index buffer
DrawObjectList[i].IndexBuffer = 0;
DrawObjectList[i].IndexBufferVBO = 0;
}
// получаем сколько всего вертексов get how many verticies
int VCount = 0;
file->fread(&VCount,sizeof(int),1);
// собственно данные actual data
GlobalVertexBuffer = new float[VCount*DrawObjectList[0].Stride];
file->fread(GlobalVertexBuffer, VCount*DrawObjectList[0].Stride*sizeof(float),1);
// индекс буфер I.B.
GlobalIndexBuffer = new unsigned int[GlobalRangeStart];
file->fread(GlobalIndexBuffer, GlobalRangeStart*sizeof(unsigned int),1);
// делаем общее VBO making the total VBO
GlobalVertexBufferVBO = new unsigned int;
if (!vw_BuildVBO(VCount, GlobalVertexBuffer, DrawObjectList[0].Stride, GlobalVertexBufferVBO))
{
delete GlobalVertexBufferVBO; GlobalVertexBufferVBO=0;
}
// делаем общий индекс VBO makes the overall index VBO
GlobalIndexBufferVBO = new unsigned int;
if (!vw_BuildIndexVBO(GlobalRangeStart, GlobalIndexBuffer, GlobalIndexBufferVBO))
{
delete GlobalIndexBufferVBO; GlobalIndexBufferVBO=0;
}
// устанавливаем правильные указатели на массивы establish the correct pointers to arrays
for (int i=0; i<DrawObjectCount; i++)
{
DrawObjectList[i].VertexBuffer = GlobalVertexBuffer;
DrawObjectList[i].VertexBufferVBO = GlobalVertexBufferVBO;
DrawObjectList[i].IndexBuffer = GlobalIndexBuffer;
DrawObjectList[i].IndexBufferVBO = GlobalIndexBufferVBO;
}
vw_fclose(file);
}
The code you've posted is pretty straight-forward. I especially enjoy the Cyrillic/English comment pairs. You probably can't fully convert back and forth between VW3d and Obj formats. It looks like VW3d is exclusively about geometry while the Obj format provides for textures, normals, and material properties too. Furthermore, I think Obj stores one object per file, while VW3d stores multiple objects, potentially re-using the same object geometry multiple times with different translations and rotations.
The functions, vw_BuildVBO and vw_BuildIndexVBO, are doing some key work, although I can guess at what they're doing, it'd be better to have access to them.
The other potential problem is in the 'Rotation' variable. It seems to be an array holding 3 floats. That suggests that they're using Euler rotation, but there are multiple ways to do that. If you wanted to make sure to orient the objects correctly, you'd need to understand a little more about how those three floats are used when drawing the object.
I'm developing a 3D game using SDL and OpenGL on Ubuntu 9.04 using Eclipse CDT. I've got a class to hold the mesh data in vectors for each type. Such as Vertex, Normal, UVcoord (texture coordinates), as well as a vector of faces. Each face has 3 int vectors which hold indexes to the other data. So far my game has been working quite well at rendering at nice rates. But then again I only had less then one hundred vertexes among two objects for testing purposes.
The loop accessing this data looks like this:
void RenderFace(oFace face)
{
/*
* More Stuff
*/
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
glNormal3f(nvert.X, nvert.Y, nvert.Z);
glTexCoord2f(tvert.U, tvert.V);
glVertex3f(scale * gvert.X, scale * gvert.Y, scale * gvert.Z);
}
/*
* More Stuff
*/
}
There is a loop that calls the renderFace() function which includes the above for loop. The minus one is because Wavefront .obj files are 1 indexed (instead of c++ 0 index). Anyway, I discovered that once you have about 30 thousand or so faces, all those calls to glVertex3f() and the like slow the game down to about 10 FPS. That I can't allow. So I learned about vertex arrays, which require pointers to arrays. Following the example of a NeHe tutorial I continued to use my oVertice class and the others. Which just have floats x, y, z, or u, v. So I added the same function above to my OnLoad() function to build the arrays which are just "oVertice*" and similar.
Here is the code:
bool oEntity::OnLoad(std::string FileName)
{
if (!obj.OnLoad(FileName))
{
return false;
}
unsigned int flsize = obj.TheMesh.GetFaceListSize();
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
oFace face = obj.TheMesh.GetFace(0);
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
unsigned int counter = 0;
unsigned int temp = 0;
for (unsigned int flIndex = 0; flIndex < obj.TheMesh.GetFaceListSize(); flIndex++)
{
face = obj.TheMesh.GetFace(flIndex);
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
temp = face.GeoVerts[fvIndex];
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
temp = face.UV_Verts[fvIndex];
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
temp = face.NrmVerts[fvIndex];
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
obj.TheMesh.VertListPointer[counter].X = gvert.X;
obj.TheMesh.VertListPointer[counter].Y = gvert.Y;
obj.TheMesh.VertListPointer[counter].Z = gvert.Z;
obj.TheMesh.UVlistPointer[counter].U = tvert.U;
obj.TheMesh.UVlistPointer[counter].V = tvert.V;
obj.TheMesh.NormListPointer[counter].X = nvert.X;
obj.TheMesh.NormListPointer[counter].Y = nvert.Y;
obj.TheMesh.NormListPointer[counter].Z = nvert.Z;
counter++;
}
}
return true;
}
The unsigned int temp variable is for debugging purposes. Apparently I don't have a default constructor for oFace that doesn't have something to initialize with. Anyway, as you can see it's pretty much that same exact routine. Only instead of calling a gl function I add the data to three arrays.
Here's the kicker:
I'm loading a typical cube made of triangles.
When I access element 16 (0 indexed) of the UV_Verts vector from the RenderFace() function I get 12.
But when I access element 16 (0 indexed) of the same UV_Verts vector from the OnLoad() function I get something like 3045472189
I am so confused.
Does anyone know what's causing this? And if so how to resolve it?
One possible reason could be that you're creating arrays with size flsize:
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
but use the arrays with indices up to flsize * face.GeoVerts.size
for (...; flIndex < obj.TheMesh.GetFaceListSize(); ...) { // flsize = GetFaceListSize
for (...; fvIndex < face.GeoVerts.size(); ...) {
...
obj.TheMesh.UVlistPointer[counter].U = ...;
...
counter++;
}
}
so your array creation code should actually be more like
obj.TheMesh.VertListPointer = new oVertice[flsize * face.GeoVerts.size()];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize * face.GeoVerts.size()];
obj.TheMesh.NormListPointer = new oNormal[flsize * face.GeoVerts.size()];