Primitive for drawing complex 3D structures ?

Problems building or running the engine, queries about how to use features etc.
Post Reply
Tiago
Gnoblar
Posts: 11
Joined: Tue Apr 19, 2005 3:11 am
Location: Macaé, BRAZIL

Primitive for drawing complex 3D structures ?

Post by Tiago »

Hi,

I need a primitive for drawing a structure like this one :

Image


I tried using vertex with OT_POINT_LIST , but the points are not scaled when the camera gets near them (I know, they are just points)... should I use cubes ? How to paint them with a color ?
That image is 300x300x300 , so the primitive has to be fast.

I never used 3d engines before and I'm having a hard time here, could anybody give me a hint ? :roll:


Thanks !
User avatar
elmer
Gnoblar
Posts: 21
Joined: Fri Apr 15, 2005 2:12 am

Post by elmer »

Elmer is not like the rest of the elephants in the jungle, he's a multi-coloured patchwork elephant!
Tiago
Gnoblar
Posts: 11
Joined: Tue Apr 19, 2005 3:11 am
Location: Macaé, BRAZIL

Post by Tiago »

Yes, I saw the Volumetric Texture demo, but my app is supposed to run on old machines too...I need another way to do it.

That image is a 3D matrix of 0's and 1's generated on the fly (it's the microstructure of a rock generated from thin section microphotographies)... all I need is to plot voxels on the screen (the 1's in the 3D matrix).

Image
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2
Contact:

Post by Kencho »

You have to build it yourself (if it's based on a binary matrix, then you can generate the mesh via-code). I saw some papers about slicing to draw volumetric textures. Maybe CSG could be used too (Constructive Solid Geometry).
Image
lodi
Greenskin
Posts: 103
Joined: Sat Jul 24, 2004 7:06 pm

Post by lodi »

Hurray for voxels!

Try googling for 'Marching Cubes Algorithm'.
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

I have an implementation of marching cubes (and tetrahedrons, although uglier) lying around for Ogre. I never released it, though. It was written for 0.15.x and maybe some fixes are necessary to get it running in 1.0.x. I can send it to you if you want...
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

Or send it to us! :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

Well, here it is then. :)

isosurfaces.zip

I can't remember what state the code is in; I think I was playing around with some shaders in there, too. And for reason I even documented it with Doxygen. Consider this code in the public domain.

BTW, isn't there some patent thingies with the marching cubes algorithm? :?
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

Subject 5.11: What is the status of the patent on the "marching cubes" algorithm?
United States Patent Number: 4,710,876
Date of Patent: Dec. 1, 1987
Inventors: Harvey E. Cline, William E. Lorensen
Assignee: General Electric Company
Title: "System and Method for the Display of Surface Structures Contained Within the Interior Region of a Solid Body"
Filed: Jun. 5, 1985

United States Patent Number: 4,885,688
Date of Patent: Dec. 5, 1989
Inventor: Carl R. Crawford
Assignee: General Electric Company
Title: "Minimization of Directed Points Generated in Three-Dimensional Dividing Cubes Method"
Filed: Nov. 25, 1987
Taken from here
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Tiago
Gnoblar
Posts: 11
Joined: Tue Apr 19, 2005 3:11 am
Location: Macaé, BRAZIL

Post by Tiago »

Hi,

DWORD, this algorithm is exactly what I needed ! I have no words to express my gratitude, man. Thank you ! :D

Here are the changes in Metaball.cpp to my Meta3DMatrix.cpp, I kept the line :
mIsoSurfaces[0]->setIsoValue(0.15);
in CustomFrameListener.cpp setting the threshold value to 0.15.

for (size_t z = z0; z <= z1; ++z) {
for (size_t y = y0; y <= y1; ++y) {
for (size_t x = x0; x <= x1; ++x) {
size_t index = dataGrid->getGridIndex(x, y, z);
// generate a non-correlated(random)
//porous media with porosity=90% for testing
if ((rand() % 100) > 90) {
values[index] = 0.81;
}
}
}
}

Here's the result with a 40x40x40 grid :

Image



:?: :?: :?:
I have a million questions, though, so I'm just going to ask the more pressing ones :
1) I need a larger grid (300x300x300 at least) and I'm getting too many vertexes, so I tried changing index buffer allocation with :

HardwareIndexBuffer::IT_32BIT

is it as simple as changing that ? It crashed at runtime because DX7 doesn't support 32 bit indexes, are they supported by opengl and DX9 ?

2) when I set values[index] to a value very close and greather than mIsoValue I get a cardboard looking structure (without volume). Replacing the "if" in the code above with :

if(z=z0) values[index]=0.15;

I get this (the iso surface on the left has a smaller threshold, the one in the right has a threshold equals to 0.15):

Image
I took a look at the marching cubes algorithm and i think this is an unexpected behavior... is it supposed to be happening ?

3) What are the gradients used for ?


Thanks a lot,
Tiago
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

Tiago wrote:DWORD, this algorithm is exactly what I needed ! I have no words to express my gratitude, man. Thank you ! :D
No problem. :)
Tiago wrote:1) I need a larger grid (300x300x300 at least) and I'm getting too many vertexes, so I tried changing index buffer allocation with :

HardwareIndexBuffer::IT_32BIT

is it as simple as changing that ? It crashed at runtime because DX7 doesn't support 32 bit indexes, are they supported by opengl and DX9 ?
OGL and D3D9 support 32 bit indices. But I don't think you'll get very good performance using a grid that big. Maybe another technique would be better for such large datasets.
Tiago wrote:2) when I set values[index] to a value very close and greather than mIsoValue I get a cardboard looking structure (without volume). Replacing the "if" in the code above with :

if(z=z0) values[index]=0.15;

I get this (the iso surface on the left has a smaller threshold, the one in the right has a threshold equals to 0.15):

(...)

I took a look at the marching cubes algorithm and i think this is an unexpected behavior... is it supposed to be happening ?
I don't really know. But there's a limit to how small structures can be polygonized.
Tiago wrote:3) What are the gradients used for ?
I used them for calculating normals but it didn't work very well, and I can't remember if they're actually used for anything as it is now. IIRC you can choose to calculate normals using the gradient.
Tiago
Gnoblar
Posts: 11
Joined: Tue Apr 19, 2005 3:11 am
Location: Macaé, BRAZIL

Post by Tiago »

Thanks a bunch, Christian !

Code is working fine now... 8)

But my program slows to a crawl when I use a grid too large, even when the window where the 3d model is displayed is minimized (it's a MDI windowed application using Qt)... maybe the rendering loop is still going when the window looses focus. Anyway, I'll try to solve that another day.

Here's how to change it to 32 bit, should anyone be interested in doing it. Took me a while since I'm new to 3d and Ogre.

1) Create a new member variable
HardwareIndexBuffer::IndexType mNumberBitsIndexBuffer;

2)Initialize in the constructor
mNumberBitsIndexBuffer = HardwareIndexBuffer::IT_32BIT;

3) In DynamicRenderable.cpp, change the assert to :
if (mNumberBitsIndexBuffer == HardwareIndexBuffer::IT_32BIT) {
OgreAssert(indexCount <= std::numeric_limits<unsigned int>::max(), "indexCount exceeds 32 bit");
}
else {
OgreAssert(indexCount <= std::numeric_limits<unsigned short>::max(), "indexCount exceeds 16 bit");
}

4) At buffer creation :
mRenderOp.indexData->indexBuffer =
HardwareBufferManager::getSingleton().createIndexBuffer(
///////////////HardwareIndexBuffer::IT_16BIT,
mNumberBitsIndexBuffer,
mIndexBufferCapacity,
HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?

5) At isosurface.cpp :
// Fill hardware index buffer
if (mNumberBitsIndexBuffer == HardwareIndexBuffer::IT_32BIT) {
// we are using 32 bit indexes now, so "unsigned int" must be used instead of "unsigned short"
unsigned int* pIndex = static_cast<unsigned int*>(ibuf->lock(0, mRenderOp.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD));
for (IsoTriangleVector::iterator x = mIsoTriangles.begin(); x != mIsoTriangles.end(); ++x)
{
*pIndex++ = static_cast<unsigned int>(mIsoVertexIndices[x->vertices[0]]);
*pIndex++ = static_cast<unsigned int>(mIsoVertexIndices[x->vertices[1]]);
*pIndex++ = static_cast<unsigned int>(mIsoVertexIndices[x->vertices[2]]);
}
}

else {
unsigned short* pIndex = static_cast<unsigned short*>(ibuf->lock(0, mRenderOp.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD));
for (IsoTriangleVector::iterator x = mIsoTriangles.begin(); x != mIsoTriangles.end(); ++x)
{
*pIndex++ = static_cast<unsigned short>(mIsoVertexIndices[x->vertices[0]]);
*pIndex++ = static_cast<unsigned short>(mIsoVertexIndices[x->vertices[1]]);
*pIndex++ = static_cast<unsigned short>(mIsoVertexIndices[x->vertices[2]]);
}
}
Post Reply