Skip to content

Commit

Permalink
finish FreeCAD model support
Browse files Browse the repository at this point in the history
  • Loading branch information
ghackenberg committed Oct 8, 2024
1 parent 5d13e11 commit de7f63a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 22 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/static-code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ jobs:
run: npm install -g npm@latest
- name: Install dependencies
run: npm install
- name: Re-install opencascade.js@beta dependency
run: npm install -w packages/frontend opencascade.js@beta
- name: Build sources
run: npm run build
- name: Lint sources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ export class VersionService implements VersionREST<VersionCreate, VersionUpdate,
} else if (files.model[0].originalname.endsWith('.mpd')) {
writeFileSync(`./uploads/${versionId}.mpd`, files.model[0].buffer)
return 'mpd'
} else if (files.model[0].originalname.endsWith('.FCStd')) {
writeFileSync(`./uploads/${versionId}.FCStd`, files.model[0].buffer)
return 'FCStd'
} else {
throw new HttpException('Model file type not supported.', 400)
}
Expand Down
12 changes: 12 additions & 0 deletions packages/frontend/src/scripts/components/widgets/FileView3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader'

import { loadDAEModel } from '../../loaders/dae'
import { loadFBXModel } from '../../loaders/fbx'
import { loadFCStdModel } from '../../loaders/fcstd'
import { loadGLTFModel } from '../../loaders/gltf'
import { loadLDrawModel, pauseLoadLDrawPath, resumeLoadLDrawPath } from '../../loaders/ldraw'
import { loadPLYModel } from '../../loaders/ply'
Expand All @@ -23,6 +24,7 @@ const PLY_MODEL_CACHE: {[path: string]: Group} = {}
const FBX_MODEL_CACHE: {[path: string]: Group} = {}
const DAE_MODEL_CACHE: {[path: string]: Group} = {}
const GLTF_MODEL_CACHE: {[path: string]: GLTF} = {}
const FCSTD_MODEL_CACHE: {[path: string]: Group} = {}

const LDRAW_MODEL_CACHE: {[path: string]: Group} = {}
const LDRAW_LOADED_CACHE: {[path: string]: number} = {}
Expand Down Expand Up @@ -62,7 +64,13 @@ async function getGLTFModel(path: string) {
GLTF_MODEL_CACHE[path] = await loadGLTFModel(path)
}
return GLTF_MODEL_CACHE[path]
}

async function getFCStdModel(path: string) {
if (!(path in FCSTD_MODEL_CACHE)) {
FCSTD_MODEL_CACHE[path] = await loadFCStdModel(path)
}
return FCSTD_MODEL_CACHE[path]
}

function trackLDrawModel(path: string, callback: Callback) {
Expand Down Expand Up @@ -132,6 +140,8 @@ export const FileView3D = (props: { path: string, mouse: boolean, highlighted?:
initialGroup = GLTF_MODEL_CACHE[props.path] && GLTF_MODEL_CACHE[props.path].scene
} else if (props.path.endsWith('.ldr') || props.path.endsWith('.mpd')) {
initialGroup = LDRAW_MODEL_CACHE[props.path]
} else if (props.path.endsWith('.FCStd')) {
initialGroup = FCSTD_MODEL_CACHE[props.path]
}

const initialLoaded = (props.path.endsWith('.ldr') || props.path.endsWith('.mpd')) && LDRAW_LOADED_CACHE[props.path]
Expand Down Expand Up @@ -183,6 +193,8 @@ export const FileView3D = (props: { path: string, mouse: boolean, highlighted?:
getGLTFModel(props.path).then(model => exec && setGroup(model.scene))
} else if (props.path.endsWith('.ldr') || props.path.endsWith('.mpd')) {
getLDrawModel(props.path).then(group => exec && setGroup(group))
} else if (props.path.endsWith('.FCStd')) {
getFCStdModel(props.path).then(group => exec && setGroup(group))
}
} else {
setGroup(undefined)
Expand Down
42 changes: 24 additions & 18 deletions packages/frontend/src/scripts/components/widgets/ModelView3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,24 @@ export class ModelView3D extends React.Component<Props> {
this.highlight_cache[mesh.uuid] = mesh.material
const highlighted = this.props.highlighted.filter(prefix => comparePath(prefix, path)).length > 0
const marked = this.props.marked.filter(prefix => comparePath(prefix, path)).length > 0
if (highlighted && marked) {
mesh.material = new MeshStandardMaterial({
color: 0x0000ff
})
} else if (highlighted) {
mesh.material = new MeshStandardMaterial({
color: 0xff0000
})
} else if (marked) {
mesh.material = new MeshStandardMaterial({
color: 0x00ff00
})
} else {
mesh.material = new MeshStandardMaterial({
color: 0xffffff, transparent: true, opacity: 0.25
})
if (mesh.material instanceof MeshStandardMaterial && !mesh.material.wireframe) {
if (highlighted && marked) {
mesh.material = new MeshStandardMaterial({
color: 0x0000ff
})
} else if (highlighted) {
mesh.material = new MeshStandardMaterial({
color: 0xff0000
})
} else if (marked) {
mesh.material = new MeshStandardMaterial({
color: 0x00ff00
})
} else {
mesh.material = new MeshStandardMaterial({
color: 0xffffff, transparent: true, opacity: 0.25
})
}
}
}
// Process children
Expand Down Expand Up @@ -154,7 +156,9 @@ export class ModelView3D extends React.Component<Props> {
const copy = material.clone()
if (copy instanceof MeshStandardMaterial) {
const standard = copy as MeshStandardMaterial
standard.emissive.setScalar(0.1)
if (!standard.wireframe) {
standard.emissive.setScalar(0.1)
}
}
array.push(copy)
}
Expand All @@ -163,7 +167,9 @@ export class ModelView3D extends React.Component<Props> {
const copy = mesh.material.clone()
if (copy instanceof MeshStandardMaterial) {
const standard = copy as MeshStandardMaterial
standard.emissive.setScalar(0.1)
if (!standard.wireframe) {
standard.emissive.setScalar(0.1)
}
}
mesh.material = copy
}
Expand Down
9 changes: 5 additions & 4 deletions packages/frontend/src/scripts/loaders/fcstd.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { TextWriter, Uint8ArrayWriter, ZipReader } from '@zip.js/zip.js'
import { BlobReader, TextWriter, Uint8ArrayWriter, ZipReader } from '@zip.js/zip.js'
import initOpenCascade, { OpenCascadeInstance } from 'opencascade.js'
import { Color, Group, Mesh, MeshStandardMaterial, Object3D } from 'three'
import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader'

import { BRep, parseBRep } from './brep'
import { parseGLTFModel } from './gltf'
import { CacheAPI } from '../clients/cache'

let OCCT: Promise<OpenCascadeInstance>

Expand Down Expand Up @@ -60,8 +61,8 @@ export class FreeCADObject {
}

export async function loadFCStdModel(path: string) {
console.log('Not yet implemented!', path)
return new Group()
const file = await CacheAPI.loadFile(path)
return parseFCStdModel(new BlobReader(new Blob([file])))
}

function traverse(object: Object3D, material: MeshStandardMaterial) {
Expand All @@ -73,7 +74,7 @@ function traverse(object: Object3D, material: MeshStandardMaterial) {
}
}

export async function parseFCStdModel(data: ReadableStream) {
export async function parseFCStdModel(data: ReadableStream | BlobReader) {
const diffuse: {[name: string]: MeshStandardMaterial[]} = {}
const breps: {[name: string]: BRep} = {}
const gltfs: {[name: string]: GLTF} = {}
Expand Down

0 comments on commit de7f63a

Please sign in to comment.