Esempio n. 1
0
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)