Window Resize Issue

Try this … run the following code. Grab the lower right corner or the right edge and drag it to the left to resize it. It crashes for me … What gives?

Error Message Follows:

Assertion failed: !mat.is_nan() at line 278 of c:\temp\mkpr\panda3d-1.3.2\panda\src\pgraph\transformState.cxx
Assertion failed: has_mat() at line 589 of c:\temp\mkpr\panda3d-1.3.2\built\include\transformState.I
# Standard imports

import sys

# Panda imports

from direct.showbase.DirectObject import DirectObject
import direct.directbase.DirectStart
from pandac.PandaModules import *

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 

def P3DCreateAxes(lineThickness=1):

	ls = LineSegs()
	ls.setThickness(lineThickness)

	# X axis
	ls.setColor(1.0, 0.0, 0.0, 1.0)
	ls.moveTo(0.0, 0.0, 0.0)
	ls.drawTo(1.0, 0.0, 0.0)

	# Y axis
	ls.setColor(0.0, 1.0, 0.0, 1.0)
	ls.moveTo(0.0,0.0,0.0)
	ls.drawTo(0.0, 1.0, 0.0)

	# Z axis
	ls.setColor(0.0, 0.0, 1.0, 1.0)
	ls.moveTo(0.0,0.0,0.0)
	ls.drawTo(0.0, 0.0, 1.0)

	node = ls.create()
	return NodePath(node)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 

class World(DirectObject):
	def __init__(self):
		# Setup basics
		wp = WindowProperties()
		wp.setTitle("Crash Test")
		base.win.requestProperties(wp)
		base.setBackgroundColor(0,0.1,0.6,1)

		# I/O bindings
		self.accept('escape',self.handleEscapeDown)

		worldScale = 40.0

		# Setup axes
		axes = P3DCreateAxes()
		axes.setScale(worldScale,worldScale,worldScale)
		axes.reparentTo(render)

		# Setup camera
		base.camLens.setFar(9000)
		base.camLens.setFov(55, 75)
		base.cam.setPos(2*worldScale,-3*worldScale,worldScale)
		base.cam.setHpr(30,-10,0)

	def handleEscapeDown(self):
		sys.exit()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 

world = World()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Run the program

run()

The crash is happening because ShowBase is attempting to automatically adjust the aspect ratio of the camera to match the window–but you have artificially set the aspect ratio of the camera yourself, and ShowBase doesn’t know about it. So if you make the window too narrow, ShowBase ends up setting the camera lens to an invalid property.

This is arguably a bug in ShowBase, since it should provide an interface for you to indicate programmatically that you don’t want it to adjust the aspect ratio. But you can tell it to leave the aspect ratio alone by putting a fixed aspect ratio in your Config.prc file, e.g.:

aspect-ratio 1

Alternatively, you could just use the one-parameter version of setFov(), and set only the field of view of the width of the screen. Then when ShowBase changes the aspect ratio, it will automatically set the height fov to match the shape of the window. Or you could use base.camLens.setMinFov(), which sets the field of view of the height of the screen, and let it compute the width.

David

Yes that’s it Thanks!. It’s been a long time since I wrote that code but I do remember expecting to see some sort of windowResized() callback.

This brings up another [related] problem I am having. Check out the two following figures … I have experimented around with combinations of setFov(fx,yy) and setAspectRatio(winSizeY/winSizeX) in trying to get a fixed aspect ratio to no avail. What is the proper procedure to do this if I want to force a fixed aspect ratio? Do I need to do this every frame?

wp = base.win.getProperties()
base.camLens.setAspectRatio(wp.getXSize()/wp.getYSize()) 


[br]

Thanks again for your help

If by “fixed aspect ratio”, you mean an aspect ratio that automatically adjusts to the window, the proper way to do this is just to avoid the two-parameter setFov() or the setAspectRatio() calls.

If you do not set the aspect ratio explicitly, it will be handled for you automatically. So instead of using two-parameter setFov(), use one-parameter setFov(), or setMinFov().

David

Yes that’s what I mean. My problem is that it is working fine for ‘render’ but not for ‘render2d’ as illustrated above. Note that the circles become ellipses and the squares become rectangles. Is there any way to force a fixed aspect ratio for ‘render2d’?

Yes. Attach your objects to aspect2d instead of render2d. By convention, render2d is always in the range -1 … 1 in both axes, regardless of the shape of the window. On the other hand, aspect2d is a child of render2d, and it has a scale on it that is intended to compensate for the aspect ratio of the window (thus the name "aspect2d’).

David

Awesome, Thanks!
—Paul

Note that you can also parent things to base.a2dTopCenter, base.a2dTopLeft, base.a2dBottomRight, etc., which are special nodes (children of aspect2d) that will be automatically repositioned to stick to their respective corners when the window changes shape.

David

Thanks David, you just solved another problem I was having …

–Paul