1. 생성했던 박스 geometry에 GUI를 적용해 직접 설정을 조정할 수 있게 수정
step 1
BosGeometry 객체는 6개의 인자를 받는데, 해당 인자를 컨트롤하기 위한
args 인자를 추가한다.
class App{
//....
// 박스 세그먼트 인자
const args = {
width: 1,
height: 1,
depth: 1,
widthSegments: 1,
heightSegments: 1,
depthSegments:1
}
//....
}
step 2
createModel 객체를 새로 만들고, 기존의 geometry를 생성하는 메서드를
createModel 객체에 담고, createModel 객체를 호출한다.
GUI 적용 시 오래된 모델은 삭제되도록 한다.
*dispose() 는 사용하지 않는 gpu 리소스를 지우는 메서드로 꼭 적용해야 gpu리소스 관리가 가능하다.
class App{
// ....
// UI로 박스에 대한 args를 조정하기 위해 만든 객체
const createModel = () =>{
const geometry = new THREE.BoxGeometry(
args.width, args.height, args.depth,
args.widthSegments, args.heightSegments, args.depthSegments
)
const mesh = new THREE.Mesh(geometry, meshMaterial)
const line = new THREE.LineSegments(new THREE.WireframeGeometry(geometry), lineMaterial) //
const group = new THREE.Group()
group.name = "myModel"
group.add(mesh, line)
// GUI 적용시 오래된 모델은 삭제
const oldModel = this.scene.getObjectByName("myModel")
if (oldModel){
(oldModel.children[0] as THREE.Mesh).geometry.dispose(); // dispose 메서드는 사용하지 않는 gpu 리소스를 삭제.
(oldModel.children[1] as THREE.LineSegments).geometry.dispose()
this.scene.remove(oldModel)
}
this.scene.add(group)
}
createModel()
// ....
}
step 3
UI 를 추가한다.
import GUI from 'three/examples/jsm/libs/lil-gui.module.min.js'
class App{
//....
//UI 추가
const gui = new GUI()
gui.add(args, "width", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "height", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "depth", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "widthSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "heightSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "depthSegments", 1, 10, 1).onChange(createModel)
//....
}
전체 코드
import { OrbitControls } from 'three/examples/jsm/Addons.js' // 컨트롤을 위한 클래스
import './style.css'
import * as THREE from 'three'
import GUI from 'three/examples/jsm/libs/lil-gui.module.min.js'
// App 클래스 정의
class App{
private renderer: THREE.WebGLRenderer
private domApp: Element
private scene: THREE.Scene
private camera?: THREE.PerspectiveCamera
// private cube?: THREE.Mesh
constructor(){
console.log('Hello three.js')
this.renderer = new THREE.WebGLRenderer({ antialias: true})
this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio))
this.domApp = document.querySelector('#app')!
this.domApp.appendChild(this.renderer.domElement)
this.scene = new THREE.Scene()
this.setupCamera()
this.setupLight()
this.setupModels()
this.setupEvents()
this.setupControl()
}
private setupCamera(){
const width = this.domApp.clientWidth
const height = this.domApp.clientHeight
this.camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 100)
this.camera.position.z = 2
}
private setupLight(){
const color = 0xffffff
const intensity = 1
const light = new THREE.DirectionalLight(color, intensity)
const light_2 = new THREE.DirectionalLight(color, intensity)
light.position.set(-1, 2, 4)
light_2.position.set(2,-4,-4)
this.scene.add(light, light_2)
}
private setupModels(){
const meshMaterial = new THREE.MeshPhongMaterial({
color: 0x156289,
flatShading: true, side: THREE.DoubleSide,
transparent: true, opacity: .75
})
const lineMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
transparent: true, opacity: 0.8
})
// 박스 세그먼트 인자
const args = {
width: 1,
height: 1,
depth: 1,
widthSegments: 1,
heightSegments: 1,
depthSegments:1
}
// UI로 박스에 대한 args를 조정하기 위해 만든 객체
const createModel = () =>{
const geometry = new THREE.BoxGeometry(
args.width, args.height, args.depth,
args.widthSegments, args.heightSegments, args.depthSegments
)
const mesh = new THREE.Mesh(geometry, meshMaterial)
const line = new THREE.LineSegments(new THREE.WireframeGeometry(geometry), lineMaterial) //
const group = new THREE.Group()
group.name = "myModel"
group.add(mesh, line)
// GUI 적용시 오래된 모델은 삭제
const oldModel = this.scene.getObjectByName("myModel")
if (oldModel){
(oldModel.children[0] as THREE.Mesh).geometry.dispose(); // dispose 메서드는 사용하지 않는 gpu 리소스를 삭제.
(oldModel.children[1] as THREE.LineSegments).geometry.dispose()
this.scene.remove(oldModel)
}
this.scene.add(group)
}
createModel()
//UI 추가
const gui = new GUI()
gui.add(args, "width", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "height", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "depth", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "widthSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "heightSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "depthSegments", 1, 10, 1).onChange(createModel)
}
private setupControl(){
new OrbitControls(this.camera!, this.domApp! as HTMLElement)
}
private setupEvents(){
window.onresize = this.resize.bind(this)
this.resize()
this.renderer.setAnimationLoop(this.render.bind(this))
}
private resize(){
const width = this.domApp.clientWidth
const height = this.domApp.clientHeight
const camera = this.camera
if(camera){
camera.aspect = width / height
camera.updateProjectionMatrix()
}
this.renderer.setSize(width,height)
}
private update(time: number){
time *= 0.001
}
private render(time: number){
this.update(time)
this.renderer.render(this.scene, this.camera!)
}
}
new App()
2. 편의성을 위한 헬퍼 추가. *안내선, 그리드 표시
step 1
setupHelpers() 메서드 생성 후 constructor()에서 호출
step 2
setupHelpers() 메서드에 좌표축에 대한 헬퍼 객체와 그리그 객체를 생성한다.
//....
class App{
//....
constructor(){
//....
// 안개 기능 추가
this.scene.fog = new THREE.Fog(0x00000000, 1, 3.5)
this.setupHelpers() // 추가
}
// 안내선, 그리드 생성
private setupHelpers(){
// 좌표축에 대한 헬퍼객체
const axes = new THREE.AxesHelper(10) // 10은 좌표축의 크디
this.scene.add(axes)
// 그리드 객체
const grid = new THREE.GridHelper(5, 20, 0xffffff, 0x444444)
this.scene.add(grid)
}
//....
}
전체 코드
import { OrbitControls } from 'three/examples/jsm/Addons.js' // 컨트롤을 위한 클래스
import './style.css'
import * as THREE from 'three'
import GUI from 'three/examples/jsm/libs/lil-gui.module.min.js'
// App 클래스 정의
class App{
private renderer: THREE.WebGLRenderer
private domApp: Element
private scene: THREE.Scene
private camera?: THREE.PerspectiveCamera
// private cube?: THREE.Mesh
constructor(){
console.log('Hello three.js')
this.renderer = new THREE.WebGLRenderer({ antialias: true})
this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio))
this.domApp = document.querySelector('#app')!
this.domApp.appendChild(this.renderer.domElement)
this.scene = new THREE.Scene()
// 안개 기능 추가
this.scene.fog = new THREE.Fog(0x00000000, 1, 3.5)
this.setupCamera()
this.setupLight()
this.setupModels()
this.setupEvents()
this.setupControl()
this.setupHelpers() // 추가
}
// 안내선, 그리드 생성
private setupHelpers(){
// 좌표축에 대한 헬퍼객체
const axes = new THREE.AxesHelper(10) // 10은 좌표축의 크기
this.scene.add(axes)
// 그리드 객체
const grid = new THREE.GridHelper(5, 20, 0xffffff, 0x444444)
this.scene.add(grid)
}
private setupCamera(){
const width = this.domApp.clientWidth
const height = this.domApp.clientHeight
this.camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 100)
this.camera.position.z = 2
}
private setupLight(){
const color = 0xffffff
const intensity = 1
const light = new THREE.DirectionalLight(color, intensity)
const light_2 = new THREE.DirectionalLight(color, intensity)
light.position.set(-1, 2, 4)
light_2.position.set(2,-4,-4)
this.scene.add(light, light_2)
}
private setupModels(){
const meshMaterial = new THREE.MeshPhongMaterial({
color: 0x156289,
flatShading: true, side: THREE.DoubleSide,
transparent: true, opacity: .75
})
const lineMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
transparent: true, opacity: 0.8
})
// 박스 세그먼트 인자
const args = {
width: 1,
height: 1,
depth: 1,
widthSegments: 1,
heightSegments: 1,
depthSegments:1
}
// UI로 박스에 대한 args를 조정하기 위해 만든 객체
const createModel = () =>{
const geometry = new THREE.BoxGeometry(
args.width, args.height, args.depth,
args.widthSegments, args.heightSegments, args.depthSegments
)
const mesh = new THREE.Mesh(geometry, meshMaterial)
const line = new THREE.LineSegments(new THREE.WireframeGeometry(geometry), lineMaterial) //
const group = new THREE.Group()
group.name = "myModel"
group.add(mesh, line)
// GUI 적용시 오래된 모델은 삭제
const oldModel = this.scene.getObjectByName("myModel")
if (oldModel){
(oldModel.children[0] as THREE.Mesh).geometry.dispose(); // dispose 메서드는 사용하지 않는 gpu 리소스를 삭제.
(oldModel.children[1] as THREE.LineSegments).geometry.dispose()
this.scene.remove(oldModel)
}
this.scene.add(group)
}
createModel()
//UI 추가
const gui = new GUI()
gui.add(args, "width", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "height", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "depth", 0.1, 10, 0.01).onChange(createModel)
gui.add(args, "widthSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "heightSegments", 1, 10, 1).onChange(createModel)
gui.add(args, "depthSegments", 1, 10, 1).onChange(createModel)
}
private setupControl(){
new OrbitControls(this.camera!, this.domApp! as HTMLElement)
}
private setupEvents(){
window.onresize = this.resize.bind(this)
this.resize()
this.renderer.setAnimationLoop(this.render.bind(this))
}
private resize(){
const width = this.domApp.clientWidth
const height = this.domApp.clientHeight
const camera = this.camera
if(camera){
camera.aspect = width / height
camera.updateProjectionMatrix()
}
this.renderer.setSize(width,height)
}
private update(time: number){
time *= 0.001
}
private render(time: number){
this.update(time)
this.renderer.render(this.scene, this.camera!)
}
}
new App()
반응형
'Three.js > Study' 카테고리의 다른 글
geometry #03 (0) | 2024.08.05 |
---|---|
geometry #01 (0) | 2024.08.02 |
Three.js 개발환경 세팅 및 큐브 생성 (0) | 2024.08.02 |