Compass effect on aspect2d squashes my object ?

Hi, folks.
I have a simple question here. I have a compass showing the north direction (and a mini map in plan), parented to aspect2d. I need the north symbol stays upright, no matter how the compass rotates. I’ve tried to use compass effect, but it squashes the north symbol, the peak is at 90 and 270 degrees. I’ve tried some sort of possible references : aspect2d, render2d, and even my HUD object, but to no avail. Is this a bug or something is definitely wrong inside my head ?
Meantime, I solve this by negating the north symbol’s roll, each time I update the compass’ roll.

Thanks in advance.

Hmm, that ought to work, though I’ve never tried using a CompassEffect under aspect2d. But it’s fundamentally no different from putting one under render. I guess you do have to be careful to get the coordinate system right.

Have you experimented further with this?


I’ve tried these :

  • originally, the north symbol is an OnscreenText. I thought it could be the problem, so I replaced it with a card and a 3d object, and they’re squashed too
  • I relocated it directly under the compass (originally it’s under a locator), no changes
  • I tried both approaches : CompassEffect.make + setEffect, and simply setCompass, no changes
    The object is downscaled along Z axis, and upscaled horisontally.

OK, I tried it out, and I see what’s happening. When you parent a node under aspect2d, it inherits the scale from aspect2d. That’s a non-uniform scale, so it scales your object differently in X and Z. But here’s the kicker–as your object rotates around under aspect2d, the relative X and Z axes change.

Normally you forget about the non-uniform scale of aspect2d, because the window itself is non-uniformly scaled, and the scale of aspect2d exactly compensates for that scale.

Now. A CompassEffect, by default, counter-rotates the object you apply it to, but doesn’t mess with its scale. So when you counter-rotate an object that has had the non-uniform aspect2d scale applied to it, you rotate the scale with it! Suddenly the aspect2d scale no longer exactly compensates for the scale, and it looks all distorted.

The easy solution is to ask the CompassEffect to fix up the scale too. This is the sort of CompassEffect you will create:

obj.setEffect(CompassEffect.make(aspect2d, CompassEffect.PRot | CompassEffect.PScale))

For reference, here’s the sample program I wrote to test this out:

from direct.directbase.DirectStart import *
from direct.interval.IntervalGlobal import *
from pandac.PandaModules import *
import random

# Make a polygon, and bounce it around the screen.
cm = CardMaker('cm')
cm.setFrame(-0.5, 0.5, -0.5, 0.5)
poly = aspect2d.attachNewNode(cm.generate())
t1 = loader.loadTexture('maps/noise.rgb')

def makeMoveInterval(obj):
    px = random.uniform(-1, 1)
    pz = random.uniform(-1, 1)
    end = Point3(px, 0, pz)
    start = obj.getPos()
    distance = (end - start).length()
    time = distance * 4
    roll = obj.getR() + time * 20

    i = Sequence(Parallel(obj.posInterval(time, end),
                          obj.hprInterval(time, VBase3(0, 0, roll))),
                 Func(makeMoveInterval, obj))


# Choose a center point on the polygon to put smiley.
anchor = poly.attachNewNode('anchor')
anchor.setPos(0, 0, 0.4)

# Attach a smiley square to that anchor point, and put a compass effect to
# keep it upright.
sm = CardMaker('sm')
sm.setFrame(-0.1, 0.1, -0.1, 0.1)
sm.setUvRange(Point2(0.25, 0.0), Point2(0.75, 1.0))
smiley = anchor.attachNewNode(sm.generate())
t2 = loader.loadTexture('maps/smiley.rgb')

# Note that this CompassEffect appears to cause strange squashing and
# stretching on the smiley square.

# This one, however, maintains his aspect ratio correctly.
smiley.setEffect(CompassEffect.make(aspect2d, CompassEffect.PRot | CompassEffect.PScale))


Thanks for your time and complete explanation, that’s perfect, David !
Just wondering why the author himself hasn’t tried it until now. :slight_smile:
Thank you again.