PDA

View Full Version : Qt3D: Most efficient way to position a plane mesh entity in space



ghorwin
10th December 2019, 17:43
Hi there,

I'm wondering whether you'd have a suggestion on how to create and position a plane in 3D space using the Qt3DExtra types.

Specifically, I have defined the target rectangular plane through points in space (p_i, i=0,1,2).

I first create a plane using Qt3DExtras::QPlaneMesh providing the width w and height h of the given plane (width and height from vectors p_2-p_0 and p_1 - p_0). The plane mesh is created in the x-z plane (positive y-axis being the normal vector), and centered around w/2 and h/2. The points t_i of the newly created plane in world coordinates corresponding the my points p_i are (-w/2, 0, -h/2), (w/2,0,-h/2), and (-w/2, 0, h/2).

Now I want to rotate and translate the plane entity to be positioned at my world coordinates p_i. My current approach involves creating a transformation matrix for world coordinates with QQuaternions and manually transforming the plane offset (w/2, h/2) (to move the lower left point of the matrix to the origin) into the mapped coordinates and add it to the local coordinate system origin p_0.

This feels kind of complicated so here's my question: can you come up with a smoother/fancy or just faster solution?

Thanks a ton,
Andreas

ghorwin
13th December 2019, 10:58
Hi all,

for your reference, here's my current solution to the problem. Can anyone do it better (shorter/faster/nicer and I mean not by removing the comments :-) ?



Qt3DCore::QEntity * createTransformedPlane(Qt3DCore::QEntity * parent, QVector3D p0, QVector3D p1, QVector3D p3) {

// vectors that span the plane
QVector3D v1 = p1-p0;
QVector3D v2 = p3-p0;

// create standard mesh in xz plane
Qt3DExtras::QPlaneMesh *planeMesh = new Qt3DExtras::QPlaneMesh();
float wx = v1.length();
float wz = v2.length();
planeMesh->setWidth(wx);
planeMesh->setHeight(wz);

// Plane entity
Qt3DCore::QEntity * planeEntity = new Qt3DCore::QEntity(parent);
// add the mesh to the entity
planeEntity->addComponent(planeMesh);


// transformation

// compute normal vector
QVector3D n1 = QVector3D::crossProduct(v1,v2);

// determine rotation matrix to align normal vector of plane with normal vector of generated plane (i.e. y-axis)
QVector3D n2(0,1,0);

QQuaternion rot = QQuaternion::rotationTo(n2, n1);

// now we transform the w1 vector (corresponding to the v1 vector) into the target plane
QVector3D w1(-1,0,0);
// Mind: PlaneMesh is generated in x-z plane, with bottom-left point at q0=(w/2, 0, -h/2)
// If numbered counter clock-wise, the next point is at q1=(-w/2, 0, -h/2) and the normalized vector w1 between q0 and q1
// is w1=(-1,0,0)

QVector3D w1Rotated = rot.rotatedVector(w1);

// now we need to compute the rotation matrix to align the w1 vector with the v1 vector
QQuaternion rot2 = QQuaternion::rotationTo(w1Rotated, v1);

// combine both rotations (mind the matrix multiplication order!)
QQuaternion planeRotation = rot2*rot;

// anchor point of generated mesh
QVector3D q0(wx/2, 0, -wz/2);
// Point q0 after rotation
QVector3D q0rot = planeRotation.rotatedVector(q0);

//translation to target anchor point
QVector3D transVec = p0 - q0rot;

// create transformation
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
transform->setTranslation(transVec);
transform->setRotation(planeRotation);

// and set it as component
planeEntity->addComponent(transform);

return planeEntity;
}