scpcb-godot/src/file_parsers/RMesh.gd

579 lines
16 KiB
GDScript

class_name RMesh
static func ReadString(reader:BufferStuffReader):
var length = reader.readInt()
return reader.readBuffer(length).get_string_from_ascii()
const WORLD_SCALE = 0.010
static func StripFilename(file: String):
var mi = ""
var lastSlash = 0
if len(file) > 0:
for i in range(len(file)):
mi = file.substr(i, 1)
if mi == "\\" or mi == "//":
lastSlash = i
return file.substr(0, lastSlash + 1)
static var EMPTY_TEXTURE = Texture2D.new()
static var RMESH_LOAD_COUNT = 0
static func LoadRMesh(parentNode: Node3D, file: String):
var correctedPath = file.replace("\\", "/")
var fileName = correctedPath.split("/")[-1]
var fileHandle = FileAccess.open(str("res://", correctedPath), FileAccess.READ)
var reader = BufferStuffReader.create(fileHandle.get_buffer(fileHandle.get_length()))
fileHandle.close()
var header = ReadString(reader)
var hasTriggerBox = header == "RoomMesh.HasTriggerBox"
if header != "RoomMesh":
print(str(correctedPath, " is Not RMESH"))
return
var scene = Node3D.new()
scene.name = str(fileName, "_", RMESH_LOAD_COUNT)
RMESH_LOAD_COUNT += 1
parentNode.add_child(scene)
var count: int = 0
var count2: int = 0
file = StripFilename(file)
#print(file)
var i
var j
var k
var x
var y
var z
var yaw
var temp1i:int
var temp2i:int
var temp3i:int
var temp1
var temp2
var temp3
var temp1s:String
var temp2s:String
var blendType: int
var textureName: String
#drawn meshes
var Opaque = Mesh.new()
var Alpha = Mesh.new()
count = reader.readInt()
var childMesh
var surf
var tex: Array = [0, 0]
var brush
var isAlpha:float
var u:float
var v:float
var activeAlbedo: Texture2D = null
var activeAlbedoHasAlpha = false
var activeBump: Texture2D = null
for i1 in range(count): # drawn mesh
childMesh = Mesh.new()
var vertices = PackedVector3Array()
var uvs = PackedVector2Array()
var tris = PackedInt32Array()
#surf=CreateSurface(childMesh)
#brush=CreateBrush()
tex[0] = 0
tex[1] = 0
isAlpha = 0
for j2 in range(2):
blendType = reader.readUByte()
if blendType != 0:
textureName = ReadString(reader)
tex[j2] = Global.GetTextureFromCache(textureName)
if tex[j2] == null: # texture is not in cache
if blendType < 3:
tex[j2] = Global.LoadTexture(str(file, textureName))
else:
tex[j2] = Global.LoadTexture(str(file, textureName)) # TODO: load with alpha
#if tex[j2] != 0:
#If blendType=1 Then TextureBlend tex[j2],5
#If Instr(Lower(textureName),"_lm")<>0 Then
#TextureBlend tex[j2],3
#EndIf
#AddTextureToCache(tex[j2])
#EndIf
if tex[j2] != null:
isAlpha = 2
if blendType == 3:
isAlpha = 1
#TextureCoords tex[j2],1-j
activeAlbedo = EMPTY_TEXTURE
activeAlbedoHasAlpha = isAlpha == 1
#if isAlpha == 1:
if tex[1] != null:
#TextureBlend tex[1],2
#BrushTexture brush,tex[1],0,0
activeAlbedo = tex[1]
else:
#BrushTexture brush,blankTexture,0,0
activeAlbedo = EMPTY_TEXTURE
#else:
#if tex[0] != null and tex[1] != null:
#bumptex% = GetBumpFromCache(StripPath(TextureName(tex[1])))
#;If bumptex<>0 Then
#; DebugLog StripPath(TextureName(bumptex))
#; Stop
#;EndIf
#For j=0 To 1
#BrushTexture brush,tex[j],0,j+1+(bumptex<>0)
#Next
#
#BrushTexture brush,AmbientLightRoomTex,0
#If (bumptex<>0) Then
#BrushTexture brush,bumptex,0,1
#EndIf
#Else
#For j=0 To 1
#If tex[j]<>0 Then
#BrushTexture brush,tex[j],0,j
#Else
#BrushTexture brush,blankTexture,0,j
#EndIf
#Next
#EndIf
#EndIf
#surf=CreateSurface(childMesh)
#if isAlpha > 0:
#PaintSurface surf,brush
#FreeBrush brush : brush = 0
count2 = reader.readInt() # vertices
for j2 in range(count2):
# world coords
x = -reader.readFloat() * WORLD_SCALE
y = reader.readFloat() * WORLD_SCALE
z = reader.readFloat() * WORLD_SCALE
#vertex = AddVertex(surf,x,y,z)
vertices.push_back(Vector3(x, y, z))
#var meshInstance = MeshInstance3D.new()
#meshInstance.mesh = QuadMesh.new()
#var mat = StandardMaterial3D.new()
#mat.albedo_color = Color.RED
#mat.billboard_mode = BaseMaterial3D.BILLBOARD_ENABLED
#meshInstance.set_surface_override_material(0, mat)
#scene.add_child(meshInstance)
#meshInstance.global_position.x = x
#meshInstance.global_position.y = y
#meshInstance.global_position.z = z
# texture coords
for k2 in range(0, 1):
u = reader.readFloat()
v = reader.readFloat()
#VertexTexCoords surf,vertex,u,v,0.0,k
uvs.push_back(Vector2(u, v))
reader.readFloat()
reader.readFloat()
# colors
temp1i = reader.readUByte()
temp2i = reader.readUByte()
temp3i = reader.readUByte()
#print(str("Got vertex. Pos:", Vector3(x, y, z), ", UV:", Vector2(u, v), ", Color:", Color(temp1i, temp2i, temp3i)))
#VertexColor surf,vertex,temp1i,temp2i,temp3i,1.0
count2 = reader.readInt() # polys
for j2 in range(count2):
tris.push_back(reader.readInt())
tris.push_back(reader.readInt())
tris.push_back(reader.readInt())
#AddTriangle(surf,temp1i,temp2i,temp3i)
if isAlpha == 1:
#AddMesh childMesh,Alpha
#EntityAlpha childMesh,0.0
#print("loaded transparent face")
x
else:
x
#AddMesh childMesh,Opaque
#EntityParent childMesh,collisionMeshes
#EntityAlpha childMesh,0.0
#EntityType childMesh,HIT_MAP
#EntityPickMode childMesh,2
#
#;make collision double-sided
#Local flipChild% = CopyMesh(childMesh)
#FlipMesh(flipChild)
#AddMesh flipChild,childMesh
#FreeEntity flipChild
#print("loaded opaque geometry")
#var st = SurfaceTool.new()
#st.begin(Mesh.PRIMITIVE_LINE_STRIP)
#var mat = StandardMaterial3D.new()
#mat.albedo_color = Color.RED
#st.set_material(mat)
#for i2 in range(len(vertices)):
##st.add(uvs[i2])
#st.add_vertex(vertices[i2])
#st.
var mesh = MeshInstance3D.new()
var arr_mesh = ArrayMesh.new()
var arr = []
arr.resize(Mesh.ARRAY_MAX)
arr[Mesh.ARRAY_VERTEX]=vertices
arr[Mesh.ARRAY_TEX_UV]=uvs
arr[Mesh.ARRAY_INDEX]=tris
var meshInstance = MeshInstance3D.new()
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr)
meshInstance.mesh = arr_mesh
var mat = StandardMaterial3D.new()
#mat.albedo_color = Color(randi() % 255 / 255.0, randi() % 255 / 255.0, randi() % 255 / 255.0)
mat.albedo_texture = activeAlbedo
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA_DEPTH_PRE_PASS if activeAlbedoHasAlpha else BaseMaterial3D.TRANSPARENCY_DISABLED
meshInstance.set_surface_override_material(0, mat)
meshInstance.create_trimesh_collision()
scene.add_child(meshInstance)
#print("YOYOYO MARKER")
#Local hiddenMesh%
#hiddenMesh=CreateMesh()
#var collisionMesh = ArrayMesh.new()
#
#var collision = CollisionPolygon3D.new()
#collision.
count = reader.readInt() # invisible collision mesh
for i1 in range(count):
var verts = PackedVector3Array()
var tris = PackedInt32Array()
#surf=CreateSurface(hiddenMesh)
count2 = reader.readInt() # vertices
for j2 in range(count2):
# world coords
x = -reader.readFloat() * WORLD_SCALE
y = reader.readFloat() * WORLD_SCALE
z = reader.readFloat() * WORLD_SCALE
verts.push_back(Vector3(x, y, z))
count2 = reader.readInt() # polys
for j2 in range(count2):
temp1i = reader.readInt()
temp2i = reader.readInt()
temp3i = reader.readInt()
tris.push_back(temp1i)
tris.push_back(temp2i)
tris.push_back(temp3i)
tris.push_back(temp1i)
tris.push_back(temp3i)
tris.push_back(temp2i)
var mesh = MeshInstance3D.new()
var arr_mesh = ArrayMesh.new()
var arr = []
arr.resize(Mesh.ARRAY_MAX)
arr[Mesh.ARRAY_VERTEX]=verts
arr[Mesh.ARRAY_INDEX]=tris
var meshInstance = MeshInstance3D.new()
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr)
meshInstance.mesh = arr_mesh
var mat = StandardMaterial3D.new()
#mat.albedo_color = Color(randi() % 255 / 255.0, randi() % 255 / 255.0, randi() % 255 / 255.0)
mat.albedo_color = Color.GREEN
meshInstance.set_surface_override_material(0, mat)
meshInstance.create_trimesh_collision()
meshInstance.visible = true
scene.add_child(meshInstance)
# trigger boxes
if hasTriggerBox:
#print("TriggerBoxEnable")
var triggerBoxAmount = reader.readInt()
for tb in range(triggerBoxAmount):
var tbVerts = PackedVector3Array()
var tbIndexes = PackedInt32Array()
#rt\TempTriggerbox[tb] = CreateMesh(rt\obj)
count = reader.readInt()
for i1 in range(count):
#surf=CreateSurface(rt\TempTriggerbox[tb])
count2 = reader.readInt()
for j2 in range(count2):
x = -reader.readFloat() * WORLD_SCALE
y = reader.readFloat() * WORLD_SCALE
z = reader.readFloat() * WORLD_SCALE
tbVerts.push_back(Vector3(x, y, z))
#vertex=AddVertex(surf,x,y,z)
count2 = reader.readInt()
for j2 in range(count2):
temp1i = reader.readInt()
temp2i = reader.readInt()
temp3i = reader.readInt()
tbIndexes.push_back(temp1i)
tbIndexes.push_back(temp2i)
tbIndexes.push_back(temp3i)
tbIndexes.push_back(temp1i)
tbIndexes.push_back(temp3i)
tbIndexes.push_back(temp2i)
#AddTriangle(surf,temp1i,temp2i,temp3i)
#AddTriangle(surf,temp1i,temp3i,temp2i)
var mesh = MeshInstance3D.new()
var arr_mesh = ArrayMesh.new()
var arr = []
arr.resize(Mesh.ARRAY_MAX)
arr[Mesh.ARRAY_VERTEX]=tbVerts
arr[Mesh.ARRAY_INDEX]=tbIndexes
var meshInstance = MeshInstance3D.new()
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr)
meshInstance.mesh = arr_mesh
var mat = StandardMaterial3D.new()
#mat.albedo_color = Color(randi() % 255 / 255.0, randi() % 255 / 255.0, randi() % 255 / 255.0)
mat.albedo_color = Color.RED
meshInstance.set_surface_override_material(0, mat)
meshInstance.create_trimesh_collision()
#meshInstance.visible = false
scene.add_child(meshInstance)
meshInstance.name = ReadString(reader)
#rt\TempTriggerboxName[tb] = ReadString(f)
count = reader.readInt() # point entities
for i1 in range(count):
temp1s = ReadString(reader)
#print(str("POINT ENTITY: ", temp1s))
if temp1s == "screen":
temp1 = -reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
temp2s = ReadString(reader)
if temp1 != 0 or temp2 != 0 or temp3 != 0:
var ts = TempScreen.new()
ts.x = temp1
ts.y = temp2
ts.z = temp3
ts.imgpath = temp2s
#ts\roomtemplate = rt
elif temp1s == "waypoint":
temp1 = -reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
var marker = Marker3D.new()
marker.position = Vector3(temp1, temp2, temp3)
scene.add_child(marker)
#Local w.TempWayPoints = New TempWayPoints
#w\roomtemplate = rt
#w\x = temp1
#w\y = temp2
#w\z = temp3
#
elif temp1s == "light":
temp1 = -reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
if temp1 != 0 or temp2 != 0 or temp3 != 0:
var range = reader.readFloat() / 2000.0
var lcolor = ReadString(reader).split(" ")
var intensity = min(reader.readFloat() * 0.8, 1.0)
#print(str("light. Range: ", range, ", lcolor: ", lcolor, ", intensity:", intensity))
var r = int(lcolor[0]) / 255 * intensity
var g = int(lcolor[1]) / 255 * intensity
var b = int(lcolor[2]) / 255 * intensity
var pointlight = OmniLight3D.new()
pointlight.light_color = Color(r, g, b)
#scene.add_child(pointlight)
pointlight.position = Vector3(temp1, temp2, temp3)
#AddTempLight(rt, temp1,temp2,temp3, 2, range, r,g,b)
else:
reader.readFloat()
ReadString(reader)
reader.readFloat()
elif temp1s == "spotlight":
temp1 = -reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
if temp1 != 0 or temp2 != 0 or temp3 != 0:
var range = reader.readFloat() / 2000.0
var lcolor = ReadString(reader).split(" ")
var intensity = min(reader.readFloat() * 0.8, 1.0)
#r%=Int(Piece(lcolor,1," "))*intensity
#g%=Int(Piece(lcolor,2," "))*intensity
#b%=Int(Piece(lcolor,3," "))*intensity
#
#Local lt.LightTemplates = AddTempLight(rt, temp1,temp2,temp3, 2, range, r,g,b)
var angles = ReadString(reader)
#pitch#=Piece(angles,1," ")
#yaw#=Piece(angles,2," ")
#lt\pitch = pitch
#lt\yaw = yaw
#
var innerconeangle = reader.readInt()
var outerconeangle = reader.readInt()
#print(str("spotlight. Range: ", range, ", lcolor: ", lcolor, ", intensity:", intensity, ", angles: ", angles, ", innerconeangle: ", innerconeangle, ", outerconeangle: ", outerconeangle))
#lt\innerconeangle = ReadInt(f)
#lt\outerconeangle = ReadInt(f)
else:
reader.readFloat()
ReadString(reader)
reader.readFloat()
ReadString(reader)
reader.readInt()
reader.readInt()
elif temp1s == "soundemitter":
reader.readFloat()
reader.readFloat()
reader.readFloat()
reader.readInt()
reader.readFloat()
#temp1i=0
#For j = 0 To MaxRoomEmitters-1
#If rt\TempSoundEmitter[j]=0 Then
#rt\TempSoundEmitterX[j]=ReadFloat(f)*RoomScale
#rt\TempSoundEmitterY[j]=ReadFloat(f)*RoomScale
#rt\TempSoundEmitterZ[j]=ReadFloat(f)*RoomScale
#rt\TempSoundEmitter[j]=ReadInt(f)
#
#rt\TempSoundEmitterRange[j]=ReadFloat(f)
#temp1i=1
#Exit
#EndIf
#Next
#
#If temp1i=0 Then
#ReadFloat(f)
#ReadFloat(f)
#ReadFloat(f)
#ReadInt(f)
#ReadFloat(f)
#EndIf
#
elif temp1s == "playerstart":
temp1 = -reader.readFloat()
temp2 = reader.readFloat()
temp3 = reader.readFloat()
var angles = ReadString(reader)
#pitch = Piece(angles,1," ")
#yaw#=Piece(angles,2," ")
#roll#=Piece(angles,3," ")
#If cam Then
#PositionEntity cam,temp1,temp2,temp3
#RotateEntity cam,pitch,yaw,roll
#EndIf
elif temp1s == "model":
var modelPath = ReadString(reader)
if modelPath != "":
#Local model = CreatePropObj("GFX\Map\Props\"+modelPath);LoadMesh("GFX\Map\Props\"+modelPath)
var model = X.LoadModel(str("GFX/Map/Props/", modelPath))
scene.add_child(model)
#
temp1 = -reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
model.position = Vector3(temp1, temp2, temp3)
#PositionEntity model,temp1,temp2,temp3
#
temp1 = reader.readFloat()
temp2 = reader.readFloat()
temp3 = reader.readFloat()
model.rotation = Vector3(deg_to_rad(temp1), deg_to_rad(temp2), deg_to_rad(temp3))
#RotateEntity model,temp1,temp2,temp3
#
temp1 = reader.readFloat() * WORLD_SCALE
temp2 = reader.readFloat() * WORLD_SCALE
temp3 = reader.readFloat() * WORLD_SCALE
model.scale = Vector3(temp1, temp2, temp3)
#ScaleEntity model,temp1,temp2,temp3
#
#EntityParent model,Opaque
#EntityType model,HIT_MAP
#EntityPickMode model,2
#Else
#DebugLog "file = 0"
#temp1=ReadFloat(f) : temp2=ReadFloat(f) : temp3=ReadFloat(f)
#DebugLog temp1+", "+temp2+", "+temp3
#
#;Stop
#EndIf
#Next
#
#Local obj%
#
#temp1i=CopyMesh(Alpha)
#FlipMesh temp1i
#AddMesh temp1i,Alpha
#FreeEntity temp1i
#
#If brush <> 0 Then FreeBrush brush
#
#AddMesh Alpha,Opaque
#FreeEntity Alpha
#
#EntityFX Opaque,3
#
#EntityAlpha hiddenMesh,0.0
#EntityAlpha Opaque,1.0
#
#;EntityType Opaque,HIT_MAP
#EntityType hiddenMesh,HIT_MAP
#FreeTexture blankTexture
#
#;AddMesh hiddenMesh,BigRoomMesh
#
#obj=CreatePivot()
#CreatePivot(obj) ;skip "meshes" object
#EntityParent Opaque,obj
#EntityParent hiddenMesh,obj
#CreatePivot(obj) ;skip "pointentites" object
#CreatePivot(obj) ;skip "solidentites" object
#EntityParent collisionMeshes,obj
#
#CloseFile f
#
#CatchErrors("LoadRMesh")
#Return obj%