Skip to content

Commit

Permalink
[AARD-1777] Mirabuf Friction Parsing (#1096)
Browse files Browse the repository at this point in the history
Co-authored-by: Brandon Pacewic <[email protected]>
Co-authored-by: KyroVibe <[email protected]>
  • Loading branch information
3 people authored Dec 28, 2024
1 parent 37d677c commit 6d87ac2
Show file tree
Hide file tree
Showing 12 changed files with 481 additions and 445 deletions.
4 changes: 2 additions & 2 deletions exporter/SynthesisFusionAddin/Synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def register_ui() -> None:
work_panel,
lambda *_: True, # TODO: Should be redone with various refactors.
ShowAPSAuthCommand.ShowAPSAuthCommandCreatedHandler,
description=f"APS",
description=f"Login to your Autodesk account",
command=True,
)

Expand All @@ -132,7 +132,7 @@ def register_ui() -> None:
work_panel,
lambda *_: True,
ShowWebsiteCommand.ShowWebsiteCommandCreatedHandler,
description=f"Website Test",
description=f"Open our tutorials page",
command=True,
)
gm.elements.append(websiteButton)
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def readFromDesign(self) -> "ExporterOptions":
attrJsonData = makeObjectFromJson(type(field.type), json.loads(attribute.value))
setattr(self, field.name, attrJsonData)

self.visualQuality = TriangleMeshQualityOptions.LowQualityTriangleMesh
return self

@logFailure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,12 @@ def _ParseBRep(
) -> None:
meshManager = body.meshManager
calc = meshManager.createMeshCalculator()
calc.setQuality(options.visualQuality)
# Disabling for now. We need the user to be able to adjust this, otherwise it gets locked
# into whatever the default was at the time it first creates the export options.
# calc.setQuality(options.visualQuality)
calc.setQuality(adsk.fusion.TriangleMeshQualityOptions.LowQualityTriangleMesh)
# calc.maxNormalDeviation = 3.14159 * (1.0 / 6.0)
# calc.surfaceTolerance = 0.5
mesh = calc.calculate()

fill_info(trimesh, body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,26 @@ def getMaterialAppearance(

properties = fusionAppearance.appearanceProperties

roughnessProp = properties.itemById("surface_roughness")
if roughnessProp:
appearance.roughness = roughnessProp.value

# Thank Liam for this.
modelItem = properties.itemById("interior_model")
if modelItem:
matModelType = modelItem.value
baseColor = None

if matModelType == 0:
reflectanceProp = properties.itemById("opaque_f0")
if reflectanceProp:
appearance.metallic = reflectanceProp.value
baseColor = properties.itemById("opaque_albedo").value
if baseColor:
baseColor.opacity = 255
elif matModelType == 1:
baseColor = properties.itemById("metal_f0").value
appearance.metallic = 0.8
if baseColor:
baseColor.opacity = 255
elif matModelType == 2:
Expand Down
2 changes: 1 addition & 1 deletion exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def notify(self, args: adsk.core.CommandEventArgs) -> None:

processedFileName = gm.app.activeDocument.name.replace(" ", "_")
if generalConfigTab.exportLocation == ExportLocation.DOWNLOAD:
savepath = FileDialogConfig.saveFileDialog(defaultPath=exporterOptions.fileLocation)
savepath = FileDialogConfig.saveFileDialog(defaultPath="~/Documents/")

if not savepath:
# save was canceled
Expand Down
2 changes: 1 addition & 1 deletion fission/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"lint:fix": "eslint . --ext ts,tsx --report-unused-disable-directives --fix",
"prettier": "bun x prettier src --check || npx prettier src --check",
"prettier:fix": "bun x prettier src --write || npx prettier src --write",
"format": "(bun run prettier:fix && bun run lint:fix) || (npm run prettier:fix && npm run lint:fix)",
"format": "bun run prettier:fix && bun run lint:fix || npm run prettier:fix && npm run lint:fix",
"assetpack": "curl -o public/assetpack.zip https://synthesis.autodesk.com/Downloadables/assetpack.zip && tar -xf public/assetpack.zip -C public/",
"playwright:install": "bun x playwright install || npx playwright install"
},
Expand Down
151 changes: 67 additions & 84 deletions fission/src/mirabuf/MirabufInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ class MirabufInstance {
}

public constructor(parser: MirabufParser, materialStyle?: MaterialStyle, progressHandle?: ProgressHandle) {
if (parser.errors.some(x => x[0] >= ParseErrorSeverity.Unimportable)) {
if (parser.errors.some(x => x[0] >= ParseErrorSeverity.Unimportable))
throw new Error("Parser has significant errors...")
}

this._mirabufParser = parser
this._materials = new Map()
Expand All @@ -126,39 +125,32 @@ class MirabufInstance {
}

/**
* Parses all mirabuf appearances into ThreeJs materials.
* Parses all mirabuf appearances into ThreeJS and Jolt materials.
*/
private LoadMaterials(materialStyle: MaterialStyle) {
Object.entries(this._mirabufParser.assembly.data!.materials!.appearances!).forEach(
([appearanceId, appearance]) => {
let hex = 0xe32b50
let opacity = 1.0
if (appearance.albedo) {
const { A, B, G, R } = appearance.albedo
if (A && B && G && R) {
hex = (A << 24) | (R << 16) | (G << 8) | B
opacity = A / 255.0
}
}

let material: THREE.Material
if (materialStyle == MaterialStyle.Regular) {
material = new THREE.MeshPhongMaterial({
color: hex,
shininess: 0.0,
shadowSide: THREE.DoubleSide,
opacity: opacity,
transparent: opacity < 1.0,
})
} else if (materialStyle == MaterialStyle.Normals) {
material = new THREE.MeshNormalMaterial()
} else if (materialStyle == MaterialStyle.Toon) {
material = World.SceneRenderer.CreateToonMaterial(hex, 5)
console.debug("Toon Material")
}

World.SceneRenderer.SetupMaterial(material!)
this._materials.set(appearanceId, material!)
const { A, B, G, R } = appearance.albedo ?? {}
const [hex, opacity] =
A && B && G && R ? [(A << 24) | (R << 16) | (G << 8) | B, A / 255.0] : [0xe32b50, 1.0]

const material =
materialStyle === MaterialStyle.Regular
? new THREE.MeshStandardMaterial({
// No specular?
color: hex,
roughness: appearance.roughness ?? 0.5,
metalness: appearance.metallic ?? 0.0,
shadowSide: THREE.DoubleSide,
opacity: opacity,
transparent: opacity < 1.0,
})
: materialStyle === MaterialStyle.Normals
? new THREE.MeshNormalMaterial()
: World.SceneRenderer.CreateToonMaterial(hex, 5)

World.SceneRenderer.SetupMaterial(material)
this._materials.set(appearanceId, material)
}
)
}
Expand All @@ -178,61 +170,52 @@ class MirabufInstance {

const batchMap = new Map<THREE.Material, Map<string, [mirabuf.IBody, Array<mirabuf.IPartInstance>]>>()
const countMap = new Map<THREE.Material, BatchCounts>()

// Filter all instances by first material, then body
for (const instance of Object.values(instances)) {
const definition = assembly.data!.parts!.partDefinitions![instance.partDefinitionReference!]!
const bodies = definition.bodies
if (bodies) {
for (const body of bodies) {
if (!body) continue
const mesh = body.triangleMesh
if (
mesh &&
mesh.mesh &&
mesh.mesh.verts &&
mesh.mesh.normals &&
mesh.mesh.uv &&
mesh.mesh.indices
) {
const appearanceOverride = body.appearanceOverride
const material: THREE.Material = WIREFRAME
? new THREE.MeshStandardMaterial({ wireframe: true, color: 0x000000 })
: appearanceOverride && this._materials.has(appearanceOverride)
? this._materials.get(appearanceOverride)!
: fillerMaterials[nextFillerMaterial++ % fillerMaterials.length]

let materialBodyMap = batchMap.get(material)
if (!materialBodyMap) {
materialBodyMap = new Map<string, [mirabuf.IBody, Array<mirabuf.IPartInstance>]>()
batchMap.set(material, materialBodyMap)
}

const partBodyGuid = this.GetPartBodyGuid(definition, body)
let bodyInstances = materialBodyMap.get(partBodyGuid)
if (!bodyInstances) {
bodyInstances = [body, new Array<mirabuf.IPartInstance>()]
materialBodyMap.set(partBodyGuid, bodyInstances)
}
bodyInstances[1].push(instance)

if (countMap.has(material)) {
const count = countMap.get(material)!
count.maxInstances += 1
count.maxVertices += mesh.mesh.verts.length / 3
count.maxIndices += mesh.mesh.indices.length
} else {
const count: BatchCounts = {
maxInstances: 1,
maxVertices: mesh.mesh.verts.length / 3,
maxIndices: mesh.mesh.indices.length,
}
countMap.set(material, count)
}
}
Object.values(instances).forEach(instance => {
const definition = assembly.data!.parts!.partDefinitions![instance.partDefinitionReference!]
const bodies = definition?.bodies ?? []
bodies.forEach(body => {
const mesh = body?.triangleMesh?.mesh
if (!mesh?.verts || !mesh.normals || !mesh.uv || !mesh.indices) return

const appearanceOverride = body.appearanceOverride

const material = WIREFRAME
? new THREE.MeshStandardMaterial({ wireframe: true, color: 0x000000 })
: appearanceOverride && this._materials.has(appearanceOverride)
? this._materials.get(appearanceOverride)!
: fillerMaterials[nextFillerMaterial++ % fillerMaterials.length]

let materialBodyMap = batchMap.get(material)
if (!materialBodyMap) {
materialBodyMap = new Map<string, [mirabuf.IBody, Array<mirabuf.IPartInstance>]>()
batchMap.set(material, materialBodyMap)
}
}
}

const partBodyGuid = this.GetPartBodyGuid(definition, body)
let bodyInstances = materialBodyMap.get(partBodyGuid)
if (!bodyInstances) {
bodyInstances = [body, new Array<mirabuf.IPartInstance>()]
materialBodyMap.set(partBodyGuid, bodyInstances)
}
bodyInstances[1].push(instance)

if (countMap.has(material)) {
const count = countMap.get(material)!
count.maxInstances += 1
count.maxVertices += mesh.verts.length / 3
count.maxIndices += mesh.indices.length
return
}

const count: BatchCounts = {
maxInstances: 1,
maxVertices: mesh.verts.length / 3,
maxIndices: mesh.indices.length,
}
countMap.set(material, count)
})
})

// Construct batched meshes
batchMap.forEach((materialBodyMap, material) => {
Expand Down
Loading

0 comments on commit 6d87ac2

Please sign in to comment.