fix visible obj occluded by portals

This commit is contained in:
ABelliqueux 2021-04-02 12:41:32 +02:00
parent 39b660dbd8
commit 036b07e2be

View File

@ -18,6 +18,8 @@ import bmesh
import unicodedata import unicodedata
import subprocess
from math import radians, degrees, floor, cos, sin, sqrt from math import radians, degrees, floor, cos, sin, sqrt
from mathutils import Vector from mathutils import Vector
@ -36,6 +38,8 @@ from bpy_extras.io_utils import (ExportHelper,
from bpy_extras.object_utils import world_to_camera_view from bpy_extras.object_utils import world_to_camera_view
from PIL import Image
class ExportMyFormat(bpy.types.Operator, ExportHelper): class ExportMyFormat(bpy.types.Operator, ExportHelper):
bl_idname = "export_psx.c"; bl_idname = "export_psx.c";
@ -71,11 +75,20 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
name="Use precalculated BGs", name="Use precalculated BGs",
description="Set the BGs UV to black", description="Render backgrounds and converts them to TIMs",
default=False, default=False,
) )
# ~ exp_ShowPortals = BoolProperty(
# ~ name="Render Portals in precalculated BGs",
# ~ description="Useful for debugging",
# ~ default=False,
# ~ )
def execute(self, context): def execute(self, context):
def triangulate_object(obj): def triangulate_object(obj):
@ -248,6 +261,20 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
return "intersect" return "intersect"
def objVertLtoW(target):
worldPos = []
mw = target.matrix_world
mesh = bpy.data.meshes[ target.name ]
for vertex in mesh.vertices:
worldPos.append( mw * vertex.co * scale )
return worldPos
def objVertWtoS(scene, cam, target, toScale = 1): def objVertWtoS(scene, cam, target, toScale = 1):
screenPos = [] screenPos = []
@ -284,7 +311,7 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
vector.x = max ( 0, min ( resX, int( resX * vector.x ) ) ) vector.x = max ( 0, min ( resX, int( resX * vector.x ) ) )
vector.y = max ( 0, min ( resY, int( resY * vector.y ) ) ) vector.y = resY - max ( 0, min ( resY, int( resY * vector.y ) ) )
vector.z = int( vector.z ) vector.z = int( vector.z )
@ -357,6 +384,12 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if o.type == 'CAMERA' and o.name.startswith("camPath"): if o.type == 'CAMERA' and o.name.startswith("camPath"):
filepath = folder + os.sep + "TIM" + os.sep
filename = "bg_" + CleanName(o.name)
fileext = "." + str(bpy.context.scene.render.image_settings.file_format).lower()
# Set camera as active # Set camera as active
bpy.context.scene.camera = o bpy.context.scene.camera = o
@ -365,7 +398,30 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
bpy.ops.render.render() bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(folder + os.sep + "TIM" + os.sep + "bg_" + CleanName(o.name) + "." + str(bpy.context.scene.render.image_settings.file_format).lower()) bpy.data.images["Render Result"].save_render( filepath + filename + fileext )
# Convert to 256 colors png with PILlow
# TODO : Add Pillow lib
# ~ bgFile = Image.open( filepath + filename + fileext )
# ~ bgFile = bgFile.convert('RGB').convert('P', palette=Image.ADAPTIVE )
# ~ bgFile.save( filepath + filename + fileext )
# Convert to tim with img2tim ( https://github.com/Lameguy64/img2tim )
exe = ""
if os.name == 'nt':
exe = ".exe"
# ImageMagick alternative
# ~ subprocess.call( [ "convert", filepath + filename + fileext, "-colors", "256", filepath + filename + fileext ] )
# ~ subprocess.call( [ "img2tim" + exe, "-t", "-bpp", "8", "-org", "320", "0", "-plt" , "0", "481","-o", filepath + filename + ".tim", filepath + filename + fileext ] )
# Add camera object to camAngles # Add camera object to camAngles
@ -533,7 +589,15 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if bpy.data.objects[o].type == 'MESH': if bpy.data.objects[o].type == 'MESH':
if bpy.data.objects[o].data.get('isRigidBody') or bpy.data.objects[o].data.get('isStaticBody') : if (
bpy.data.objects[o].data.get('isRigidBody') or
bpy.data.objects[o].data.get('isStaticBody')
#or bpy.data.objects[o].data.get('isPortal')
):
rayTargets.append(bpy.data.objects[o]) rayTargets.append(bpy.data.objects[o])
@ -1324,7 +1388,7 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
# Chech object is in view frame # Chech object is in view frame
if isInFrame(scene, camera, target): if isInFrame(scene, camera, target):# and not target.data.get('isPortal') :
# Get normalized direction vector between camera and object # Get normalized direction vector between camera and object
@ -1336,16 +1400,54 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
# Unpack results into several variables. # Unpack results into several variables.
# We're only interested in 'hitObject' though # We're only interested in 'hitObject' though
result, location, normal, index, hitObject, matrix = scene.ray_cast( camera.location, dirToTarget ) result, hitLocation, normal, index, hitObject, matrix = scene.ray_cast( camera.location, dirToTarget )
# If hitObject is the same as target, nothing is obstructing it's visibility # If hitObject is the same as target, nothing is obstructing it's visibility
if hitObject is not None: if hitObject is not None:
if hitObject in rayTargets: # If hit object is a portal, cast a new ray from hit location to target
if hitObject.data.get('isPortal'):
# Find out if we're left or right of portal
v0 = hitObject.matrix_world * hitObject.data.vertices[0].co
v1 = hitObject.matrix_world * hitObject.data.vertices[1].co
side = checkLine(v0.x, v0.y, v1.x, v1.y , camera.location.x, camera.location.y, camera.location.x, camera.location.y )
if side == 'front':
offset = [ 1.001, 0.999, 0.999 ]
else :
offset = [ 0.999, 1.001, 1.001 ]
origin = Vector( ( hitLocation.x * offset[0], hitLocation.y * offset[1], hitLocation.z * offset[2] ) )
print(hitObject.name + " is a portal at " + str( hitLocation ) + " N : " + str(normal) + " - " + side + "Or : " + str(origin) )
result, hitLocationPort, normal, index, hitObjectPort, matrix = scene.ray_cast( origin , dirToTarget )
print( camera.name + " : recasting from " + str( origin ) + " to " + target.name )
if hitObjectPort is not None:
if hitObjectPort in rayTargets:
print(hitObjectPort.name)
visibleTarget.append(target)
elif hitObject in rayTargets:
visibleTarget.append(target) visibleTarget.append(target)
print("\n")
if bpy.data.objects[ actorPtr ] not in visibleTarget: if bpy.data.objects[ actorPtr ] not in visibleTarget:
visibleTarget.append( bpy.data.objects[ actorPtr ] ) visibleTarget.append( bpy.data.objects[ actorPtr ] )
@ -1385,22 +1487,40 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
for portal in visiblePortal: for portal in visiblePortal:
s = objVertWtoS( scene, camera, portal ) w = objVertLtoW(portal)
# Write quad NW, NE, SE, SW f.write("// " + str(portal) + "\n" )
# Write portal'vertices world coordinates NW, NE, SE, SW
f.write("\t{\n\t\t" + f.write("\t{\n\t\t" +
"{ " + str( int (s[3].x ) ) + ", " + str( int (s[3].y ) ) + ", " + str( int (s[3].z ) ) + ", 0 },\n\t\t" + "{ " + str( int (w[3].x ) ) + ", " + str( int (w[3].y ) ) + ", " + str( int (w[3].z ) ) + ", 0 },\n\t\t" +
"{ " + str( int (s[2].x ) ) + ", " + str( int (s[2].y ) ) + ", " + str( int (s[2].z ) ) + ", 0 },\n\t\t" + "{ " + str( int (w[2].x ) ) + ", " + str( int (w[2].y ) ) + ", " + str( int (w[2].z ) ) + ", 0 },\n\t\t" +
"{ " + str( int (s[0].x ) ) + ", " + str( int (s[0].y ) ) + ", " + str( int (s[0].z ) ) + ", 0 },\n\t\t" + "{ " + str( int (w[0].x ) ) + ", " + str( int (w[0].y ) ) + ", " + str( int (w[0].z ) ) + ", 0 },\n\t\t" +
"{ " + str( int (s[1].x ) ) + ", " + str( int (s[1].y ) ) + ", " + str( int (s[1].z ) ) + ", 0 }\n" + "{ " + str( int (w[1].x ) ) + ", " + str( int (w[1].y ) ) + ", " + str( int (w[1].z ) ) + ", 0 }\n" +
"\t},\n" ) "\t},\n" )
# UNUSED : Screen coords
# ~ s = objVertWtoS( scene, camera, portal )
# ~ f.write("\t{\n\t\t" +
# ~ "{ " + str( int (s[3].x ) ) + ", " + str( int (s[3].y ) ) + ", " + str( int (s[3].z ) ) + ", 0 },\n\t\t" +
# ~ "{ " + str( int (s[2].x ) ) + ", " + str( int (s[2].y ) ) + ", " + str( int (s[2].z ) ) + ", 0 },\n\t\t" +
# ~ "{ " + str( int (s[0].x ) ) + ", " + str( int (s[0].y ) ) + ", " + str( int (s[0].z ) ) + ", 0 },\n\t\t" +
# ~ "{ " + str( int (s[1].x ) ) + ", " + str( int (s[1].y ) ) + ", " + str( int (s[1].z ) ) + ", 0 }\n" +
# ~ "\t},\n" )
f.write("\t" + str( len( visibleTarget ) ) + ",\n" + f.write("\t" + str( len( visibleTarget ) ) + ",\n" +
"\t{\n") "\t{\n")
@ -1512,8 +1632,11 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
Yvalues.append( (mw * v.co).y ) Yvalues.append( (mw * v.co).y )
LvlObjects[o.name] = {'x1' : min(Xvalues), LvlObjects[o.name] = {'x1' : min(Xvalues),
'y1' : min(Yvalues), 'y1' : min(Yvalues),
'x2' : max(Xvalues), 'x2' : max(Xvalues),
'y2' : max(Yvalues)} 'y2' : max(Yvalues)}
# Clear X/Y lists for next iteration # Clear X/Y lists for next iteration