Преглед изворни кода

Add Rhino3dmLoader2, Rhino3dmLoadPlugin and examples/rhino3dm-load

master
Palash Bansal пре 3 година
родитељ
комит
ddc85b2080
No account linked to committer's email address

+ 34
- 0
examples/rhino3dm-load/index.html Прегледај датотеку

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rhino 3DM Load</title>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 37
- 0
examples/rhino3dm-load/script.ts Прегледај датотеку

@@ -0,0 +1,37 @@
import {_testFinish, IObject3D, Rhino3dmLoadPlugin, ThreeViewer} from 'threepipe'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
dropzone: {
allowedExtensions: ['3dm', 'hdr'],
addOptions: {
disposeSceneObjects: true,
autoSetEnvironment: true, // when hdr is dropped
autoSetBackground: true,
},
},
})

viewer.addPluginSync(Rhino3dmLoadPlugin)

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', {
setBackground: true,
})
const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/3dm/Rhino_Logo.3dm', {
autoCenter: true,
autoScale: true,
})
console.log(result)

// Some objects are invisible in this file, set visible to true for all objects
result?.traverse(object => {
object.visible = true
})
result?.setDirty()

}

init().then(_testFinish)

+ 111
- 0
src/assetmanager/import/Rhino3dmLoader2.ts Прегледај датотеку

@@ -0,0 +1,111 @@
import {Rhino3dmLoader} from 'three/examples/jsm/loaders/3DMLoader.js'
import {Color, DoubleSide, InstancedMesh, LoadingManager, Material, Mesh, MeshStandardMaterial, Object3D} from 'three'

export class Rhino3dmLoader2 extends Rhino3dmLoader {
public static LIBRARY_PATH = 'https://cdn.jsdelivr.net/npm/rhino3dm@7.15.0/'

constructor(manager?: LoadingManager) {
super(manager)
this.setLibraryPath(Rhino3dmLoader2.LIBRARY_PATH)
}
public static ImportMaterials = true

materials: Material[] = []

private _createMaterial(material: any): Material {
if (!Rhino3dmLoader2.ImportMaterials) return this.materials[0] || new MeshStandardMaterial({
color: new Color(1, 1, 1),
metalness: 0.8,
name: 'default',
side: DoubleSide,
})
// @ts-expect-error not in ts
return super._createMaterial(material)
}
private _compareMaterials!: (material: Material) => Material

async loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Object3D> {
const ret = await super.loadAsync(url, onProgress)
ret.rotateX(-Math.PI / 2) // since models are rotated
if (ret.userData.materials) delete ret.userData.materials // we don't want them saved in the file during export

// console.log(ret.userData)

const layers = ret.userData.layers
ret.traverse((obj) => {
const castShadow = obj.userData.attributes?.castsShadows
const receiveShadow = obj.userData.attributes?.receivesShadows
obj.castShadow = castShadow
obj.receiveShadow = receiveShadow
const layerIndex = obj.userData.attributes?.layerIndex || obj.userData.defAttributes?.layerIndex
const layer = layers[layerIndex]
if (layer) obj.userData.rhinoLayer = layer
obj.userData.rhino3dmRoot = ret.uuid

// console.log(obj.userData.attributes)
// instancing
this._useInstancedMesh(obj)
this._useMaterialSource(obj, layer)
})
this.materials = [] // so that next file load doesn't give the same materials.
return ret
}

private _useMaterialSource(obj: Object3D, layer: any) {
if (!Rhino3dmLoader2.ImportMaterials) return
const mesh = obj as Mesh
if ((mesh.material as any)?.name === 'default') {

// https://developer.rhino3d.com/api/rhinoscript/object_methods/objectmaterialsource.htm
const materialSource = mesh.userData.attributes?.materialSource || mesh.userData.defAttributes?.materialSource
const colorSource = mesh.userData.attributes?.colorSource || mesh.userData.defAttributes?.colorSource
// const materialSource = mesh.userData.defAttributes?.materialSource
// console.log(materialSource, mesh.userData.attributes, mesh.userData.defAttributes)
if (!materialSource && !colorSource) return
if (materialSource?.value === 0 || materialSource?.value === 1 && colorSource?.value === 0) { // material from layer
if (layer) {
mesh.material = this._compareMaterials(this._createMaterial({
diffuseColor: layer.color,
name: layer.name,
transparency: 0,
textures: [],
}))
}
} else if (materialSource?.value === 3 || materialSource?.value === 1 && colorSource?.value === 3) { // material from parent
mesh.traverseAncestors((parent: any) => {
if (parent?.material) mesh.material = parent.material
})
} else if (materialSource && materialSource.value !== 1) {
console.warn('Unknown material source', materialSource, mesh, mesh.userData.attributes)
}
}
}

static ReplaceWithInstancedMesh = false
private _useInstancedMesh(obj: Object3D) {
if (!Rhino3dmLoader2.ReplaceWithInstancedMesh) return
if (obj.children.length <= 0) return
const children = obj.children
const geometries = children.map((c: any) => c.geometry)
const uniqueGeometries = geometries.filter((g, i) => geometries.indexOf(g) === i)
uniqueGeometries.forEach((g) => {
const instances = children.filter((c: any) => c.geometry === g)
const instances2 = instances.length > 0 ? instances.filter((c: any) => c.material === (instances[0] as any).material) : []
if (instances2.length > 1) {
const instanced = new InstancedMesh(g, (instances2[0] as any).material, instances2.length)
instanced.userData = {...instances2[0].userData}
instanced.userData.instanceUserData = []
instanced.userData.attributes = instanced.userData.defAttributes || instanced.userData.attributes
if (instanced.userData.defAttributes) delete instanced.userData.defAttributes
instanced.name = instanced.userData.attributes?.name || instances2[0].name
instances2.forEach((c: any, i: number) => {
instanced.setMatrixAt(i, c.matrix)
obj.remove(c)
instanced.userData.instanceUserData.push(c.userData)
})
obj.add(instanced)
}
})
}
}


+ 1
- 0
src/assetmanager/import/index.ts Прегледај датотеку

@@ -6,3 +6,4 @@ export {ZipLoader} from './ZipLoader'
export {GLTFLoader2, type GLTFPreparser} from './GLTFLoader2'
export {DRACOLoader2} from './DRACOLoader2'
export {RGBEPNGLoader} from './RGBEPNGLoader'
export {Rhino3dmLoader2} from './Rhino3dmLoader2'

+ 3
- 0
src/index.ts Прегледај датотеку

@@ -8,6 +8,9 @@ export * from './plugins/index'
export * from './postprocessing/index'
export * from './materials/index'
export * from './rendering/index'

// testing
export {_testStart, _testFinish} from './testing/testing'

// deprecated
export {autoCenterObject3D, autoScaleObject3D} from './three/utils/object-transform'

+ 22
- 0
src/plugins/import/Rhino3dmLoadPlugin.ts Прегледај датотеку

@@ -0,0 +1,22 @@
import {IViewerPluginSync, ThreeViewer} from '../../viewer'
import {Importer, Rhino3dmLoader2} from '../../assetmanager'

export class Rhino3dmLoadPlugin implements IViewerPluginSync {
declare ['constructor']: typeof Rhino3dmLoadPlugin

public static readonly PluginType = 'Rhino3dmLoadPlugin'
private _importer = new Importer(Rhino3dmLoader2, ['3dm'], ['model/vnd.3dm', 'model/3dm'], true)

onAdded(viewer: ThreeViewer) {
viewer.assetManager.importer.addImporter(this._importer)
}

onRemove(viewer: ThreeViewer) {
viewer.assetManager.importer.removeImporter(this._importer)
}

dispose() {
return
}

}

+ 11
- 1
src/plugins/index.ts Прегледај датотеку

@@ -1,7 +1,17 @@
// base
export {PipelinePassPlugin} from './base/PipelinePassPlugin'

// pipeline
export {DepthBufferPlugin} from './pipeline/DepthBufferPlugin'
export {NormalBufferPlugin} from './pipeline/NormalBufferPlugin'
export type {DepthBufferPluginEventTypes, DepthBufferPluginPass, DepthBufferPluginTarget} from './pipeline/DepthBufferPlugin'
export {PipelinePassPlugin} from './base/PipelinePassPlugin'

// ui
export {RenderTargetPreviewPlugin} from './ui/RenderTargetPreviewPlugin'
export {TweakpaneUiPlugin} from './ui/tweakpane/TweakpaneUiPlugin'

// interaction
export {DropzonePlugin, type DropzonePluginOptions} from './interaction/DropzonePlugin'

// import
export {Rhino3dmLoadPlugin} from './import/Rhino3dmLoadPlugin'

+ 3
- 0
src/three/utils/object-transform.ts Прегледај датотеку

@@ -12,6 +12,9 @@ export function autoCenterObject3D(obj: Object3D) {
/**
* @deprecated use {@link IObject3D.autoScale} instead, or {@link iObjectCommons.autoScale}
* @param obj
* @param autoScaleRadius
* @param isCentered
* @param setDirty
*/
export function autoScaleObject3D(obj: Object3D, autoScaleRadius?: number, isCentered?: boolean, setDirty?: boolean) {
return iObjectCommons.autoScale.call(obj, autoScaleRadius, isCentered, setDirty)

Loading…
Откажи
Сачувај