我在 Python 3.8 中使用 Ursina
我有一个为实体制作的自定义模型。我有该模型的纹理,从 3D 建模工具导出为 .png 图像。我尝试像这样应用纹理:
Entity(model='monolith', scale=0.2, name='monolith', position=(50,0,100), collider='mesh', color=color.dark_gray, texture='/models/monolith')
在游戏中,模型只是纯黑色。我用不同的模型尝试了这个,结果相同 - 自定义模型没有显示其纹理。
如何让 Ursina 为我的自定义模型添加纹理?
对于这个具体示例,我使用的是 .obj 文件,但我在 .fbx、.glb 和 .stl 3D 对象中也遇到过此问题
如果有帮助的话,我用这个在线工具制作了我的 3D 模型。
完整代码:
from classes.constants import *
fsmode = getinput("Fullscreen? [Y/N] > ")
if (fsmode == "Y"):fsmode = True
else:fsmode = False
import time as systime, socket, socketserver, random
from ursina import *
import ursina.audio as audio
from ursina.prefabs.first_person_controller import FirstPersonController
from ursina.prefabs.health_bar import HealthBar
from ursina.shaders import *
from threading import Thread as thread
from classes.class_override import *
from classes.custom_classes import *
grav=1
player_model = "/models/player"
pcolor = color.rgb(185, 185, 135)
remoteplayer_color = color.rgb(145, 185, 145)
remoteplayer_disconnected = color.rgb(25,25,25,25)
stored_camera_y = 0
duty_cycle=0
remote_player_connected = False
r_player_justconnected = False
paused = False
block_outgoing_updates = False
app = Ursina(development_mode=False, show_ursina_splash_screen=True,fullscreen=fsmode,title="Reality Simulator (now with Portals!)")
random.seed(0)
Entity.default_shader = lit_with_shadows_shader
ground = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground")
ground2 = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(128,0,128))
ground_brick = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(0,0,128))
ground_brick2 = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(128,0,0))
spawning_platform = Entity(model='cube', collider='box', scale=(3,0.5,3), texture='brick', position=(0,0,-10))
editor_camera = EditorCamera(enabled=False, ignore_paused=True, move_speed=30)
player = FirstPersonController(model=player_model, z=-10, y=0.5, color=pcolor, origin_y=0.12, gravity=grav, speed=8, jump_height = 4, height=3, collider='mesh', name="player", cursor=Entity(parent=camera.ui, model='quad', color=color.pink, scale=.001, rotation_z=45))
# player_healthbar = HealthBar(max_value=player.max_hp, animation_duration=0.1, value=player.max_hp, parent=camera.ui)
p2 = Entity(model=player_model, color=remoteplayer_disconnected, scale=1, name='remote_player', x=-5,y=0,z=-5, rotation_y=180)
# sim_symbol = Entity(model='diamond', collider='mesh', color=color.green, name='sim_symbol', parent=player, position=(0,6,0), scale=(.5,1,.5), visible=False)
player.visible_self = False
# player = FirstPersonController(model=player_model, z=-10, color=color.orange, origin_y=-.5, speed=8)
# player.collider = MeshCollider(player, Vec3(0,1,0), Vec3(1,2,1))
arm = Entity(model='portal_gun_2', parent=camera, position=(.5,-.25,0.45), scale=.004, origin_z=-.5, rotation_z=0, on_cooldown=False, name="gun", color=pcolor, texture='/textures/w_portalgun.png')
portal_gun_showcase = Entity(model=('portal_gun.fbx'), position=(25,2,-5), scale=.05, origin_z=-.5, rotation_z=0, on_cooldown=False, name="pgun_showcase", collider='box', texture=('/textures/w_portalgun.png'))
def genstairs():
stairs(128,0.3,7,30)
thread(name="stair_gen", target=genstairs).start()
def update():
global player, stored_camera_y, duty_cycle
duty_cycle += 1
if (block_outgoing_updates):
arm.color=color.rgb(25,25,25,25)
else:
arm.color=pcolor
if held_keys['escape']:
os.abort()
if held_keys['x']:
player.y += 10
if (held_keys['left shift'] and not held_keys['control']):
player.speed = player.sprint_speed
elif (player.speed == player.sprint_speed):player.speed=8
if player.get_position()[1] < -20:
prot = player.rotation
destroy(player)
player = FirstPersonController(model=player_model, z=-10, color=pcolor, speed=8, rotation=prot, origin_y=0.12, gravity=grav, jump_height = 4, height=3, collider='mesh', name=player_model)
player.visible_self = False
print("info: player reset")
mouse.visible = False
mouse.locked = True
app.run()
添加此代码后,您可以尝试 ursina 中的
Entity.flip_faces()
功能,您的代码将如下所示:
from classes.constants import *
fsmode = getinput("Fullscreen? [Y/N] > ")
if (fsmode == "Y"):fsmode = True
else:fsmode = False
import time as systime, socket, socketserver, random
from ursina import *
import ursina.audio as audio
from ursina.prefabs.first_person_controller import FirstPersonController
from ursina.prefabs.health_bar import HealthBar
from ursina.shaders import *
from threading import Thread as thread
from classes.class_override import *
from classes.custom_classes import *
grav=1
player_model = "/models/player"
pcolor = color.rgb(185, 185, 135)
remoteplayer_color = color.rgb(145, 185, 145)
remoteplayer_disconnected = color.rgb(25,25,25,25)
stored_camera_y = 0
duty_cycle=0
remote_player_connected = False
r_player_justconnected = False
paused = False
block_outgoing_updates = False
app = Ursina(development_mode=False, show_ursina_splash_screen=True,fullscreen=fsmode,title="Reality Simulator (now with Portals!)")
random.seed(0)
Entity.default_shader = lit_with_shadows_shader
ground = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground")
ground2 = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(128,0,128))
ground_brick = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(0,0,128))
ground_brick2 = Entity(model='plane', collider='box', scale=128, texture='grass', texture_scale=(4,4), name="ground", position=(128,0,0))
spawning_platform = Entity(model='cube', collider='box', scale=(3,0.5,3), texture='brick', position=(0,0,-10))
editor_camera = EditorCamera(enabled=False, ignore_paused=True, move_speed=30)
player = FirstPersonController(model=player_model, z=-10, y=0.5, color=pcolor, origin_y=0.12, gravity=grav, speed=8, jump_height = 4, height=3, collider='mesh', name="player", cursor=Entity(parent=camera.ui, model='quad', color=color.pink, scale=.001, rotation_z=45))
# player_healthbar = HealthBar(max_value=player.max_hp, animation_duration=0.1, value=player.max_hp, parent=camera.ui)
p2 = Entity(model=player_model, color=remoteplayer_disconnected, scale=1, name='remote_player', x=-5,y=0,z=-5, rotation_y=180)
# sim_symbol = Entity(model='diamond', collider='mesh', color=color.green, name='sim_symbol', parent=player, position=(0,6,0), scale=(.5,1,.5), visible=False)
player.visible_self = False
# player = FirstPersonController(model=player_model, z=-10, color=color.orange, origin_y=-.5, speed=8)
# player.collider = MeshCollider(player, Vec3(0,1,0), Vec3(1,2,1))
arm = Entity(model='portal_gun_2', parent=camera, position=(.5,-.25,0.45), scale=.004, origin_z=-.5, rotation_z=0, on_cooldown=False, name="gun", color=pcolor, texture='/textures/w_portalgun.png')
portal_gun_showcase = Entity(model=('portal_gun.fbx'), position=(25,2,-5), scale=.05, origin_z=-.5, rotation_z=0, on_cooldown=False, name="pgun_showcase", collider='box', texture=('/textures/w_portalgun.png'))
arm.flip_faces()
portal_gun_showcase.flip_faces()
def genstairs():
stairs(128,0.3,7,30)
thread(name="stair_gen", target=genstairs).start()
def update():
global player, stored_camera_y, duty_cycle
duty_cycle += 1
if (block_outgoing_updates):
arm.color=color.rgb(25,25,25,25)
else:
arm.color=pcolor
if held_keys['escape']:
os.abort()
if held_keys['x']:
player.y += 10
if (held_keys['left shift'] and not held_keys['control']):
player.speed = player.sprint_speed
elif (player.speed == player.sprint_speed):player.speed=8
if player.get_position()[1] < -20:
prot = player.rotation
destroy(player)
player = FirstPersonController(model=player_model, z=-10, color=pcolor, speed=8, rotation=prot, origin_y=0.12, gravity=grav, jump_height = 4, height=3, collider='mesh', name=player_model)
player.visible_self = False
print("info: player reset")
mouse.visible = False
mouse.locked = True
app.run()
以前的解决方案对我不起作用,这对我有用,我使用底层 Panda3D 库来处理法线方向的反转。
from ursina import *
from panda3d.core import GeomNode
app = Ursina()
# Laad je model
entity = Entity(model='your_model.stl')
# Toegang tot de onderliggende NodePath
nodepath = entity.model
# Normals omdraaien
for node in nodepath.find_all_matches('**/+GeomNode'):
geom_node = node.node()
for i in range(geom_node.get_num_geoms()):
geom = geom_node.modify_geom(i)
# Draai de geometrie om
geom.reverse_in_place()
# Start de Ursina-app
app.run()