[SOLVED] Getting pivot point of programmatically loaded model?

I dont have a control of the models I’m loading but I was wondering how could I get the pivot point of it? What I’m trying to achieve is to set all the models so that they’re all aligned with ground, not somehere in air or…

I can’t use templates in this project, only adding models as a:

    const entity = new pc.Entity('Entity');
        entity.addComponent('model', {
            asset: asset.resource.model
        });

Any ideas? So far normalized scale based on halfextents

        asset.ready(function(asset) {
            entity.aabb = new pc.BoundingBox();
            var meshes = entity.model.model.meshInstances;
            if (meshes.length) {
                entity.aabb.copy(meshes[0].aabb);
                for (var i = 1; i < meshes.length; i++)
                    entity.aabb.add(meshes[i].aabb);
            }

            const desiredHalfExtentsY = 1;
            const originalHalfExtentsY = entity.aabb.halfExtents.y;
            const scaleFactor = desiredHalfExtentsY / originalHalfExtentsY;

            entity.setLocalScale(scaleFactor, scaleFactor, scaleFactor);
            entity.setPosition(0, entity.aabb.center.y - 1, 0);
            pc.app.root.findByName('Root').addChild(entity);


        });

I’m not sure if I understood your question.

Isn’t the pivot point the location of the object? careful with the parenting.

If you want to align the meshes on the floor, you should work instead with the bounding box as you are already aware. You could calculate the bounding box of each of the meshes before adding them and translate their vertices vertically as necessary. That means that if your model is a desk with a computer on it, you’ll end up with a table with a computer below it, touching the floor.

The problem that the pivot point (the point position is sat from) is not always in the middle of bounding box (all meshes) for some models

Hi @Newbie_Coder,

I gather by pivot point you mean the lower on local Y point to be able to “sit” them on the ground?

Your approach seems correct, calculate the total bounding box of all mesh instances included in the model, and from there calculate your new pivot like this:

const pivot = new pc.Vec3().copy(totalAabb.center);
pivot.y -= totalAabb.halfExtents.y;

This works in case if pivot is at the bottom of model like:
Capture2
But if the pivot would be anywhere else it wouldn’t, I really think im missing something simple
Capture

If you mean you want to get the pivot point the artist has set for each model than that you only need to position the entity you instantiate from the remote asset on the ground and that’s it.

If you manually upload the model in editor and drag/drop the resulting template in the hierarchy you will see the parent entity that is created to be exactly located at the pivot point.

Too bad I can’t use templates in this specific project, nor adding any parent entities for the target entity

If you are using the legacy model component there is an internal graph node used on each mesh instance, that will have the pivot point for each model mesh.

Do you mean …model.model.meshInstances.node ?
Which property should I look at, localPosition, position or somewhere else?

Sorry it’s being a while since I last used it, I gather you need world position with getPosition().

getPosition, getLocalPoisition of mesh node always returns (0,0,0)
I wonder how the engine itself retrieves the pivot/origin point that it used while setting position

It may be using the local position and adding it to the parent entity. May I suggest that you explore using the render asset instead? The model component is being deprecated and is not receiving updates for a while.

Unfortunately there’s a reason why I’m using model component…

white it works great in editor type projects / engine-only project faced issues with render not to match collision model / weird scaling-skewing issues

Ended up using very dirty solution: iterating trough meshes positions to find the lowest point in world space

function findLowestPositionInWorldSpace(entity) {
  var meshes = entity.model.model.meshInstances;
  if (meshes.length) {
    var lowestPosition = null;

    for (var i = 0; i < meshes.length; i++) {
      var meshInstance = meshes[i];
      var mesh = meshInstance.mesh;

      var srcPositions = [];
      mesh.getPositions(srcPositions);

      var worldTransform = meshInstance.node.worldTransform;

      for (var j = 0; j < srcPositions.length; j += 3) {
        var vertexPosition = new pc.Vec3(srcPositions[j], srcPositions[j + 1], srcPositions[j + 2]);
        worldTransform.transformPoint(vertexPosition, vertexPosition);
        if (lowestPosition === null || vertexPosition.y < lowestPosition.y) {
          lowestPosition = vertexPosition.clone();
        }
      }
    }

    return lowestPosition;
  } else {
    return null; 
  }
}



var lowestPosition = findLowestPositionInWorldSpace(entity);
if (lowestPosition) {
  console.log("The lowest position in world space is:", lowestPosition);
} else {
  console.log("No meshes found in the entity's model component.");
}

const invertNumber = (num) => -num;
var invertedValue = invertNumber(lowestPosition.y);


entity.setPosition(0,invertedValue, 0);
1 Like