• Create Account

## Efficient way of computing faces of axially-aligned box

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

2 replies to this topic

### #1X6Herbius  Members

109
Like
0Likes
Like

Posted 04 January 2014 - 11:57 AM

Just found these forums and they look like they'd be pretty helpful for me. I'm semi-experienced in programming but fairly new to graphics specifically, so questions might seem basic while I'm getting to grips with some things.

I'm attempting to implement a primitive axially-aligned box renderable for a level editor written in Qt (C++). I'm using the Qt3D library and am intending to ensure that each renderable implements a render interface, which at the moment consists just of:

// Export to QGeometryData, in world co-ordinates.
virtual QGeometryData toGeomData() const = 0;


The QGeometryData is a Qt3D manager for vertex data. My box renderable's function looks like this:

QGeometryData RenderBox::toGeomData() const
{
// Calculate the min and max co-ordinates in world space.
QVector3D min = m_vecPosition + minimum();
QVector3D max = m_vecPosition + maximum();
QColor col = color();

// Order of vertices:
// 0. Minimum
// 1. Minimum with modified X co-ord
// 2. Minimum with modified X and Z co-ords
// 3. Minimum with modified Z co-ord
// 4. Maximum with modified Z co-ord
// 5. Maximum with modified Z and X co-ords
// 6. Maximum with modified X co-ord
// 7. Maximum
// This gives us an easy counter-clockwise winding for the top and bottom faces.

const QVector3D verts[8] =               // Taking Z as "north" and looking down on the box (Y pointing at us), we have:
{
min,                                    // Lower SW 0
QVector3D(max.x(), min.y(), min.z()),   // Lower NW 1
QVector3D(max.x(), min.y(), max.z()),   // Lower NE 2
QVector3D(min.x(), min.y(), max.z()),   // Lower SE 3
QVector3D(max.x(), max.y(), min.z()),   // Upper NW 4
QVector3D(min.x(), max.y(), min.z()),   // Upper SW 5
QVector3D(min.x(), max.y(), max.z()),   // Upper SE 6
max                                     // Upper NE 7
};

// Calculate normals for faces.
QVector3D nTop = ccwNormal(verts[5], verts[6], verts[7]);       // SW, SE, NE
QVector3D nBottom = ccwNormal(verts[0], verts[1], verts[2]);    // SW, NW, NE
QVector3D nNorth = ccwNormal(verts[7], verts[2], verts[1]);     // UNE, LNE, LNW
QVector3D nSouth = ccwNormal(verts[0], verts[3], verts[6]);     // LSW, LSE, USE
QVector3D nEast = ccwNormal(verts[7], verts[6], verts[3]);      // UNE, USE, LSE
QVector3D nWest = ccwNormal(verts[0], verts[5], verts[4]);      // LSW, USW, UNW

// Create a GeomData and add each face of the box.
QGeometryData geom;

// Top face
geom.appendVertex(verts[4], verts[5], verts[6], verts[7]);
geom.appendNormal(nTop, nTop, nTop, nTop);

// Bottom face
geom.appendVertex(verts[0], verts[1], verts[2], verts[3]);
geom.appendNormal(nBottom, nBottom, nBottom, nBottom);

// North face
geom.appendVertex(verts[7], verts[2], verts[1], verts[4]);
geom.appendNormal(nNorth, nNorth, nNorth, nNorth);

// South face
geom.appendVertex(verts[0], verts[3], verts[6], verts[5]);
geom.appendNormal(nSouth, nSouth, nSouth, nSouth);

// East face
geom.appendVertex(verts[7], verts[6], verts[3], verts[2]);
geom.appendNormal(nEast, nEast, nEast, nEast);

// West face
geom.appendVertex(verts[0], verts[5], verts[4], verts[1]);
geom.appendNormal(nWest, nWest, nWest, nWest);

// Append colour attributes.
// These will all be the same.
for ( int i = 0; i < 24; i++ )
{
geom.appendColor(col);
}

// Return the GeomData.
return geom;
}


ccwNormal() is a simple helper function that returns the normal (pointing towards the viewer) of three vectors assumed to be supplied in an anticlockwise winding order.

My question here is whether there is a more efficient/elegant way of calculating the faces of the box. Theoretically (if I've done the calculations right) this way should provide the correct vertex information, but it seems inflexible from a distance and looks like it'd be a pain to modify later on if I needed to. How acceptable is this method?

(Also, an implementation-specific question for those familiar with Qt/OpenGL: is returning a QGeometryData object the best way to implement rendering? My concerns with it are twofold: firstly, copying data from geom on the stack to the returned object might cause unnecessary overhead, especially considering that this would have to be done for every single renderable, and secondly returning a fresh object every time toGeomData() is called would be a waste of time if the render data was exactly the same as the previous frame. According to the documentation for QGeometryData the graphics data is not re-uploaded to the GPU if it hasn't changed, but if the object is being replaced by a new one each frame then it might prevent this optimisation from happening.)

### #2NumberXaero  Prime Members

2492
Like
0Likes
Like

Posted 04 January 2014 - 01:29 PM

If the box is axis aligned, why calc normals at all? The face normal will be the axis it points down. Skip the normal calc calls, which will probably save 6 sqrt()'s.

### #3X6Herbius  Members

109
Like
0Likes
Like

Posted 04 January 2014 - 02:01 PM

That's a very good point, actually. I guess I'm a bit blind to my own code.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.