def is_in_view(cam_node, obj_node, scale_size=None, crop_size=None): """ Returns the intersection flag between the camera's frustrum and the object's tight bounding box. https://www.panda3d.org/forums/viewtopic.php?t=11704 Intersection flags are defined in here: https://github.com/panda3d/panda3d/blob/master/panda/src/mathutil/boundingVolume.h """ lens_bounds = make_bounds(cam_node.node().getLens(), scale_size=scale_size, crop_size=crop_size) bounds = BoundingBox(*obj_node.getTightBounds()) bounds.xform(obj_node.getParent().getMat(cam_node)) return lens_bounds.contains(bounds)
class WaterNode(NodePath): Nothing = 0 Touching = 2 Submerged = 4 def __init__(self, size, pos, depth, mask, spec = WaterSpec()): NodePath.__init__(self, 'waterNode') self.setPos(pos) self.spec = spec self.pos = pos self.depth = depth self.size = size self.mask = mask self.height = pos[2] normal = (0, 0, 1) tangent = (normal[0], normal[2], -normal[1]) binormal = (normal[2], normal[1], -normal[0]) # Build array for new format. array = GeomVertexArrayFormat() array.addColumn(InternalName.make('vertex'), 3, Geom.NTFloat32, Geom.CPoint) array.addColumn(InternalName.make('texcoord'), 2, Geom.NTFloat32, Geom.CTexcoord) array.addColumn(InternalName.make('normal'), 3, Geom.NTFloat32, Geom.CVector) array.addColumn(InternalName.make('binormal'), 3, Geom.NTFloat32, Geom.CVector) array.addColumn(InternalName.make('tangent'), 3, Geom.NTFloat32, Geom.CVector) # Create and register format. format = GeomVertexFormat() format.addArray(array) format = GeomVertexFormat.registerFormat(format) vdata = GeomVertexData('waterPlanes', format, Geom.UHStatic) vdata.setNumRows(4) vtxWriter = GeomVertexWriter(vdata, 'vertex') tcWriter = GeomVertexWriter(vdata, 'texcoord') tnWriter = GeomVertexWriter(vdata, 'tangent') bnWriter = GeomVertexWriter(vdata, 'binormal') normWriter = GeomVertexWriter(vdata, 'normal') # top left corner vtxWriter.addData3f(size[0], size[3], 0) tcWriter.addData2f(0, 1) normWriter.addData3f(*normal) tnWriter.addData3f(*tangent) bnWriter.addData3f(*binormal) # bottom left corner vtxWriter.addData3f(size[0], size[2], 0) tcWriter.addData2f(0, 0) normWriter.addData3f(*normal) tnWriter.addData3f(*tangent) bnWriter.addData3f(*binormal) # top right corner vtxWriter.addData3f(size[1], size[3], 0) tcWriter.addData2f(1, 1) normWriter.addData3f(*normal) tnWriter.addData3f(*tangent) bnWriter.addData3f(*binormal) # bottom right corner vtxWriter.addData3f(size[1], size[2], 0) tcWriter.addData2f(1, 0) normWriter.addData3f(*normal) tnWriter.addData3f(*tangent) bnWriter.addData3f(*binormal) topTris = GeomTriangles(Geom.UHStatic) topTris.addVertices(0, 1, 2) topTris.addVertices(3, 2, 1) topGeom = Geom(vdata) topGeom.addPrimitive(topTris) self.topNP = self.attachNewNode(GeomNode('waterTop')) self.topNP.node().addGeom(topGeom) # Reverse the winding for the bottom water plane botTris = GeomTriangles(Geom.UHStatic) botTris.addVertices(2, 1, 0) botTris.addVertices(1, 2, 3) botGeom = Geom(vdata) botGeom.addPrimitive(botTris) self.botNP = self.attachNewNode(GeomNode('waterBot')) self.botNP.node().addGeom(botGeom) # Create an AABB which defines the volume of this water. self.aabb = BoundingBox(Point3(size[0], size[2], -depth), Point3(size[1], size[3], 0)) self.aabb.xform(self.getMat(render)) self.cubemap = base.bspLoader.getClosestCubemapTexture(self.getPos(render)) self.dudvFrame = 0 def setup(self): self.reparentTo(render) self.hide(CIGlobals.ReflectionCameraBitmask | CIGlobals.RefractionCameraBitmask) #self.setLightOff(1) self.setMaterialOff(1) self.setTransparency(1) def disableEffects(self): self.topNP.clearShader() self.botNP.clearShader() def enableFakeEffect(self): self.disableEffects() staticTex = loader.loadTexture(self.spec.staticTex) self.topNP.setTexture(staticTex, 1) self.botNP.setTexture(staticTex, 1) def disableFakeEffect(self): self.topNP.clearTexture() self.botNP.clearTexture() def enableEffects(self, reflScene, refrScene, underwaterRefrScene): self.disableFakeEffect() static = loader.loadTexture(self.spec.staticTex) if not self.spec.cheap: self.topNP.setShader(Shader.load(Shader.SL_GLSL, "shaders/water_v.glsl", "shaders/water_f.glsl"), 2) self.topNP.setShaderInput("dudv", static) self.topNP.setShaderInput("dudv_tile", self.spec.dudvTile) self.topNP.setShaderInput("dudv_strength", self.spec.dudvStrength) self.topNP.setShaderInput("move_factor", self.spec.moveFactor) self.topNP.setShaderInput("near", CIGlobals.DefaultCameraNear) self.topNP.setShaderInput("far", CIGlobals.DefaultCameraFar) self.topNP.setShaderInput("normal_map", static) self.topNP.setShaderInput("fog_density", self.spec.fog.density) self.topNP.setShaderInput("fog_color", self.spec.fog.color) self.topNP.setShaderInput("water_tint", self.spec.tint) self.topNP.setShaderInput("reflect_factor", self.spec.reflectFactor) self.topNP.setShaderInput("static_depth", self.depth) self.botNP.setShader(Shader.load(Shader.SL_GLSL, "shaders/water_bottom_v.glsl", "shaders/water_bottom_f.glsl"), 2) self.botNP.setShaderInput("dudv", static) self.botNP.setShaderInput("dudv_tile", self.spec.dudvTile) self.botNP.setShaderInput("dudv_strength", self.spec.dudvStrength) self.botNP.setShaderInput("move_factor", self.spec.moveFactor) self.botNP.setShaderInput("water_tint", self.spec.tint) else: # We are doing cheap water self.topNP.setShader(Shader.load(Shader.SL_GLSL, "shaders/water_cheap_v.glsl", "shaders/water_cheap_f.glsl"), 2) self.topNP.setShaderInput("tex_scale", self.spec.dudvTile) self.topNP.setShaderInput("cube_map", self.cubemap) self.topNP.setShaderInput("normal_map", static) self.topNP.setShaderInput("base_map", static) self.topNP.setShaderInput("reflectivity", self.spec.reflectivity) self.topNP.setShaderInput("_exposureAdjustment", base.shaderGenerator.getExposureAdjustment()) self.topNP.setShaderInput("water_tint", self.spec.tint) self.setTextureInputs(reflScene, refrScene, underwaterRefrScene) def setTextureInputs(self, reflScene, refrScene, underwaterRefrScene): if not self.spec.cheap: self.topNP.setShaderInput("refl", reflScene.texture) self.topNP.setShaderInput("refr", refrScene.texture) self.topNP.setShaderInput("refr_depth", refrScene.depthTex) self.botNP.setShaderInput("refr", underwaterRefrScene.texture) def isInWater(self, bottom, top): return self.aabb.contains(bottom, top) def isTouchingWater(self, position): return self.aabb.contains(position) != BoundingBox.IFNoIntersection def removeNode(self): self.topNP.removeNode() del self.topNP self.botNP.removeNode() del self.botNP del self.aabb del self.height del self.pos del self.size del self.depth NodePath.removeNode(self)