演示地址:https://capricorncd.github.io/blog/dist/three/index.html#/ClockObj

源码:https://github.com/capricorncd/blog/tree/master/demos/three

C4D文件:clock(R21.207).c4d https://github.com/capricorncd/blog/tree/master/c4d

流程

  • C4D建模
  • 导出.obj文件
  • js实现(Three.js),此例开发环境应用的Webpack+React

一、C4D建模

这里B站有视频教程,这里就不赘述。

在线视频教程:https://www.bilibili.com/video/BV177411P7d1?p=3

建模时留神须要留神的中央:

  • 建模:不能应用面(Disc)建模,在浏览器中不会显示,需改用圆柱体(Cylinder)。
  • 贴图:需给每个几何体贴图,不能应用分组贴图。在Three.js中分组贴图不能与单个几何体绑定,顾浏览器中不会显示贴图。

二、导出.obj文件

C4D中实现建模和贴图后,就能够导出.obj文件。

# 工具栏file -> Export -> Wavefront OBJ(*.obj)

其余导出选项默认即可。导出obj文件的同时,会导出一个同名贴图.mtl文件。

三、js实现

# "three": "^0.120.1"npm i -S three# oryarn add three

src/components/ClockObj/core.js

import {  AmbientLight,  DirectionalLight, PerspectiveCamera,  Scene, WebGLRenderer} from 'three'import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'let scene, renderer/** * 加载贴图和模型对象文件  * load resource  * @returns {Promise<unknown>} */ function loadResource() {   return new Promise((resolve, reject) => {     const objLoader = new OBJLoader()     const mtlLoader = new MTLLoader()     // 加载贴图文件     mtlLoader.load('static/clock.mtl', mtl => {       // 加载对象前,先设置贴图数据       objLoader.setMaterials(mtl)       // 加载对象文件       objLoader.load('static/clock.obj', res => {         resolve(res)       }, undefined, reject)     }, undefined, reject)  })}/** * 初始化 */function _init(el, obj) {  // 获取容器尺寸,  // 如果时window对象,请应用window.innerWidth, window.innerHeight  const width = el.offsetWidth  const height = el.offsetHeight    // 创立场景  scene = new Scene()  // 将加载实现的模型对象,增加到场景中  scene.add(obj)    // 创立环境光  const ambientLight = new AmbientLight(0x666666)  ambientLight.position.set(100, -100, -200)  scene.add(ambientLight)    // 创立平行光  const light = new DirectionalLight(0xcccccc, 1)  light.position.set(2000, 1000, 1000)  scene.add(light)    // 创立摄像机  const camera = new PerspectiveCamera(45, width / height, 1, 80000)  camera.position.set(-150, -50, 300)    // 创立renderer  renderer = new WebGLRenderer({    // 打消锯齿    antialias: true  })  // 设置渲染区域尺寸  renderer.setSize(width, height)  // 设置背景色彩  renderer.setClearColor(COLORS.black, 1)  // 将场景Canvas DOM元素,增加至父元素中  el.appendChild(renderer.domElement)    // 创立场景鼠标管制实例,  // 能够对页面上的模型对象进行旋转/缩放等操作  const orbitControls = new OrbitControls(camera, el)  orbitControls.addEventListener('change', render)    // 执行渲染,指定场景和相机作为参数  function render() {    renderer.render(scene, camera)  }  render()}/** * 导出初始化办法 */export function init(el) {  loadResource().then(res => {    _init(el, res)  }).catch(console.error)}/** * destroy */export function destroy() {  if (!scene || !renderer) return  scene.remove()  renderer.dispose()  scene = null  renderer = null}

src/components/ClockObj/index.jsx

import React, { useEffect } from 'react'import { destroy, init } from './core'function ClockObjDemo() {  useEffect(() => {    const el = document.querySelector('.clock-demo-el-hook')    init(el)    return () => {      destroy()    }  }, [])  return <main className="clock-demo-el-hook"/>}export default ClockObjDemo

备注

建模贴图未应用图片等内部文件,可能还有其余的坑,当前遇到了再补上。