From 94f4f5b660228c496732d0f14fbeb1ad7c5faaf9 Mon Sep 17 00:00:00 2001 From: Torsten Kammer <2102135+cochrane@users.noreply.github.com> Date: Sat, 4 May 2024 01:17:51 +0200 Subject: [PATCH] Simplify and remove weight Full OBJ export now Swift --- GLLara.xcodeproj/project.pbxproj | 10 ++--- GLLara/GLLDocument.m | 5 +-- GLLara/GLLDocumentWindowController.m | 1 - GLLara/GLLItem+OBJExport.h | 20 --------- GLLara/GLLItem+OBJExport.m | 63 ---------------------------- GLLara/GLLItem+OBJExport.swift | 45 ++++++++++++++++++++ GLLara/GLLItemMesh+OBJExport.swift | 8 ++-- GLLara/GLLModelMesh+OBJExport.swift | 2 +- 8 files changed, 56 insertions(+), 98 deletions(-) delete mode 100644 GLLara/GLLItem+OBJExport.h delete mode 100644 GLLara/GLLItem+OBJExport.m create mode 100644 GLLara/GLLItem+OBJExport.swift diff --git a/GLLara.xcodeproj/project.pbxproj b/GLLara.xcodeproj/project.pbxproj index f8122b2d..4f900965 100644 --- a/GLLara.xcodeproj/project.pbxproj +++ b/GLLara.xcodeproj/project.pbxproj @@ -209,7 +209,7 @@ 5267F1B71615B2C400987717 /* moveNodeOnly.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 5267F1B41615B2C400987717 /* moveNodeOnly.pdf */; }; 5267F1B81615B2C400987717 /* moveParent.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 5267F1B51615B2C400987717 /* moveParent.pdf */; }; 526AB3151609BD4300940A74 /* GLLItemMesh+OBJExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526AB3141609BD4300940A74 /* GLLItemMesh+OBJExport.swift */; }; - 526AB31C1609C7C300940A74 /* GLLItem+OBJExport.m in Sources */ = {isa = PBXBuildFile; fileRef = 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.m */; }; + 526AB31C1609C7C300940A74 /* GLLItem+OBJExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.swift */; }; 526D5AE62060596000DCDE85 /* GLLNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = 526D5AE52060596000DCDE85 /* GLLNotifications.m */; }; 526E0F9C1C169E3500F198BF /* testDiffuse.png in Resources */ = {isa = PBXBuildFile; fileRef = 526E0F8B1C169E3500F198BF /* testDiffuse.png */; }; 526E0F9D1C169E3500F198BF /* testDiffuseBump.png in Resources */ = {isa = PBXBuildFile; fileRef = 526E0F8C1C169E3500F198BF /* testDiffuseBump.png */; }; @@ -647,8 +647,7 @@ 5267F1B41615B2C400987717 /* moveNodeOnly.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = moveNodeOnly.pdf; sourceTree = ""; }; 5267F1B51615B2C400987717 /* moveParent.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = moveParent.pdf; sourceTree = ""; }; 526AB3141609BD4300940A74 /* GLLItemMesh+OBJExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GLLItemMesh+OBJExport.swift"; sourceTree = ""; }; - 526AB31A1609C7C300940A74 /* GLLItem+OBJExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLLItem+OBJExport.h"; sourceTree = ""; }; - 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GLLItem+OBJExport.m"; sourceTree = ""; }; + 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GLLItem+OBJExport.swift"; sourceTree = ""; }; 526D5AE52060596000DCDE85 /* GLLNotifications.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GLLNotifications.m; sourceTree = ""; }; 526D5AE72060596E00DCDE85 /* GLLNotifications.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLLNotifications.h; sourceTree = ""; }; 526E0F891C146B8000F198BF /* GLLSceneModel 4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "GLLSceneModel 4.xcdatamodel"; sourceTree = ""; }; @@ -1369,8 +1368,7 @@ 52BB21D915FCF02200937450 /* GLLCamera.h */, 52BB21DA15FCF02200937450 /* GLLCamera.m */, 526AB3141609BD4300940A74 /* GLLItemMesh+OBJExport.swift */, - 526AB31A1609C7C300940A74 /* GLLItem+OBJExport.h */, - 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.m */, + 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.swift */, 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.swift */, 5214470C16DC2312003E260F /* GLLItem+MeshExport.swift */, 521102EE2899C430001BE4BC /* GLLItemBoneExtensions.swift */, @@ -1917,7 +1915,7 @@ 5275F6891607399800978779 /* GLLItemListController.m in Sources */, 526AB3151609BD4300940A74 /* GLLItemMesh+OBJExport.swift in Sources */, 52B6C5392BE2EB26005E53CE /* MtlFile.swift in Sources */, - 526AB31C1609C7C300940A74 /* GLLItem+OBJExport.m in Sources */, + 526AB31C1609C7C300940A74 /* GLLItem+OBJExport.swift in Sources */, 525BF29D287A0AE200E30D48 /* GLLView.swift in Sources */, 52CDFEE42875B46700BC4298 /* GLLSceneDrawer.swift in Sources */, 52301E352087E71400B3E331 /* GLLOptionalPartViewController.m in Sources */, diff --git a/GLLara/GLLDocument.m b/GLLara/GLLDocument.m index bff9d251..451b0076 100644 --- a/GLLara/GLLDocument.m +++ b/GLLara/GLLDocument.m @@ -18,7 +18,6 @@ #import "GLLItem.h" #import "GLLItemBone.h" #import "GLLItemMesh.h" -#import "GLLItem+OBJExport.h" #import "GLLLogarithmicValueTransformer.h" #import "GLLRenderWindowController.h" #import "GLLSelection.h" @@ -304,12 +303,12 @@ - (IBAction)exportSelectedModel:(id)sender NSURL *mtlURL = [NSURL URLWithString:materialLibraryName relativeToURL:objURL]; NSError *error = nil; - if (![item writeOBJToLocation:objURL withTransform:controller.includeTransformations withColor:controller.includeVertexColors error:&error]) + if (![item writeOBJWithLocation:objURL transform:controller.includeTransformations color:controller.includeVertexColors error:&error]) { [self.windowForSheet presentError:error]; return; } - if (![item writeMTLToLocation:mtlURL error:&error]) + if (![item writeMTLWithLocation:mtlURL error:&error]) { [self.windowForSheet presentError:error]; return; diff --git a/GLLara/GLLDocumentWindowController.m b/GLLara/GLLDocumentWindowController.m index 20a97a7e..11dfd021 100644 --- a/GLLara/GLLDocumentWindowController.m +++ b/GLLara/GLLDocumentWindowController.m @@ -16,7 +16,6 @@ #import "GLLDirectionalLight.h" #import "GLLDocument.h" #import "GLLItem.h" -#import "GLLItem+OBJExport.h" #import "GLLItemBone.h" #import "GLLItemController.h" #import "GLLItemListController.h" diff --git a/GLLara/GLLItem+OBJExport.h b/GLLara/GLLItem+OBJExport.h deleted file mode 100644 index 35696ff6..00000000 --- a/GLLara/GLLItem+OBJExport.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// GLLItem+OBJExport.h -// GLLara -// -// Created by Torsten Kammer on 19.09.12. -// Copyright (c) 2012 Torsten Kammer. All rights reserved. -// - -#import "GLLItem.h" - -/*! - * @abstract Methods for exporting a posed item to an OBJ file. - */ -@interface GLLItem (OBJExport) - -@property (nonatomic, readonly) BOOL willLoseDataWhenConvertedToOBJ; -- (BOOL)writeOBJToLocation:(NSURL *)location withTransform:(BOOL)transform withColor:(BOOL)color error:(NSError *__autoreleasing*)error; -- (BOOL)writeMTLToLocation:(NSURL *)location error:(NSError *__autoreleasing*)error; - -@end diff --git a/GLLara/GLLItem+OBJExport.m b/GLLara/GLLItem+OBJExport.m deleted file mode 100644 index d4b45814..00000000 --- a/GLLara/GLLItem+OBJExport.m +++ /dev/null @@ -1,63 +0,0 @@ -// -// GLLItem+OBJExport.m -// GLLara -// -// Created by Torsten Kammer on 19.09.12. -// Copyright (c) 2012 Torsten Kammer. All rights reserved. -// - -#import "GLLItem+OBJExport.h" - -#import "NSArray+Map.h" -#import "GLLItemBone.h" - -#import "GLLara-Swift.h" - -@implementation GLLItem (OBJExport) - -- (BOOL)willLoseDataWhenConvertedToOBJ -{ - return [self.meshes firstObjectMatching:^(id mesh) { - return [mesh willLoseDataWhenConvertedToOBJ]; - }] != nil; -} - -- (BOOL)writeOBJToLocation:(NSURL *)location withTransform:(BOOL)transform withColor:(BOOL)color error:(NSError *__autoreleasing*)error; -{ - NSMutableString *obj = [NSMutableString string]; - - NSString *materialLibraryName = [[location.lastPathComponent stringByDeletingPathExtension] stringByAppendingPathExtension:@"mtl"]; - [obj appendFormat:@"mtllib %@\n", materialLibraryName]; - - mat_float16 *transforms = malloc(sizeof(mat_float16) * self.bones.count); - NSUInteger boneIndex = 0; - for (GLLItemBone *bone in self.bones) - { - if (transform) - transforms[boneIndex] = bone.globalTransform; - else - transforms[boneIndex] = bone.bone.positionMatrix; - boneIndex += 1; - } - - uint32_t indexOffset = 0; - for (GLLItemMesh *mesh in self.meshes) - { - [obj appendString:[mesh writeOBJWithTransformations:transforms baseIndex:indexOffset includeColors:color]]; - indexOffset += mesh.mesh.countOfVertices; - } - - free(transforms); - return [obj writeToURL:location atomically:YES encoding:NSUTF8StringEncoding error:error]; -} - -- (BOOL)writeMTLToLocation:(NSURL *)location error:(NSError *__autoreleasing*)error; -{ - NSString *mtl = [[self.meshes map:^(GLLItemMesh *mesh) { - return [mesh writeMTLWithBaseURL:location]; - }] componentsJoinedByString:@"\n"]; - - return [mtl writeToURL:location atomically:YES encoding:NSUTF8StringEncoding error:error]; -} - -@end diff --git a/GLLara/GLLItem+OBJExport.swift b/GLLara/GLLItem+OBJExport.swift new file mode 100644 index 00000000..ef021f45 --- /dev/null +++ b/GLLara/GLLItem+OBJExport.swift @@ -0,0 +1,45 @@ +// +// GLLItem+OBJExport.m +// GLLara +// +// Created by Torsten Kammer on 19.09.12. +// Copyright (c) 2012 Torsten Kammer. All rights reserved. +// + +import Foundation + +extension GLLItem { + @objc var willLoseDataWhenConvertedToOBJ: Bool { + return meshes.first { ($0 as! GLLItemMesh).willLoseDataWhenConvertedToOBJ } != nil + } + + @objc func writeOBJ(location: URL, transform: Bool, color: Bool) throws { + var string = "" + + let materialLibraryName = location.deletingPathExtension().appendingPathExtension(".mtl").lastPathComponent + string += "usemtl \(materialLibraryName)\r\n" + + var transforms = Array(repeating: mat_float16(), count: bones.count) + var boneIndex = 0 + for bone in bones { + if transform { + transforms[boneIndex] = (bone as! GLLItemBone).globalTransform + } else { + transforms[boneIndex] = (bone as! GLLItemBone).bone.positionMatrix + } + boneIndex += 1 + } + + var indexOffset = 0 + for mesh in meshes { + string += (mesh as! GLLItemMesh).writeOBJ(transformations: transforms, baseIndex: indexOffset, includeColors: color) + indexOffset += (mesh as! GLLItemMesh).mesh.countOfVertices + } + try string.write(to: location, atomically: true, encoding: .utf8) + } + + @objc func writeMTL(location: URL) throws { + let content = meshes.map { ($0 as! GLLItemMesh).writeMTL(baseURL: location) }.joined(separator: "\r\n") + try content.write(to: location, atomically: true, encoding: .utf8) + } +} diff --git a/GLLara/GLLItemMesh+OBJExport.swift b/GLLara/GLLItemMesh+OBJExport.swift index a4c6e850..63a6fdfa 100644 --- a/GLLara/GLLItemMesh+OBJExport.swift +++ b/GLLara/GLLItemMesh+OBJExport.swift @@ -10,12 +10,12 @@ import Foundation extension GLLItemMesh { - @objc var willLoseDataWhenConvertedToOBJ: Bool { + var willLoseDataWhenConvertedToOBJ: Bool { return (self.mesh.textures.count > 1) || (self.mesh.textures.count == 1 && self.mesh.textures["diffuseTexture"]?.url == nil) || (self.renderParameters.count > 0) } - @objc func writeMTL(baseURL: URL) -> String { - var result = "newmtl material\(meshIndex)\n" + func writeMTL(baseURL: URL) -> String { + var result = "newmtl material\(meshIndex)\r\n" // Use only first texture and only if it isn't baked into the model file // TODO It's probably possible to extract this texture, but does anyone care? @@ -48,7 +48,7 @@ extension GLLItemMesh { return result } - @objc func writeOBJ(transformations: UnsafePointer, baseIndex: Int, includeColors: Bool) -> String { + func writeOBJ(transformations: [mat_float16], baseIndex: Int, includeColors: Bool) -> String { return mesh.writeOBJ(transformations: transformations, baseIndex: baseIndex, includeColors: includeColors) } diff --git a/GLLara/GLLModelMesh+OBJExport.swift b/GLLara/GLLModelMesh+OBJExport.swift index 6eed1f8c..24457323 100644 --- a/GLLara/GLLModelMesh+OBJExport.swift +++ b/GLLara/GLLModelMesh+OBJExport.swift @@ -10,7 +10,7 @@ import Foundation extension GLLModelMesh { - @objc func writeOBJ(transformations: UnsafePointer, baseIndex: Int, includeColors: Bool) -> String { + func writeOBJ(transformations: [mat_float16], baseIndex: Int, includeColors: Bool) -> String { var objString = "" let groupName = name.components(separatedBy: CharacterSet.whitespacesAndNewlines).joined(separator: "_")