Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions fast64_internal/f3d/occlusion_planes/exporter/classes.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
from dataclasses import dataclass
from mathutils import Vector
from typing import List
from bpy.types import Object

from ....utility import CData, indent


@dataclass
class OcclusionPlaneCandidate:
v0: Vector
v1: Vector
v2: Vector
v3: Vector
verts: tuple[Vector, Vector, Vector, Vector]
weight: float

def to_c(self):
def occVertexToC(vertex: Vector):
return indent * 3 + "{" + ", ".join([str(int(round(a))) for a in vertex]) + "},\n"
def vertex_to_c(self, vertex: Vector, indent_char: str):
coords = ", ".join([str(round(a)) for a in vertex])
return f"{indent_char}{{{coords}}},\n"

def vertices_to_c(self, indent_char: str):
return "".join(map(self.vertex_to_c, self.verts, [indent_char] * 4))

def to_c(self, indent_char: str) -> str:
return (
indent
+ "{\n"
+ indent * 2
+ "{\n"
+ "".join(map(occVertexToC, [self.v0, self.v1, self.v2, self.v3]))
+ indent * 2
+ "},\n"
+ indent * 2
+ str(self.weight)
+ "f\n"
+ indent
+ "},\n"
f"{indent_char}{{\n"
f"{indent_char * 2}{{\n"
f"{self.vertices_to_c(indent_char * 3)}"
f"{indent_char * 2}}},\n"
f"{indent_char * 2}{self.weight}f\n"
f"{indent_char}}},\n"
)


class OcclusionPlaneCandidatesList:
def __init__(self, ownerName):
self.planes: List[OcclusionPlaneCandidate] = []
self.name: str = ownerName + "_occlusionPlaneCandidates"
def __init__(self, owner_name: str):
self.planes: list[OcclusionPlaneCandidate] = []
self.name: str = owner_name + "_occlusionPlaneCandidates"
self.indent_char: str = indent

def add_plane(self, obj: Object, verts: tuple[Vector, Vector, Vector, Vector], weight: float):
self.planes.append(OcclusionPlaneCandidate(verts, weight))

def to_c(self):
def to_c(self) -> CData:
cdata = CData()
if len(self.planes) > 0:
name = "OcclusionPlaneCandidate " + self.name + "[" + str(len(self.planes)) + "]"
cdata.header = "extern " + name + ";\n"
cdata.source = name + " = {\n" + "".join(candidate.to_c() for candidate in self.planes) + "};\n\n"
name = f"OcclusionPlaneCandidate {self.name}[{len(self.planes)}]"
cdata.header = f"extern {name};\n"

plane_c_code = "".join(candidate.to_c(self.indent_char) for candidate in self.planes)
cdata.source = f"{name} = {{\n{plane_c_code}}};\n\n"
return cdata
2 changes: 1 addition & 1 deletion fast64_internal/f3d/occlusion_planes/exporter/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def addOcclusionQuads(
cross0 = edge30.cross(edge01)
if cross0.dot(cross1) < 0.0 or cross0.dot(cross2) < 0.0 or cross0.dot(cross3) < 0.0:
raise PluginError(f"Occlusion planes mesh {obj.name} contains a quad which is not convex.")
candidatesList.planes.append(OcclusionPlaneCandidate(verts[3], verts[2], verts[1], verts[0], weight))
candidatesList.add_plane(obj, tuple(verts), weight)

if includeChildren:
for child in obj.children:
Expand Down
2 changes: 1 addition & 1 deletion fast64_internal/sm64/sm64_collision.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def exportCollisionCommon(obj, transformMatrix, includeSpecials, includeChildren
indices.append(index)
collision.triangles[collisionType].append(CollisionTriangle(indices, specialParam, room))
if includeSpecials:
area = SM64_Area(areaIndex, "", "", "", None, None, [], name, None)
area = SM64_Area(areaIndex, "", "", "", None, None, [], name, None, False)
# This assumes that only levels will export with included specials,
# And that the collision exporter never will.
start_process_sm64_objects(obj, area, transformMatrix, True)
Expand Down
9 changes: 5 additions & 4 deletions fast64_internal/sm64/sm64_geolayout_bone.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,11 @@ def draw(self, context):
prop_split(col, geo_asm, "param", "Parameter")
col.prop(obj, "ignore_render")
col.prop(obj, "ignore_collision")
# if bpy.context.scene.f3d_type == "F3DEX3":
# box.prop(obj, "is_occlusion_planes")
# if obj.is_occlusion_planes and (not obj.ignore_render or not obj.ignore_collision):
# box.label(icon="INFO", text="Suggest Ignore Render & Ignore Collision.")
if bpy.context.scene.f3d_type == "F3DEX3":
col.prop(obj, "is_occlusion_planes")
if obj.is_occlusion_planes and (not obj.ignore_render or not obj.ignore_collision):
col.label(icon="INFO", text="Suggest Ignore Render & Ignore Collision.")
col.label(icon="ERROR", text="May not bet implemented in your repo yet.")
if context.scene.exportInlineF3D:
col.prop(obj, "bleed_independently")
if obj_scale_is_unified(obj) and len(obj.modifiers) == 0:
Expand Down
7 changes: 7 additions & 0 deletions fast64_internal/sm64/sm64_level_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,13 @@ def include_proto(file_name):
level_data.script_data += include_proto("spline.inc.c")
level_data.header_data += splinesC.header

# Write occlusion planes
if len(area.occlusion_planes.planes) > 0:
occ_planes_c = area.occlusion_planes.to_c()
saveDataToFile(os.path.join(areaDir, "occlusion_planes.inc.c"), occ_planes_c.source)
level_data.script_data += include_proto("occlusion_planes.inc.c")
level_data.header_data += occ_planes_c.header

return level_data, fModel, uses_env_fx


Expand Down
53 changes: 52 additions & 1 deletion fast64_internal/sm64/sm64_objects.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import dataclasses
import math, bpy, mathutils
from bpy.utils import register_class, unregister_class
from bpy.types import UILayout
Expand Down Expand Up @@ -34,6 +35,11 @@
DLFormat,
upgrade_old_prop,
)
from ..f3d.occlusion_planes.exporter.functions import (
addOcclusionQuads,
OcclusionPlaneCandidate,
OcclusionPlaneCandidatesList,
)

from .sm64_constants import (
levelIDNames,
Expand Down Expand Up @@ -511,9 +517,45 @@ def to_c(self, _depth=0):
)


@dataclasses.dataclass
class SM64_OcclusionPlaneCandidate(OcclusionPlaneCandidate):
room_num: int

def to_c(self, indent_char: str) -> str:
return (
f"{indent_char}{{\n"
f"{indent_char * 2}{{\n"
f"{self.vertices_to_c(indent_char * 3)}"
f"{indent_char * 2}}},\n"
f"{indent_char * 2}{self.weight}f\n"
f"{indent_char * 2}{self.room_num}\n"
f"{indent_char}}},\n"
)


class SM64_OcclusionPlaneCandidatesList(OcclusionPlaneCandidatesList):
def __init__(self, ownerName: str, enable_rooms: bool):
super().__init__(ownerName)
self.indent_char: str = "\t"
self.enable_rooms = enable_rooms

def add_plane(self, obj: bpy.types.Object, verts: list[Vector], weight: float):
self.planes.append(SM64_OcclusionPlaneCandidate(verts, weight, obj.room_num if self.enable_rooms else -1))


class SM64_Area:
def __init__(
self, index, music_seq, music_preset, terrain_type, geolayout, collision, warpNodes, name, startDialog
self,
index,
music_seq,
music_preset,
terrain_type,
geolayout,
collision,
warpNodes,
name,
startDialog,
enable_rooms: bool,
):
self.cameraVolumes = []
self.puppycamVolumes = []
Expand All @@ -533,6 +575,9 @@ def __init__(
self.splines = []
self.startDialog = startDialog
self.custom_cmds = []
self.occlusion_planes: SM64_OcclusionPlaneCandidatesList = SM64_OcclusionPlaneCandidatesList(
self.name, enable_rooms
)

def macros_name(self):
return self.name + "_macro_objs"
Expand All @@ -556,6 +601,8 @@ def to_c_script(self, includeRooms, persistentBlockString: str = ""):
if self.startDialog is not None:
data += "\t\tSHOW_DIALOG(0x00, " + self.startDialog + "),\n"
data += "\t\tTERRAIN_TYPE(" + self.terrain_type + "),\n"
if bpy.context.scene.f3d_type == "F3DEX3" and len(self.occlusion_planes.planes) > 0:
data += f"\t\tSETUP_OCCLUSION_PLANES({self.occlusion_planes.name}),\n"
data += f"{persistentBlockString}\n"
data += "\tEND_AREA(),\n"
return data
Expand Down Expand Up @@ -768,8 +815,12 @@ def exportAreaCommon(areaObj, transformMatrix, geolayout, collision, name):
[areaObj.warpNodes[i].to_c() for i in range(len(areaObj.warpNodes))],
name,
areaObj.startDialog if areaObj.showStartDialog else None,
areaObj.enableRoomSwitch,
)

if bpy.context.scene.f3d_type == "F3DEX3":
addOcclusionQuads(areaObj, area.occlusion_planes, True, transformMatrix)

start_process_sm64_objects(areaObj, area, transformMatrix, False)

return area
Expand Down