Scaling a NodePath in terms of x/y/z offset dimensions?

Quick question (I hope):

From what I understand, a model’s NodePath’s scale will always start out as 1.0 by definition - its actual dimensions depend entirely on whatever the model was exported as. Is there a built-in way of working with object dimensions in the same “units” as their coordinates? (this is handy for forcing canned models of varying sizes to what their actual desired size).

What I’ve been doing so far is, for getting the actual dimenions:

pMin, pMax = np.getTightBounds()
dimensions = pMax - pMin

Then to coerce the model to new absolute dimensions:

targetDimensions = Vec3(10.0, 20.0, 40.0) # for example
np.setScale(targetDimenions/dimensions)

Is that about as easy as it gets or am I missing a built-in method?

If so, is there a “safe” method of extending the NodePath class with user utility methods, or should I just make something like

myutils.getDims(np, [refNode])
myutils.setDims(np, [refNode], *dimensions)

Do you not have access to the original model files? This is really the sort of thing that should be done in the files, not Panda3d.

Even if you don’t, it should be fairly easy to write a quick python file to read the egg file, find all vertex positions, and scale them by a certain amount before writing them back out. That will have the same effect.

Edit: To clarify your understanding of models. They don’t necessarily start with a scale of 1. Each group in the egg file has a transform matrix in it, and this matrix can have a scale in it that will get applied automatically when loaded. You could probably edit the transform matrix by hand to introduce a scaling without touching the vertices. I don’t know which values to change to do that, though.

That sounds… far harder in every possible way then the getTightBounds based math… :open_mouth: I didn’t realize models can have their own scale info however, thanks for the heads up. It can simply be dealt with by multiplying the scale factor above with getScale()'s output first.

Having said that, you are probably right - it’s unlikely you’d ever have to do this with “production” models. Well a quick way of doing getDims() would still be handy, but it’s a minor saving (2 lines into 1).

It sounds appealing to make a set_dimensions method, but this would have to call get_tight_dimensions every time, which can be rather slow. Hiding this abstraction might give people the wrong idea that it’s a fast operation.

You can inherit a class from NodePath, but you have to be aware of one thing: panda3d gives you always a generic, fresh NodePath object as a return value. You can use a pythonTag to store a reference to you subclass, but be aware that this is a cyclic reference you need to break before you remove the np.

http://www.panda3d.org/manual/index.php/Subclassing

You don’t need to inherit from NodePath in order to add extension methods. Take a look at how getTightBounds is implemented in direct/src/extensions_native/NodePath_extensions.py.