16 bit object names?
Posted: Fri Aug 26, 2016 9:21 pm
How easy or difficult would it be to implement a version of Irrlicht that uses wide characters rather than single byte characters for object names?
Official forum of the Irrlicht Engine
https://irrlicht.sourceforge.io/forum/
Code: Select all
class APPCORE_EXPORT BaseAppObject
{
...
public:
virtual const char* appObjectName() const = 0;
...
};
LOL. That is what I just looked into. I just found the places in the code to make this change to use QChar as the base character. I am going to try that.hendu wrote:Well sure, you can also modify irr to use QChar, and it's not a terrible amount of work.
To me the issue isn't the time. It is the simplicity of the code and the ability to boil it down to once interface. In my experience that gives a lot more flexibility in the long run.hendu wrote:But given the slowness of strings in general, would the overhead of conversion to 16-bit at read time matter?
Code: Select all
//! recursive method for going through all scene nodes
void CSLevel::getPickedNodeBB(ISceneNode* root,
core::line3df& ray, s32 bits, bool noDebugObjects,
f32& outbestdistance, ISceneNode*& outbestnode, long ot)
{
const ISceneNodeList& children = root->getChildren();
const core::vector3df rayVector = ray.getVector().normalize();
ISceneNodeList::ConstIterator it = children.begin();
for (; it != children.end(); ++it)
{
ISceneNode* current = *it;
if ((noDebugObjects ? !current->isDebugObject() : true))
{
CSObject* obj = getObjectFromNode(current);
if (!obj) return;
if ((current->isVisible()) && (obj->isObjectType(ot)))
{
// Assume that single-point bounding-boxes are not meant for collision
const core::aabbox3df & objectBox = current->getBoundingBox();
if (objectBox.isEmpty())
continue;
// get world to object space transform
core::matrix4 worldToObject;
if (!current->getAbsoluteTransformation().getInverse(worldToObject))
continue;
// transform vector from world space to object space
core::line3df objectRay(ray);
worldToObject.transformVect(objectRay.start);
worldToObject.transformVect(objectRay.end);
// Do the initial intersection test in object space, since the
// object space box test is more accurate.
if (objectBox.isPointInside(objectRay.start))
{
// use fast bbox intersection to find distance to hitpoint
// algorithm from Kay et al., code from gamedev.net
const core::vector3df dir = (objectRay.end - objectRay.start).normalize();
const core::vector3df minDist = (objectBox.MinEdge - objectRay.start) / dir;
const core::vector3df maxDist = (objectBox.MaxEdge - objectRay.start) / dir;
const core::vector3df realMin(core::min_(minDist.X, maxDist.X), core::min_(minDist.Y, maxDist.Y), core::min_(minDist.Z, maxDist.Z));
const core::vector3df realMax(core::max_(minDist.X, maxDist.X), core::max_(minDist.Y, maxDist.Y), core::max_(minDist.Z, maxDist.Z));
const f32 minmax = core::min_(realMax.X, realMax.Y, realMax.Z);
// nearest distance to intersection
const f32 maxmin = core::max_(realMin.X, realMin.Y, realMin.Z);
const f32 toIntersectionSq = (maxmin>0 ? maxmin*maxmin : minmax*minmax);
if (toIntersectionSq < outbestdistance)
{
outbestdistance = toIntersectionSq;
outbestnode = current;
// And we can truncate the ray to stop us hitting further nodes.
ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq));
}
}
else
if (objectBox.intersectsWithLine(objectRay))
{
// Now transform into world space, since we need to use world space
// scales and distances.
core::aabbox3df worldBox(objectBox);
current->getAbsoluteTransformation().transformBox(worldBox);
core::vector3df edges[8];
worldBox.getEdges(edges);
/* We need to check against each of 6 faces, composed of these corners:
/3--------/7
/ | / |
/ | / |
1---------5 |
| 2- - -| -6
| / | /
|/ | /
0---------4/
Note that we define them as opposite pairs of faces.
*/
static const s32 faceEdges[6][3] =
{
{ 0, 1, 5 }, // Front
{ 6, 7, 3 }, // Back
{ 2, 3, 1 }, // Left
{ 4, 5, 7 }, // Right
{ 1, 3, 7 }, // Top
{ 2, 0, 4 } // Bottom
};
core::vector3df intersection;
core::plane3df facePlane;
f32 bestDistToBoxBorder = FLT_MAX;
f32 bestToIntersectionSq = FLT_MAX;
for (s32 face = 0; face < 6; ++face)
{
facePlane.setPlane(edges[faceEdges[face][0]],
edges[faceEdges[face][1]],
edges[faceEdges[face][2]]);
// Only consider lines that might be entering through this face, since we
// already know that the start point is outside the box.
if (facePlane.classifyPointRelation(ray.start) != core::ISREL3D_FRONT)
continue;
// Don't bother using a limited ray, since we already know that it should be long
// enough to intersect with the box.
if (facePlane.getIntersectionWithLine(ray.start, rayVector, intersection))
{
const f32 toIntersectionSq = ray.start.getDistanceFromSQ(intersection);
if (toIntersectionSq < outbestdistance)
{
// We have to check that the intersection with this plane is actually
// on the box, so need to go back to object space again.
worldToObject.transformVect(intersection);
// find the closest point on the box borders. Have to do this as exact checks will fail due to floating point problems.
f32 distToBorder = core::max_(core::min_(core::abs_(objectBox.MinEdge.X - intersection.X), core::abs_(objectBox.MaxEdge.X - intersection.X)),
core::min_(core::abs_(objectBox.MinEdge.Y - intersection.Y), core::abs_(objectBox.MaxEdge.Y - intersection.Y)),
core::min_(core::abs_(objectBox.MinEdge.Z - intersection.Z), core::abs_(objectBox.MaxEdge.Z - intersection.Z)));
if (distToBorder < bestDistToBoxBorder)
{
bestDistToBoxBorder = distToBorder;
bestToIntersectionSq = toIntersectionSq;
}
}
}
// If the ray could be entering through the first face of a pair, then it can't
// also be entering through the opposite face, and so we can skip that face.
if (!(face & 0x01))
++face;
}
if (bestDistToBoxBorder < FLT_MAX)
{
outbestdistance = bestToIntersectionSq;
outbestnode = current;
// If we got a hit, we can now truncate the ray to stop us hitting further nodes.
ray.end = ray.start + (rayVector * sqrtf(outbestdistance));
}
}
}
// Only check the children if this node is visible.
getPickedNodeBB(current, ray, bits, noDebugObjects, outbestdistance, outbestnode, ot);
}
}
}
Wow. Thanks! As I said, I made some changes today to see how involved it would be There are a lot more changes than I originally thought (compiler counted 1000+ errors because of missing conversion issue) but it would be doable in the long run Many of those issues were repeated header lines. I think for my initial prototyping I may use a temporary workaround that is based on wide characters rather than 8 bit ones. That way the change will be compatible no matter whose changes I use.CuteAlien wrote:To answer the original question - it wouldn't be difficult. But it changes the library interface and I only do that when the gain is large enough and there are no other workarounds.
But in the long run it might be a good idea. So when we switch to stl in next Irrlicht version (which breaks interfaces anyway) I'll consider it (aka switching to std::wstring).
I'm not sure why Niko used 8-bit here when he worked with 16-bit characters in other places. Maybe because he considered this more of a label than real text (just guessing).
Code: Select all
typedef string<QChar> stringw