Пример #1
0
class Tester(ShowBase):

    TipoImagenNulo = 0
    TipoImagenTopo = 1
    TipoImagenRuido = 2
    TipoImagenRuidoContinuo = 3

    def __init__(self):
        #
        super(Tester, self).__init__()
        self.disableMouse()
        self.win.setClearColor(Vec4(0.95, 1.0, 1.0, 1.0))
        #
        bullet_world = BulletWorld()
        #
        self.cam_pitch = 30.0
        self.escribir_archivo = False  # cada update
        #
        config.iniciar()
        self.sistema = Sistema()
        self.sistema.radio_expansion_parcelas = 1
        self.sistema.iniciar()
        Sistema.establecer_instancia(self.sistema)
        #
        GestorShader.iniciar(self, Sistema.TopoAltitudOceano,
                             Vec4(0, 0, 1, Sistema.TopoAltitudOceano))
        GestorShader.aplicar(self.render, GestorShader.ClaseGenerico, 1)
        self.render.setShaderInput("distancia_fog_maxima",
                                   3000.0,
                                   0,
                                   0,
                                   0,
                                   priority=3)
        #
        self.terreno = Terreno(self, bullet_world)
        self.terreno.iniciar()
        #self.terreno.nodo.setRenderModeWireframe()
        #
        plano = CardMaker("plano_agua")
        r = Sistema.TopoTamanoParcela * 6
        plano.setFrame(-r, r, -r, r)
        plano.setColor((0, 0, 1, 1))
        self.plano_agua = self.render.attachNewNode(plano.generate())
        self.plano_agua = self.loader.loadModel("objetos/plano_agua")
        self.plano_agua.reparentTo(self.render)
        self.plano_agua.setScale(0.5)
        #self.plano_agua.setP(-90.0)
        #self.plano_agua.hide()
        #
        self.cam_driver = self.render.attachNewNode("cam_driver")
        self.camera.reparentTo(self.cam_driver)
        self.camera.setPos(Sistema.TopoTamanoParcela / 2, 500, 100)
        self.camera.lookAt(self.cam_driver)
        self.cam_driver.setP(self.cam_pitch)
        #
        self.luz_ambiental = self.render.attachNewNode(
            AmbientLight("luz_ambiental"))
        self.luz_ambiental.node().setColor(Vec4(0.1, 0.1, 0.1, 1))
        #
        self.sun = self.render.attachNewNode(DirectionalLight("sun"))
        self.sun.node().setColor(Vec4(1, 1, 1, 1))
        self.sun.setPos(self.terreno.nodo, 100, 100, 100)
        self.sun.lookAt(self.terreno.nodo)
        #
        self.render.setLight(self.luz_ambiental)
        self.render.setLight(self.sun)
        #
        self.texturaImagen = None
        self.imagen = None
        self.zoom_imagen = 1
        #
        self.tipo_imagen = Tester.TipoImagenTopo
        #
        self.taskMgr.add(self.update, "update")
        self.accept("wheel_up", self.zoom, [1])
        self.accept("wheel_down", self.zoom, [-1])
        #
        self._cargar_ui()
        #self._actualizar_terreno()
        self._generar_imagen()

    def update(self, task):
        nueva_pos_foco = Vec3(self.sistema.posicion_cursor)
        #
        mwn = self.mouseWatcherNode
        if mwn.isButtonDown(KeyboardButton.up()):
            nueva_pos_foco[1] -= Sistema.TopoTamanoParcela
        elif mwn.isButtonDown(KeyboardButton.down()):
            nueva_pos_foco[1] += Sistema.TopoTamanoParcela
        elif mwn.isButtonDown(KeyboardButton.left()):
            nueva_pos_foco[0] += Sistema.TopoTamanoParcela
        elif mwn.isButtonDown(KeyboardButton.right()):
            nueva_pos_foco[0] -= Sistema.TopoTamanoParcela
        #
        if nueva_pos_foco != self.sistema.posicion_cursor:
            log.info("update pos_foco=%s" % str(nueva_pos_foco))
            self.sistema.posicion_cursor = nueva_pos_foco
            self._actualizar_terreno()
        return task.cont

    def zoom(self, dir):
        dy = 25 * dir
        self.camera.setY(self.camera, dy)

    def analizar_altitudes(self, pos_foco, tamano=1024):
        log.info("analizar_altitudes en %ix%i" % (tamano, tamano))
        i = 0
        media = 0
        vals = list()
        min = 999999
        max = -999999
        for x in range(tamano):
            for y in range(tamano):
                a = self.sistema.obtener_altitud_suelo(
                    (pos_foco[0] + x, pos_foco[1] + y))
                vals.append(a)
                if a > max:
                    max = a
                if a < min:
                    min = a
                media = ((media * i) + a) / (i + 1)
                i += 1
        sd = 0
        for val in vals:
            sd += ((val - media) * (val - media))
        sd /= (tamano * tamano)
        sd = math.sqrt(sd)
        log.info("analizar_altitudes rango:[%.3f/%.3f] media=%.3f sd=%.3f" %
                 (min, max, media, sd))

    def _actualizar_terreno(self):
        log.info("_actualizar_terreno pos=%s" %
                 (str(self.sistema.posicion_cursor)))
        #
        self.sistema.update(0, self.sistema.posicion_cursor)
        self.terreno.update()
        if self.escribir_archivo:
            log.info("escribir_archivo")
            self.terreno.nodo.writeBamFile("terreno.bam")
        self.plano_agua.setPos(
            Vec3(self.sistema.posicion_cursor[0],
                 self.sistema.posicion_cursor[1], Sistema.TopoAltitudOceano))
        #
        self.cam_driver.setPos(
            Vec3(
                self.sistema.posicion_cursor[0] +
                Sistema.TopoTamanoParcela / 2,
                self.sistema.posicion_cursor[1] - Sistema.TopoTamanoParcela,
                Sistema.TopoAltitudOceano))
        #
        self.lblInfo["text"] = self.terreno.obtener_info()
        #
        self._generar_imagen()

    def _ruido(self, position, imagen_ruido, tamano_imagen_ruido):
        octaves = 8
        persistance = 0.55
        value = 0.0
        amplitude = 1.0
        total_amplitude = 0.0
        for i_octave in range(octaves):
            amplitude *= persistance
            total_amplitude += amplitude
            period = 1 << (octaves - i_octave)
            offset_periodo_x, cant_periodos_x = math.modf(position[0] / period)
            offset_periodo_y, cant_periodos_y = math.modf(position[1] / period)
            periodo_x0 = (cant_periodos_x * period) % tamano_imagen_ruido
            periodo_y0 = (cant_periodos_y * period) % tamano_imagen_ruido
            periodo_x1 = (periodo_x0 + period) % tamano_imagen_ruido
            periodo_y1 = (periodo_y0 + period) % tamano_imagen_ruido
            c00 = imagen_ruido.getGray(int(periodo_x0), int(periodo_y0))
            c10 = imagen_ruido.getGray(int(periodo_x1), int(periodo_y0))
            c01 = imagen_ruido.getGray(int(periodo_x0), int(periodo_y1))
            c11 = imagen_ruido.getGray(int(periodo_x1), int(periodo_y1))
            interp_x0 = (c00 *
                         (1.0 - offset_periodo_x)) + (c10 * offset_periodo_x)
            interp_x1 = (c01 *
                         (1.0 - offset_periodo_x)) + (c11 * offset_periodo_x)
            interp_y = (interp_x0 *
                        (1.0 - offset_periodo_y)) + (interp_x1 *
                                                     offset_periodo_y)
            value += interp_y * amplitude
            #info="_ruido\tposition=%s tamano_imagen_ruido=%i i_octave=%i periodo=%i offset_periodo=%s\n"%(str(position), tamano_imagen_ruido, i_octave, period, str((offset_periodo_x, offset_periodo_y)))
            #info+="\tpx0=%.1f px1=%.1f offset_x=%.2f py0=%.1f py1=%.1f offset_y=%.2f interp_y=%.3f"%(periodo_x0, periodo_x1, offset_x, periodo_y0, periodo_y1, offset_y, interp_y)
            #print(info)
            #print("cxx=%s a=%.4f p=%i v=%.4f"%(str((c00, c10, c01, c11)), amplitude, period, value))
        if total_amplitude > 1.0:
            value /= total_amplitude
        return value

    def _limpiar_imagen(self):
        if self.imagen:
            self.texturaImagen.releaseAll()
            self.texturaImagen.clear()
            self.texturaImagen = None
            self.imagen.clear()
            self.imagen = None

    def _generar_imagen(self):
        log.info("_generar_imagen")
        self._limpiar_imagen()
        if self.tipo_imagen == Tester.TipoImagenTopo:
            self._generar_imagen_topo()
        elif self.tipo_imagen == Tester.TipoImagenRuido:
            self._generar_imagen_ruido()
        elif self.tipo_imagen == Tester.TipoImagenRuidoContinuo:
            self._generar_imagen_ruido_continuo()

    def _generar_imagen_ruido_continuo(self):
        log.info("_generar_imagen_ruido_continuo")
        #
        tamano = 512
        #
        #        perlin_noise_scale=64
        #        perlin=StackedPerlinNoise2(perlin_noise_scale, perlin_noise_scale, 6, 2.0, 0.50, 256, 1069)
        perlin = self.sistema.ruido_terreno
        #
        if not self.imagen:
            type = PNMFileTypeRegistry.getGlobalPtr().getTypeFromExtension(
                "*.png")
            self.imagen = PNMImage(tamano, tamano, 4, 255, type, CS_linear)
            self.texturaImagen = Texture()
            self.frmImagen["image"] = self.texturaImagen
            self.frmImagen["image_scale"] = 0.4
        #
        zoom = self.zoom_imagen
        log.info("zoom: %.2f" % (zoom))
        #        range_x, range_y=tamano, tamano
        #        factor_x, factor_y=range_x/tamano, range_y/tamano
        for x in range(tamano):
            for y in range(tamano):
                #                _x=x*factor_x
                #                _y=y*factor_y
                #                c00=perlin(_x,                  _y                  )
                #                c10=perlin((_x+range_x)        ,_y                  )
                #                c01=perlin(_x,                  (_y+range_y)        )
                #                c11=perlin((_x+range_x)        ,(_y+range_y)        )
                #                mix_x, mix_y=1.0-_x/range_x, 1.0-_y/range_y
                #                if mix_x<0.0 or mix_y<0.0 or mix_x>1.0 or mix_y>1.0:
                #                    print("error mix_x,mix_y")
                #                interp_x0=(c00*(1.0-mix_x))+(c10*mix_x)
                #                interp_x1=(c01*(1.0-mix_x))+(c11*mix_x)
                #                interp_y=(interp_x0*(1.0-mix_y))+(interp_x1*mix_y)
                #                interp_y=interp_y*0.5+0.5
                #                interp_y=interp_y if interp_y<1.0 else 1.0
                #                interp_y=interp_y if interp_y>0.0 else 0.0
                #                c=interp_y
                #                if c<0.0 or c>1.0:
                #                    print("error c")
                c = self.sistema.calcular_ruido_continuo(perlin, x, y, tamano)
                self.imagen.setXelA(x, y, c, c, c, 1.0)
        #


#        self.imagen.write("texturas/white_noise.png")
        image_tiled = PNMImage(2 * tamano, 2 * tamano)
        image_tiled.copySubImage(self.imagen, 0, 0, 0, 0, tamano, tamano)
        image_tiled.copySubImage(self.imagen, tamano, 0, 0, 0, tamano, tamano)
        image_tiled.copySubImage(self.imagen, 0, tamano, 0, 0, tamano, tamano)
        image_tiled.copySubImage(self.imagen, tamano, tamano, 0, 0, tamano,
                                 tamano)
        self.imagen.clear()
        self.imagen = None
        self.imagen = image_tiled
        self.texturaImagen.load(self.imagen)

    def _generar_imagen_ruido(self):
        # http://devmag.org.za/2009/04/25/perlin-noise/
        log.info("_generar_imagen_ruido")
        return
        #
        tamano = 128
        #
        if not self.imagen:
            self.imagen = PNMImage(tamano + 1, tamano + 1)
            self.texturaImagen = Texture()
            self.frmImagen["image"] = self.texturaImagen
            self.frmImagen["image_scale"] = 0.4
        #
        zoom = self.zoom_imagen
        log.info("zoom: %.2f" % (zoom))
        imagen_ruido = PNMImage("texturas/white_noise.png")
        n = 0
        vals = list()
        tamano_imagen_ruido = imagen_ruido.getReadXSize()
        for x in range(tamano_imagen_ruido):
            vals.append(list())
            for y in range(tamano_imagen_ruido):
                _x = self.sistema.posicion_cursor[0] + zoom * (tamano /
                                                               2.0) - zoom * x
                _y = self.sistema.posicion_cursor[1] - zoom * (tamano /
                                                               2.0) + zoom * y
                a = self._ruido((_x, _y), imagen_ruido, tamano_imagen_ruido)
                vals[x].append(a)
                n += 1
        media = 0.0
        sd = 0.0
        for fila in vals:
            for val in fila:
                media += val
        media /= n
        for fila in vals:
            for val in fila:
                sd += (val - media)**2
        sd = math.sqrt(sd / (n - 1))
        vals2 = list()
        k = 7
        for x in range(tamano_imagen_ruido):
            vals2.append(list())
            for y in range(tamano_imagen_ruido):
                val = vals[x][y]
                val -= (media - 0.5)
                val += (0.5 - val) * (-(1.0 + (2**k) * sd))
                val2 = min(1.0, max(0.0, val))
                vals2[x].append(val2)
        for x in range(tamano_imagen_ruido):
            for y in range(tamano_imagen_ruido):
                self.imagen.setXel(x, y, vals2[x][y])
        print("_generar_imagen_ruido media=%.4f sd=%.4f" % (media, sd))
        #
        self.texturaImagen.load(self.imagen)

    def _generar_imagen_topo(self):
        log.info("_generar_imagen_topo")
        #
        tamano = 128
        if not self.imagen:
            self.imagen = PNMImage(tamano + 1, tamano + 1)
            self.texturaImagen = Texture()
            self.frmImagen["image"] = self.texturaImagen
            self.frmImagen["image_scale"] = 0.4
        #
        zoom = self.zoom_imagen
        log.info("zoom: %.2f" % (zoom))
        for x in range(tamano + 1):
            for y in range(tamano + 1):
                _x = self.sistema.posicion_cursor[0] + zoom * (tamano /
                                                               2.0) - zoom * x
                _y = self.sistema.posicion_cursor[1] - zoom * (tamano /
                                                               2.0) + zoom * y
                a = self.terreno.sistema.obtener_altitud_suelo(
                    (_x, _y)) / Sistema.TopoAltura
                if x == tamano / 2 or y == tamano / 2:
                    self.imagen.setXel(x, y, 1.0)
                else:
                    if a > (Sistema.TopoAltitudOceano / Sistema.TopoAltura):
                        self.imagen.setXel(x, y, a, a, 0.0)
                    else:
                        self.imagen.setXel(x, y, 0.0, 0.0, a)
        #
        self.texturaImagen.load(self.imagen)

    def _ir_a_idx_pos(self):
        log.info("_ir_a_idx_pos")
        try:
            idx_x = int(self.entry_x.get())
            idx_y = int(self.entry_y.get())
            pos = self.sistema.obtener_pos_parcela((idx_x, idx_y))
            tam = self.sistema.obtener_temperatura_anual_media_norm(pos)
            prec_f = self.sistema.obtener_precipitacion_frecuencia_anual(pos)
            log.info("idx_pos:(%i,%i); pos:%s; tam=%.4f prec_f=%.4f" %
                     (idx_x, idx_y, str(pos), tam, prec_f))
            self.sistema.posicion_cursor = Vec3(pos[0], pos[1], 0.0)
            self._actualizar_terreno()
        except Exception as e:
            log.exception(str(e))

    def _cargar_ui(self):
        # frame
        self.frame = DirectFrame(parent=self.aspect2d,
                                 pos=(0, 0, -0.85),
                                 frameSize=(-1, 1, -0.15, 0.25),
                                 frameColor=(1, 1, 1, 0.5))
        # info
        self.lblInfo = DirectLabel(parent=self.frame,
                                   pos=(-1, 0, 0.15),
                                   scale=0.05,
                                   text="info terreno?",
                                   frameColor=(1, 1, 1, 0.2),
                                   frameSize=(0, 40, -2, 2),
                                   text_align=TextNode.ALeft,
                                   text_pos=(0, 1, 1))
        # idx_pos
        idx_pos = self.sistema.obtener_indice_parcela(
            self.sistema.posicion_cursor)
        DirectLabel(parent=self.frame,
                    pos=(-1, 0, 0),
                    scale=0.05,
                    text="idx_pos_x",
                    frameColor=(1, 1, 1, 0),
                    frameSize=(0, 2, -1, 1),
                    text_align=TextNode.ALeft)
        DirectLabel(parent=self.frame,
                    pos=(-1, 0, -0.1),
                    scale=0.05,
                    text="idx_pos_y",
                    frameColor=(1, 1, 1, 0),
                    frameSize=(0, 2, -1, 1),
                    text_align=TextNode.ALeft)
        self.entry_x = DirectEntry(parent=self.frame,
                                   pos=(-0.7, 0, 0),
                                   scale=0.05,
                                   initialText=str(idx_pos[0]))
        self.entry_y = DirectEntry(parent=self.frame,
                                   pos=(-0.7, 0, -0.1),
                                   scale=0.05,
                                   initialText=str(idx_pos[1]))
        DirectButton(parent=self.frame,
                     pos=(0, 0, -0.1),
                     scale=0.075,
                     text="actualizar",
                     command=self._ir_a_idx_pos)
        #
        self.frmImagen = DirectFrame(parent=self.frame,
                                     pos=(0.8, 0, 0.2),
                                     state=DGG.NORMAL,
                                     frameSize=(-0.4, 0.4, -0.4, 0.4))
        self.frmImagen.bind(DGG.B1PRESS, self._click_imagen)
        DirectButton(parent=self.frame,
                     pos=(0.500, 0, 0.65),
                     scale=0.1,
                     text="acercar",
                     command=self._acercar_zoom_imagen,
                     frameSize=(-1, 1, -0.4, 0.4),
                     text_scale=0.5)
        DirectButton(parent=self.frame,
                     pos=(0.725, 0, 0.65),
                     scale=0.1,
                     text="alejar",
                     command=self._alejar_zoom_imagen,
                     frameSize=(-1, 1, -0.4, 0.4),
                     text_scale=0.5)
        DirectButton(parent=self.frame,
                     pos=(0.950, 0, 0.65),
                     scale=0.1,
                     text="cambiar",
                     command=self._cambiar_tipo_imagen,
                     frameSize=(-1, 1, -0.4, 0.4),
                     text_scale=0.5)

    def _cambiar_tipo_imagen(self):
        log.info("_cambiar_tipo_imagen a:")
        if self.tipo_imagen == Tester.TipoImagenTopo:
            log.info("TipoImagenRuido")
            self.tipo_imagen = Tester.TipoImagenRuido
        elif self.tipo_imagen == Tester.TipoImagenRuido:
            log.info("TipoImagenRuidoContinuo")
            self.tipo_imagen = Tester.TipoImagenRuidoContinuo
        elif self.tipo_imagen == Tester.TipoImagenRuidoContinuo:
            log.info("TipoImagenTopo")
            self.tipo_imagen = Tester.TipoImagenTopo
        self._generar_imagen()

    def _click_imagen(self, *args):
        log.info("_click_imagen %s" % str(args))

    def _acercar_zoom_imagen(self):
        log.info("_acercar_zoom_imagen")
        self.zoom_imagen -= 4
        if self.zoom_imagen < 1:
            self.zoom_imagen = 1
        self._generar_imagen()

    def _alejar_zoom_imagen(self):
        log.info("_alejar_zoom_imagen")
        self.zoom_imagen += 4
        if self.zoom_imagen > 4096:
            self.zoom_imagen = 4096
        self._generar_imagen()
Пример #2
0
class Mundo:
    def __init__(self, base):
        # referencias:
        self.base = base
        self.sistema = None
        # componentes:
        self.nodo = self.base.render.attachNewNode("mundo")
        self.input_mapper = None
        self.controlador_camara = None
        self.terreno = None
        self.cielo = None
        self.sol = None
        self.agua = None
        self.objetos = None
        self.hombre = None
        self.nave = None
        # variables internas:
        self._counter = 50  # forzar terreno.update antes de hombre.update
        self._personajes = []
        self._periodo_dia_actual = 0

    def iniciar(self):
        log.info("iniciar")
        # sistema:
        self.sistema = Sistema()
        self.sistema.iniciar()
        self.sistema.cargar_parametros_iniciales()
        self.sistema.update(0.0, self.sistema.posicion_cursor)
        Sistema.establecer_instancia(self.sistema)
        # fisica:
        self._configurar_fisica()
        # mundo:
        self._establecer_material()  # quitarlo, optimizacion? no, al reves!
        self._establecer_shader()
        # componentes:
        self.input_mapper = InputMapperTecladoMouse(self.base)
        self.controlador_camara = ControladorCamara(self.base)
        self.controlador_camara.iniciar()
        #
        self._cargar_terreno()  #
        self._cargar_personajes()  #
        self._cargar_objetos()  #
        #self._cargar_obj_voxel()
        # gui:
        self._cargar_debug_info()
        self._cargar_gui()
        # ShowBase
        self.base.cam.node().setCameraMask(DrawMask(1))
        self.base.render.node().adjustDrawMask(DrawMask(5), DrawMask(0),
                                               DrawMask(0))
        #
        self.base.accept("l-up", self._hacer, [0])
        self.base.accept("m-up", self._hacer, [1])
        self.base.accept("v-up", self._hacer, [2])
        #
        self.base.taskMgr.add(self._update, "mundo_update")
        #

    def terminar(self):
        log.info("terminar")
        #
        self.base.ignore("l-up")
        self.base.ignore("m-up")
        self.base.ignore("v-up")
        #
        self.controlador_camara.terminar()
        #
        for _personaje in self._personajes:
            _personaje.terminar()
        if self.objetos:
            self.objetos.terminar()
        if self.agua:
            self.agua.terminar()
        if self.sol:
            self.sol.terminar()
        if self.cielo:
            self.cielo.terminar()
        if self.terreno:
            self.terreno.terminar()
        #
        self.sistema = None
        Sistema.remover_instancia()

    def _hacer(self, que):
        if que == 0:
            log.debug(self.sistema.obtener_info())
        elif que == 1:
            self.nodo.analyze()
        elif que == 2:
            self.base.bufferViewer.toggleEnable()
        elif que == 3:
            if not self.nave:
                return
            if not self.hombre.conduciendo:
                self.nave.setPos(self.sistema.posicion_cursor)
                self.hombre.cuerpo.reparentTo(self.nave.cuerpo)
                self.hombre.setPos(Vec3(0, 0, -0.5))
                self.hombre.conduciendo = True
                self.controlador_camara.seguir(self.nave.cuerpo)
            else:
                self.hombre.cuerpo.reparentTo(self.nodo)
                self.hombre.setPos(self.sistema.posicion_cursor)
                self.hombre.conduciendo = False
                self.controlador_camara.seguir(self.hombre.cuerpo)

    def _establecer_material(self):
        log.info("_establecer_material")
        intensidades = (0.20, 0.35, 0.0)  # (a,d,s)
        material = Material("material_mundo")
        material.setAmbient(
            (intensidades[0], intensidades[0], intensidades[0], 1.0))
        material.setDiffuse(
            (intensidades[1], intensidades[1], intensidades[1], 1.0))
        material.setSpecular(
            (intensidades[2], intensidades[2], intensidades[2], 1.0))
        material.setShininess(0)
        self.nodo.setMaterial(material, 1)

    def _establecer_shader(self):
        log.info("_establecer_shader")
        GestorShader.iniciar(self.base, Sistema.TopoAltitudOceano,
                             Vec4(0, 0, 1, Sistema.TopoAltitudOceano))
        #
        # ¿esto habra solucionado el problema del clipping caprichoso?
        self.nodo.setShaderInput("altitud_agua",
                                 Sistema.TopoAltitudOceano,
                                 0.0,
                                 0.0,
                                 0.0,
                                 priority=1)
        #
        #GestorShader.aplicar(self.nodo, GestorShader.ClaseGenerico, 1) # quitarlo, optimizacion?
        #GestorShader.aplicar(self, GestorShader.ClaseDebug, 1000)

    def _cargar_obj_voxel(self):
        hm = HeightMap(id=66)
        N = 64
        self.obj = voxels.Objeto("volumen", N, N, N, 0)
        for x in range(N - 2):
            for y in range(N - 2):
                h = int(hm.getHeight(x, y) * N)
                print("%s,%s->%i" % (str(x), str(y), h))
                for z in range(h):
                    self.obj.establecer_valor(x + 1, y + 1, z + 1, 255)
        model_root = ModelRoot("volumen")
        self.objN = self.nodo.attachNewNode(model_root)
        self.objN.attachNewNode(self.obj.iniciar_smooth())
        self.objN.setColor(0.4, 0.4, 0.4, 1)
        self.objN.setTwoSided(True, 1)
        self.objN.setShaderAuto()
        self.objN.setScale(1)
        self.objN.setPos(-N / 2, -N / 2, -9.5)

    def _configurar_fisica(self):
        self.bullet_world = BulletWorld()
        #return
        #
        debug_fisica = BulletDebugNode("debug_fisica")
        debug_fisica.showNormals(True)
        self.debug_fisicaN = self.nodo.attachNewNode(debug_fisica)
        self.debug_fisicaN.hide()
        self.base.accept("f3", self._toggle_debug_fisica)
        #
        self.bullet_world.setGravity(Vec3(0.0, 0.0, -9.81))
        self.bullet_world.setDebugNode(debug_fisica)
        return
        #
        _shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
        _cuerpo = BulletRigidBodyNode("caja_rigid_body")
        _cuerpo.setMass(1.0)
        _cuerpo.addShape(_shape)
        _cuerpoN = self.nodo.attachNewNode(_cuerpo)
        _cuerpoN.setPos(0.0, 0.0, 100.0)
        _cuerpoN.setCollideMask(BitMask32.bit(3))
        self.bullet_world.attachRigidBody(_cuerpo)
        _cuerpoN.reparentTo(self.nodo)
        caja = self.base.loader.loadModel("box.egg")
        caja.reparentTo(_cuerpoN)

    def _cargar_debug_info(self):
        Negro = Vec4(0.0, 0.0, 0.0, 1.0)
        #Blanco=Vec4(1.0, 1.0, 1.0, 1.0)
        self.texto1 = OnscreenText(text="mundo",
                                   pos=(-1.2, 0.9),
                                   scale=0.045,
                                   align=TextNode.ALeft,
                                   fg=Negro,
                                   mayChange=True)

    def _cargar_gui(self):
        self.lblHora = DirectLabel(text="00:00",
                                   text_fg=(0.15, 0.15, 0.9, 1.0),
                                   text_bg=(1.0, 1.0, 1.0, 1.0),
                                   scale=0.1,
                                   pos=(1.2, 0.0, -0.8),
                                   color=(1, 1, 1, 1))
        self.lblTemperatura = DirectLabel(text="0º",
                                          text_fg=(0.15, 0.15, 0.9, 1.0),
                                          text_bg=(1.0, 1.0, 1.0, 1.0),
                                          scale=0.1,
                                          pos=(1.2, 0.0, -0.93),
                                          color=(1, 1, 1, 1))

    def _cargar_personajes(self):
        # personajes
        self.hombre = Hombre()
        self._personajes.append(self.hombre)
        # nave
        self.nave = Nave()
        self._personajes.append(self.nave)
        #
        for _personaje in self._personajes:
            _personaje.input_mapper = self.input_mapper
            _personaje.altitud_agua = Sistema.TopoAltitudOceano
            _personaje.iniciar(self.nodo, self.bullet_world)
        # posicionar
        self.hombre.setPos(self.sistema.posicion_cursor)
        pos = self.sistema.posicion_cursor + Vec3(-3, -3, 0)
        self.nave.setPos(
            Vec3(pos[0], pos[1], self.sistema.obtener_altitud_suelo(pos)))
        #
        self.controlador_camara.seguir(self.hombre.cuerpo)

    def _cargar_objetos(self):
        #
        self.palo = self.base.loader.loadModel("objetos/palof")
        self.palo.reparentTo(self.nodo)
        self.palo.setPos(self.sistema.obtener_posicion_3d(Vec3(12, 12, 0)))
        #
        luz_omni = self.nodo.attachNewNode(PointLight("luz_omni"))
        luz_omni.setPos(Vec3(0, -2, 152.5))
        luz_omni.node().setColor(Vec4(1, 0, 0, 1))
        luz_omni.node().setAttenuation(Vec3(0, 1.1, 0))
        self.nodo.setShaderInput("luz_omni[0]", luz_omni, priority=4)
        #        luz_omni.reparentTo(self.palo)
        #        luz_omni.setPos(0, 0, 1)
        #
        self.spot_light = self.nodo.attachNewNode(Spotlight("spot_light"))
        self.spot_light.setPos(self.hombre.cuerpo.getPos() + Vec3(0, -5, 6))
        self.spot_light.node().setColor((1, 1, 0.7, 1))
        self.spot_light.node().setAttenuation(Vec3(0.04, 0.025, 0.01))
        self.spot_light.node().setLens(PerspectiveLens())
        #self.spot_light.node().setShadowCaster(True, 256, 256)
        self.spot_light.lookAt(self.hombre.cuerpo)
        self.nodo.setLight(self.spot_light)
        self.spot_light.reparentTo(self.palo)
        self.spot_light.setPos(0, 0, 1)
        self.spot_light.setHpr(0, 15, 0)
        #
        self.nubes = self.base.loader.loadModel("objetos/plano")
        self.nubes.reparentTo(self.nodo)
        #self.nubes.setTwoSided(True)
        self.nubes.setPos(self.hombre.cuerpo.getPos() + Vec3(0, -16, 2.5))
        self.nubes.setP(-90)
        #noise=StackedPerlinNoise2(1, 1, 8, 2, 0.5, 256, 18)
        ts0 = TextureStage("ts_nubes")
        tamano = 512
        imagen = PNMImage(tamano, tamano)
        #imagen.perlinNoiseFill(noise)
        for x in range(tamano):
            for y in range(tamano):
                #v=noise(x, y)*0.5+0.5
                imagen.setXelA(x, y, 1, 0, 0, 0.5)
        tex0 = self.base.loader.loadTexture(
            "texturas/white_noise.png")  #Texture("tex_nubes")
        #        tex0.load(imagen)
        self.nubes.setTexture(ts0, tex0)
        #
        pelota = self.base.loader.loadModel("objetos/pelota.egg")
        pelota.reparentTo(self.nodo)
        pelota.setZ(
            self.sistema.obtener_altitud_suelo(self.sistema.posicion_cursor) +
            3.0)
        material_pelota = Material("material_pelota")
        intensidades = (0.3, 0.2, 0.2)
        material_pelota.setAmbient(
            (intensidades[0], intensidades[0], intensidades[0], 1.0))
        material_pelota.setDiffuse(
            (intensidades[1], intensidades[1], intensidades[1], 1.0))
        material_pelota.setSpecular(
            (intensidades[2], intensidades[2], intensidades[2], 1.0))
        material_pelota.setShininess(20)
        pelota.setMaterial(material_pelota, priority=2)
        GestorShader.aplicar(pelota, GestorShader.ClaseGenerico, 3)
        #
        plano_vertical = self.base.loader.loadModel(
            "objetos/plano_vertical.egg")
        plano_vertical.reparentTo(self.nodo)
        plano_vertical.setPos(0, -6,
                              self.sistema.obtener_altitud_suelo((0, -6, 0)))
        #plano_vertical.setTwoSided(True)
        plano_vertical.setBillboardAxis()
        GestorShader.aplicar(plano_vertical, GestorShader.ClaseGenerico, 3)
        #
        nodo_flatten = self.nodo.attachNewNode("nodo_flatten")
        for x in range(4):
            p = self.base.loader.loadModel("objetos/pelota.egg")
            p.clearModelNodes()
            p.reparentTo(nodo_flatten)
            p.setPos(6, 0, 153 + x)
            p.setScale(0.2)
        nodo_flatten.flattenStrong()
        #
        cant = 3
        prisma = self.base.loader.loadModel("objetos/prisma_tri.egg")
        prisma_geomnode = prisma.find("**/+GeomNode")
        for i_geom in range(prisma_geomnode.node().getNumGeoms()):
            prisma_geom = prisma_geomnode.node().getGeom(i_geom)
            ##
            prisma_vdata = prisma_geom.getVertexData()
            consolidado_prismas_vdata = GeomVertexData(
                "vertex_data", prisma_vdata.getFormat(), Geom.UHStatic)
            consolidado_prismas_vdata.setNumRows(cant *
                                                 prisma_vdata.getNumRows())
            offset = prisma_vdata.getNumRows()
            ##
            prisma_prims = list()
            consolidado_prismas_prims = list()
            for i_prim in range(prisma_geom.getNumPrimitives()):
                prim = prisma_geom.getPrimitive(i_prim).decompose()
                prisma_prims.append(prim)
                consolidado_prismas_prim = GeomTriangles(Geom.UHStatic)
                consolidado_prismas_prims.append(consolidado_prismas_prim)
            for i_cant in range(cant):
                vdata = GeomVertexData(prisma_vdata)
                vdata.transformVertices(
                    LMatrix4f.translateMat(3 * i_cant, 0.0, 0.0))
                for i_row in range(vdata.getNumRows()):
                    consolidado_prismas_vdata.copyRowFrom(
                        i_cant * offset + i_row, vdata, i_row,
                        Thread.getCurrentThread())
                for i_prim in range(len(prisma_prims)):
                    consolidado_prismas_prim = consolidado_prismas_prims[
                        i_prim]
                    prim_verts = prisma_prims[i_prim].getVertexList()
                    for vert in prim_verts:
                        consolidado_prismas_prim.addVertex(vert +
                                                           i_cant * offset)
            consolidado_prismas_geom = Geom(consolidado_prismas_vdata)
            consolidado_prismas_geom.addPrimitive(consolidado_prismas_prim)
            #
            consolidado_prismas_geomnode = GeomNode("copia_geomnode")
            consolidado_prismas_geomnode.addGeom(consolidado_prismas_geom)
            self.nodo_prismas = self.nodo.attachNewNode("nodo_prismas")
            self.nodo_prismas.setPos(
                20, 6, 2 + self.sistema.obtener_altitud_suelo((20, 6, 0)))
            self.nodo_prismas.attachNewNode(consolidado_prismas_geomnode)
        #

    def _cargar_terreno(self):
        # terreno
        self.terreno = Terreno(self.base, self.bullet_world)
        self.terreno.iniciar()
        self.terreno.nodo.reparentTo(self.nodo)
        self.terreno.update()
        # cielo
        self.cielo = Cielo(self.base, Sistema.TopoAltitudOceano - 20.0)
        self.cielo.nodo.reparentTo(self.nodo)
        # agua
        self.agua = Agua(self.base, Sistema.TopoAltitudOceano)
        self.agua.nodo.reparentTo(self.nodo)  # estaba self.base.render
        self.agua.generar()
        #        self.agua.mostrar_camaras()
        # sol
        self.sol = Sol(self.base, Sistema.TopoAltitudOceano - 20.0)
        self.sol.pivot.reparentTo(self.nodo)  # self.cielo.nodo
        #        self.sol.mostrar_camaras()
        self.nodo.setLight(self.sol.luz)
        # objetos
        #        self.objetos=Objetos(self.base)
        #        self.objetos.iniciar()
        #        self.objetos.nodo.reparentTo(self.nodo)
        #        self.objetos.update()
        #
        #        self.cielo.nodo.setBin("background", 0)
        #        self.agua.nodo.setBin("background", 1)
        #        self.sol.nodo.setBin("background", 2)
        #        self.terreno.nodo.setBin("opaque", 0)
        #        self.objetos.nodo.setBin("transparent", 0)
        #
        self.controlador_camara.altitud_agua = Sistema.TopoAltitudOceano
        #

    def _update(self, task):
        if self._counter == 50:
            info = ""
            info += self.sistema.obtener_info() + "\n"
            #info+=self.terreno.obtener_info()+"\n"
            info += self.hombre.obtener_info() + "\n"
            #info+=self.agua.obtener_info()+"\n"
            #info+=self.objetos.obtener_info()+"\n"
            #info+=self.input_mapper.obtener_info()+"\n"
            #info+=self.cielo.obtener_info()
            #info+=self.sol.obtener_info()+"\n"
            self.texto1.setText(info)
        # tiempo
        dt = self.base.taskMgr.globalClock.getDt()
        # input
        self.input_mapper.update()
        # fisica
        self.bullet_world.doPhysics(dt)
        # controlador cámara
        self.controlador_camara.altitud_suelo = self.sistema.obtener_altitud_suelo(
            self.controlador_camara.pos_camara.getXy())
        self.controlador_camara.update(dt)
        pos_pivot_camara = self.controlador_camara.pivot.getPos(self.nodo)
        self.nodo.setShaderInput("pos_pivot_camara",
                                 pos_pivot_camara,
                                 priority=10)
        # sistema
        self.sistema.update(dt, pos_pivot_camara)
        # cielo
        if self.cielo:
            offset_periodo = self.sistema.calcular_offset_periodo_dia()
            self.cielo.nodo.setX(
                self.controlador_camara.target_node_path.getPos().getX())
            self.cielo.nodo.setY(
                self.controlador_camara.target_node_path.getPos().getY())
            self.cielo.update(pos_pivot_camara, self.sistema.hora_normalizada,
                              self.sistema.periodo_dia_actual, offset_periodo)
            self.nodo.setShaderInput("color_luz_ambiental",
                                     self.cielo.color_luz_ambiental,
                                     priority=10)
            self.nodo.setShaderInput("offset_periodo_cielo",
                                     self.cielo.offset_periodo,
                                     priority=10)
            self.nodo.setShaderInput("color_cielo_base_inicial",
                                     self.cielo.color_cielo_base_inicial,
                                     priority=10)
            self.nodo.setShaderInput("color_cielo_base_final",
                                     self.cielo.color_cielo_base_final,
                                     priority=10)
            self.nodo.setShaderInput("color_halo_sol_inicial",
                                     self.cielo.color_halo_sol_inicial,
                                     priority=10)
            self.nodo.setShaderInput("color_halo_sol_final",
                                     self.cielo.color_halo_sol_final,
                                     priority=10)
        # sol
        if self.sol:
            self.sol.update(pos_pivot_camara, self.sistema.hora_normalizada,
                            self.sistema.periodo_dia_actual, offset_periodo)
            self.nodo.setShaderInput("posicion_sol",
                                     self.sol.nodo.getPos(self.nodo),
                                     priority=10)
        # personajes
        for _personaje in self._personajes:
            _personaje.update(dt)
        # contador 1/50
        if self._counter == 50:
            self._counter = 0
            #
            if self.terreno:
                self.terreno.update(
                )  #pos_pivot_camara)#self.controlador_camara.target_node_path.getPos()) ?
            if self.objetos:
                self.objetos.update()  #pos_pivot_camara)
            # gui
            self.lblHora["text"] = self.sistema.obtener_hora()
            self.lblTemperatura[
                "text"] = "%.0fº" % self.sistema.obtener_temperatura_actual_grados(
                )
        # agua
        if self.agua:
            self.agua.nodo.setX(
                self.controlador_camara.target_node_path.getPos().getX())
            self.agua.nodo.setY(
                self.controlador_camara.target_node_path.getPos().getY())
            self.agua.update(dt, self.sol.luz.getPos(self.cielo.nodo),
                             self.sol.luz.node().getColor())
        #
        self._counter += 1
        return task.cont

    def _toggle_debug_fisica(self):
        if self.debug_fisicaN.isHidden():
            self.debug_fisicaN.show()
        else:
            self.debug_fisicaN.hide()