From 140bd090d0979e45cc01330a7cf02c28f276e64a Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2026 09:51:49 +0200 Subject: [PATCH 1/5] Line2NodeMaterial: Implement `setupPosition()`. (#34005) Co-authored-by: sunag --- src/materials/nodes/Line2NodeMaterial.js | 25 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/materials/nodes/Line2NodeMaterial.js b/src/materials/nodes/Line2NodeMaterial.js index 5ade4458a4d23e..4e69af766267b6 100644 --- a/src/materials/nodes/Line2NodeMaterial.js +++ b/src/materials/nodes/Line2NodeMaterial.js @@ -1,10 +1,10 @@ import NodeMaterial from './NodeMaterial.js'; import { dashSize, diffuseColor, gapSize, varyingProperty } from '../../nodes/core/PropertyNode.js'; import { attribute } from '../../nodes/core/AttributeNode.js'; -import { cameraProjectionMatrix } from '../../nodes/accessors/Camera.js'; +import { cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraWorldMatrix } from '../../nodes/accessors/Camera.js'; import { materialLineScale, materialLineDashSize, materialLineGapSize, materialLineDashOffset, materialLineWidth } from '../../nodes/accessors/MaterialNode.js'; -import { modelViewMatrix } from '../../nodes/accessors/ModelNode.js'; -import { positionGeometry } from '../../nodes/accessors/Position.js'; +import { modelViewMatrix, modelWorldMatrixInverse } from '../../nodes/accessors/ModelNode.js'; +import { positionGeometry, positionLocal, positionPrevious } from '../../nodes/accessors/Position.js'; import { mix, smoothstep } from '../../nodes/math/MathNode.js'; import { Fn, float, vec2, vec3, vec4, If } from '../../nodes/tsl/TSLBase.js'; import { uv } from '../../nodes/accessors/UV.js'; @@ -518,15 +518,24 @@ class Line2NodeMaterial extends NodeMaterial { } /** - * Setups the position in clip space for the vertex stage of the fat line. - * Overrides the default model-view-projection to return the expanded fat line vertex coordinates. + * Setups the position of the expanded fat line vertex in local space. * * @param {NodeBuilder} builder - The current node builder. - * @return {Node} The position of the fat line vertex in clip space. + * @return {Node} The position of the fat line vertex in local space. */ - setupModelViewProjection( /*builder*/ ) { + setupPosition( builder ) { - return mvpLine; + const localPosition = modelWorldMatrixInverse.mul( cameraWorldMatrix ).mul( cameraProjectionMatrixInverse ).mul( mvpLine ); + + positionLocal.assign( localPosition.xyz.div( localPosition.w ) ); + + if ( builder.needsPreviousData() ) { + + positionPrevious.assign( positionLocal ); + + } + + return super.setupPosition( builder ); } From 22ce92d7e784e7f55cdad6318f8d596219e75428 Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Fri, 10 Jul 2026 11:20:41 +0200 Subject: [PATCH 2/5] Updated builds. --- build/three.module.js | 25 ++++++++-- build/three.webgpu.js | 93 +++++++++++++++++++++++++------------ build/three.webgpu.nodes.js | 93 +++++++++++++++++++++++++------------ 3 files changed, 147 insertions(+), 64 deletions(-) diff --git a/build/three.module.js b/build/three.module.js index 8fd0f0ab44106d..920b632861af05 100644 --- a/build/three.module.js +++ b/build/three.module.js @@ -3,7 +3,7 @@ * Copyright 2010-2026 Three.js Authors * SPDX-License-Identifier: MIT */ -import { Matrix3, Vector2, Color, Vector3, mergeUniforms, CubeUVReflectionMapping, Mesh, BoxGeometry, ShaderMaterial, BackSide, cloneUniforms, Matrix4, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, IntType, warn, HalfFloatType, UnsignedByteType, FloatType, RGBAFormat, Plane, CubeReflectionMapping, CubeRefractionMapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, NoToneMapping, MeshBasicMaterial, NoBlending, WebGLRenderTarget, BufferAttribute, LinearSRGBColorSpace, LinearFilter, CubeTexture, LinearMipmapLinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, warnOnce, Uint32BufferAttribute, Uint16BufferAttribute, error, DataArrayTexture, Vector4, DepthTexture, Float32BufferAttribute, RawShaderMaterial, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, Data3DTexture, GreaterEqualCompare, LessEqualCompare, Texture, GLSL3, VSMShadowMap, PCFShadowMap, AddOperation, MixOperation, MultiplyOperation, LinearTransfer, UniformsUtils, DoubleSide, NormalBlending, TangentSpaceNormalMap, ObjectSpaceNormalMap, Layers, RGFormat, RG11_EAC_Format, RED_GREEN_RGTC2_Format, MeshDepthMaterial, MeshDistanceMaterial, PCFSoftShadowMap, DepthFormat, NearestFilter, CubeDepthTexture, UnsignedIntType, Frustum, LessEqualDepth, ReverseSubtractEquation, SubtractEquation, AddEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcAlphaFactor, SrcColorFactor, OneFactor, ZeroFactor, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceNone, CullFaceBack, CullFaceFront, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, ReversedDepthFuncs, MinEquation, MaxEquation, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearMipmapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NotEqualCompare, GreaterCompare, EqualCompare, LessCompare, AlwaysCompare, NeverCompare, NoColorSpace, DepthStencilFormat, getByteLength, UnsignedInt248Type, UnsignedShortType, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, UnsignedInt101111Type, ByteType, ShortType, AlphaFormat, RGBFormat, RedFormat, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, ExternalTexture, EventDispatcher, ArrayCamera, WebXRController, RAD2DEG, DataTexture, createCanvasElement, SRGBColorSpace, REVISION, log, WebGLCoordinateSystem, probeAsync } from './three.core.js'; +import { Matrix3, Vector2, Color, Vector3, mergeUniforms, CubeUVReflectionMapping, Mesh, BoxGeometry, ShaderMaterial, BackSide, cloneUniforms, Matrix4, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, IntType, warn, HalfFloatType, UnsignedByteType, FloatType, RGBAFormat, Plane, CubeReflectionMapping, CubeRefractionMapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, NoToneMapping, MeshBasicMaterial, NoBlending, WebGLRenderTarget, BufferAttribute, LinearSRGBColorSpace, LinearFilter, CubeTexture, LinearMipmapLinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, warnOnce, Uint32BufferAttribute, Uint16BufferAttribute, error, DataArrayTexture, Vector4, DepthTexture, DepthStencilFormat, UnsignedInt248Type, Float32BufferAttribute, RawShaderMaterial, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, Data3DTexture, GreaterEqualCompare, LessEqualCompare, Texture, GLSL3, VSMShadowMap, PCFShadowMap, AddOperation, MixOperation, MultiplyOperation, LinearTransfer, UniformsUtils, DoubleSide, NormalBlending, TangentSpaceNormalMap, ObjectSpaceNormalMap, Layers, RGFormat, RG11_EAC_Format, RED_GREEN_RGTC2_Format, MeshDepthMaterial, MeshDistanceMaterial, PCFSoftShadowMap, DepthFormat, NearestFilter, CubeDepthTexture, UnsignedIntType, Frustum, LessEqualDepth, ReverseSubtractEquation, SubtractEquation, AddEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcAlphaFactor, SrcColorFactor, OneFactor, ZeroFactor, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceNone, CullFaceBack, CullFaceFront, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, ReversedDepthFuncs, MinEquation, MaxEquation, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearMipmapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NotEqualCompare, GreaterCompare, EqualCompare, LessCompare, AlwaysCompare, NeverCompare, NoColorSpace, getByteLength, UnsignedShortType, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, UnsignedInt101111Type, ByteType, ShortType, AlphaFormat, RGBFormat, RedFormat, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, ExternalTexture, EventDispatcher, ArrayCamera, WebXRController, RAD2DEG, DataTexture, createCanvasElement, SRGBColorSpace, REVISION, log, WebGLCoordinateSystem, probeAsync } from './three.core.js'; export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, Euler, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Fog, FogExp2, FramebufferTexture, FrustumArray, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NoNormalPacking, NormalAnimationBlendMode, NormalGAPacking, NormalRGPacking, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, Ray, Raycaster, RectAreaLight, RenderTarget, RenderTarget3D, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp, getConsoleFunction, setConsoleFunction } from './three.core.js'; function WebGLAnimation() { @@ -4693,13 +4693,30 @@ const toneMappingMap = { function WebGLOutput( type, width, height, antialias, depth, stencil ) { + // make sure depth texture matches renderer settings + + let depthTexture; + + if ( depth === true ) { + + depthTexture = new DepthTexture( width, height ); + + if ( stencil === true ) { + + depthTexture.format = DepthStencilFormat; + depthTexture.type = UnsignedInt248Type; + + } + + } + // render targets for scene and post-processing const targetA = new WebGLRenderTarget( width, height, { type: type, depthBuffer: depth, stencilBuffer: stencil, samples: antialias ? 4 : 0, - depthTexture: depth ? new DepthTexture( width, height ) : undefined + depthTexture: depthTexture } ); const targetB = new WebGLRenderTarget( width, height, { @@ -11967,8 +11984,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - texture.clearLayerUpdates(); - } else { state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data ); @@ -12009,6 +12024,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( texture.layerUpdates.size > 0 ) texture.clearLayerUpdates(); + } else { if ( useTexStorage && allocateMemory ) { diff --git a/build/three.webgpu.js b/build/three.webgpu.js index f5a47aef3d798f..3cba712f0216ed 100644 --- a/build/three.webgpu.js +++ b/build/three.webgpu.js @@ -46,6 +46,7 @@ const refreshUniforms = [ 'normalMap', 'normalScale', 'opacity', + 'retroreflective', 'roughness', 'roughnessMap', 'sheen', @@ -195,6 +196,7 @@ class NodeMaterialObserver { data = { geometryId: geometry.id, + materialVersion: this.getMaterialData( renderObject.material )._version, worldMatrix: object.matrixWorld.clone() }; @@ -335,7 +337,7 @@ class NodeMaterialObserver { if ( data === undefined ) { - data = { _renderId: -1, _equal: false }; + data = { _renderId: -1, _version: 0 }; for ( const property of this.refreshUniforms ) { @@ -399,19 +401,21 @@ class NodeMaterialObserver { const materialData = this.getMaterialData( renderObject.material ); - // check the material for the "equal" state just once per render for all render objects + // check the material properties just once per render for all render objects if ( materialData._renderId !== renderId ) { materialData._renderId = renderId; + let changed = false; + for ( const property in materialData ) { const value = materialData[ property ]; const mtlValue = material[ property ]; if ( property === '_renderId' ) continue; - if ( property === '_equal' ) continue; + if ( property === '_version' ) continue; if ( value.equals !== undefined ) { @@ -419,8 +423,7 @@ class NodeMaterialObserver { value.copy( mtlValue ); - materialData._equal = false; - return false; + changed = true; } @@ -431,8 +434,7 @@ class NodeMaterialObserver { value.id = mtlValue.id; value.version = mtlValue.version; - materialData._equal = false; - return false; + changed = true; } @@ -440,34 +442,38 @@ class NodeMaterialObserver { materialData[ property ] = mtlValue; - materialData._equal = false; - return false; + changed = true; } } - if ( materialData.transmission > 0 ) { + if ( changed === true ) materialData._version ++; - const { width, height } = renderObject.context; + } - if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) { + // a version mismatch means the material has changed since this render object was last refreshed - renderObjectData.bufferWidth = width; - renderObjectData.bufferHeight = height; + if ( renderObjectData.materialVersion !== materialData._version ) { - materialData._equal = false; - return false; + renderObjectData.materialVersion = materialData._version; - } + return false; - } + } - materialData._equal = true; + if ( materialData.transmission > 0 ) { - } else { + const { width, height } = renderObject.context; - if ( materialData._equal === false ) return false; + if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) { + + renderObjectData.bufferWidth = width; + renderObjectData.bufferHeight = height; + + return false; + + } } @@ -22883,15 +22889,24 @@ class Line2NodeMaterial extends NodeMaterial { } /** - * Setups the position in clip space for the vertex stage of the fat line. - * Overrides the default model-view-projection to return the expanded fat line vertex coordinates. + * Setups the position of the expanded fat line vertex in local space. * * @param {NodeBuilder} builder - The current node builder. - * @return {Node} The position of the fat line vertex in clip space. + * @return {Node} The position of the fat line vertex in local space. */ - setupModelViewProjection( /*builder*/ ) { + setupPosition( builder ) { + + const localPosition = modelWorldMatrixInverse.mul( cameraWorldMatrix ).mul( cameraProjectionMatrixInverse ).mul( mvpLine ); + + positionLocal.assign( localPosition.xyz.div( localPosition.w ) ); - return mvpLine; + if ( builder.needsPreviousData() ) { + + positionPrevious.assign( positionLocal ); + + } + + return super.setupPosition( builder ); } @@ -48276,8 +48291,8 @@ const mx_heighttonormal = ( input, scale/*, texcoord*/ ) => { const getParallaxCorrectNormal = /*@__PURE__*/ Fn( ( [ normal, cubeSize, cubePos ] ) => { const nDir = normalize( normal ).toVar(); - const rbmax = sub( float( 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar(); - const rbmin = sub( float( -0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar(); + const rbmax = cubeSize.mul( 0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar(); + const rbmin = cubeSize.mul( -0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar(); const rbminmax = vec3().toVar(); rbminmax.x = nDir.x.greaterThan( float( 0 ) ).select( rbmax.x, rbmin.x ); rbminmax.y = nDir.y.greaterThan( float( 0 ) ).select( rbmax.y, rbmin.y ); @@ -69830,12 +69845,29 @@ class WebGLTextureUtils { if ( texture.isCompressedArrayTexture ) { - if ( texture.format !== gl.RGBA ) { if ( glFormat !== null ) { - gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data ); + if ( texture.layerUpdates.size > 0 ) { + + const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type ); + + for ( const layerIndex of texture.layerUpdates ) { + + const layerData = mipmap.data.subarray( + layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT + ); + gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData ); + + } + + } else { + + gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data ); + + } } else { @@ -69865,6 +69897,7 @@ class WebGLTextureUtils { } + if ( texture.isCompressedArrayTexture && texture.layerUpdates.size > 0 ) texture.clearLayerUpdates(); } else if ( texture.isCubeTexture ) { diff --git a/build/three.webgpu.nodes.js b/build/three.webgpu.nodes.js index 6ee8b25b4f5fb5..57e1155e7d55b0 100644 --- a/build/three.webgpu.nodes.js +++ b/build/three.webgpu.nodes.js @@ -46,6 +46,7 @@ const refreshUniforms = [ 'normalMap', 'normalScale', 'opacity', + 'retroreflective', 'roughness', 'roughnessMap', 'sheen', @@ -195,6 +196,7 @@ class NodeMaterialObserver { data = { geometryId: geometry.id, + materialVersion: this.getMaterialData( renderObject.material )._version, worldMatrix: object.matrixWorld.clone() }; @@ -335,7 +337,7 @@ class NodeMaterialObserver { if ( data === undefined ) { - data = { _renderId: -1, _equal: false }; + data = { _renderId: -1, _version: 0 }; for ( const property of this.refreshUniforms ) { @@ -399,19 +401,21 @@ class NodeMaterialObserver { const materialData = this.getMaterialData( renderObject.material ); - // check the material for the "equal" state just once per render for all render objects + // check the material properties just once per render for all render objects if ( materialData._renderId !== renderId ) { materialData._renderId = renderId; + let changed = false; + for ( const property in materialData ) { const value = materialData[ property ]; const mtlValue = material[ property ]; if ( property === '_renderId' ) continue; - if ( property === '_equal' ) continue; + if ( property === '_version' ) continue; if ( value.equals !== undefined ) { @@ -419,8 +423,7 @@ class NodeMaterialObserver { value.copy( mtlValue ); - materialData._equal = false; - return false; + changed = true; } @@ -431,8 +434,7 @@ class NodeMaterialObserver { value.id = mtlValue.id; value.version = mtlValue.version; - materialData._equal = false; - return false; + changed = true; } @@ -440,34 +442,38 @@ class NodeMaterialObserver { materialData[ property ] = mtlValue; - materialData._equal = false; - return false; + changed = true; } } - if ( materialData.transmission > 0 ) { + if ( changed === true ) materialData._version ++; - const { width, height } = renderObject.context; + } - if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) { + // a version mismatch means the material has changed since this render object was last refreshed - renderObjectData.bufferWidth = width; - renderObjectData.bufferHeight = height; + if ( renderObjectData.materialVersion !== materialData._version ) { - materialData._equal = false; - return false; + renderObjectData.materialVersion = materialData._version; - } + return false; - } + } - materialData._equal = true; + if ( materialData.transmission > 0 ) { - } else { + const { width, height } = renderObject.context; - if ( materialData._equal === false ) return false; + if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) { + + renderObjectData.bufferWidth = width; + renderObjectData.bufferHeight = height; + + return false; + + } } @@ -22883,15 +22889,24 @@ class Line2NodeMaterial extends NodeMaterial { } /** - * Setups the position in clip space for the vertex stage of the fat line. - * Overrides the default model-view-projection to return the expanded fat line vertex coordinates. + * Setups the position of the expanded fat line vertex in local space. * * @param {NodeBuilder} builder - The current node builder. - * @return {Node} The position of the fat line vertex in clip space. + * @return {Node} The position of the fat line vertex in local space. */ - setupModelViewProjection( /*builder*/ ) { + setupPosition( builder ) { + + const localPosition = modelWorldMatrixInverse.mul( cameraWorldMatrix ).mul( cameraProjectionMatrixInverse ).mul( mvpLine ); + + positionLocal.assign( localPosition.xyz.div( localPosition.w ) ); - return mvpLine; + if ( builder.needsPreviousData() ) { + + positionPrevious.assign( positionLocal ); + + } + + return super.setupPosition( builder ); } @@ -48276,8 +48291,8 @@ const mx_heighttonormal = ( input, scale/*, texcoord*/ ) => { const getParallaxCorrectNormal = /*@__PURE__*/ Fn( ( [ normal, cubeSize, cubePos ] ) => { const nDir = normalize( normal ).toVar(); - const rbmax = sub( float( 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar(); - const rbmin = sub( float( -0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar(); + const rbmax = cubeSize.mul( 0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar(); + const rbmin = cubeSize.mul( -0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar(); const rbminmax = vec3().toVar(); rbminmax.x = nDir.x.greaterThan( float( 0 ) ).select( rbmax.x, rbmin.x ); rbminmax.y = nDir.y.greaterThan( float( 0 ) ).select( rbmax.y, rbmin.y ); @@ -69830,12 +69845,29 @@ class WebGLTextureUtils { if ( texture.isCompressedArrayTexture ) { - if ( texture.format !== gl.RGBA ) { if ( glFormat !== null ) { - gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data ); + if ( texture.layerUpdates.size > 0 ) { + + const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type ); + + for ( const layerIndex of texture.layerUpdates ) { + + const layerData = mipmap.data.subarray( + layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT + ); + gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData ); + + } + + } else { + + gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data ); + + } } else { @@ -69865,6 +69897,7 @@ class WebGLTextureUtils { } + if ( texture.isCompressedArrayTexture && texture.layerUpdates.size > 0 ) texture.clearLayerUpdates(); } else if ( texture.isCubeTexture ) { From e59aab58f224f14a3b1f0a921d1dfb88a22c9ed3 Mon Sep 17 00:00:00 2001 From: Ben Houston Date: Fri, 10 Jul 2026 05:46:56 -0400 Subject: [PATCH 3/5] Refresh external links in /examples (#34001) --- examples/misc_controls_arcball.html | 2 +- examples/models/obj/female02/readme.txt | 2 +- examples/webaudio_orientation.html | 2 +- examples/webaudio_sandbox.html | 6 +++--- examples/webaudio_visualizer.html | 2 +- examples/webgl_buffergeometry_selective_draw.html | 2 +- examples/webgl_depth_texture.html | 2 +- examples/webgl_geometry_minecraft.html | 2 +- examples/webgl_gpgpu_birds_gltf.html | 2 +- examples/webgl_lensflares.html | 2 +- examples/webgl_lights_hemisphere.html | 2 +- examples/webgl_lights_physical.html | 2 +- examples/webgl_lights_rectarealight.html | 2 +- examples/webgl_lines_colors.html | 2 +- examples/webgl_loader_3mf.html | 2 +- examples/webgl_loader_3mf_materials.html | 2 +- examples/webgl_loader_gltf_anisotropy.html | 2 +- examples/webgl_loader_gltf_avif.html | 2 +- examples/webgl_loader_gltf_instancing.html | 2 +- examples/webgl_loader_gltf_transmission.html | 2 +- examples/webgl_loader_ldraw.html | 4 ++-- examples/webgl_loader_ply.html | 2 +- examples/webgl_loader_stl.html | 2 +- examples/webgl_loader_texture_dds.html | 2 +- examples/webgl_loader_texture_exr.html | 2 +- examples/webgl_loader_texture_hdr.html | 2 +- examples/webgl_materials_channels.html | 2 +- examples/webgl_materials_displacementmap.html | 2 +- examples/webgl_materials_envmaps.html | 2 +- examples/webgl_materials_envmaps_hdr.html | 2 +- examples/webgl_materials_normalmap_object_space.html | 2 +- examples/webgl_materials_texture_filters.html | 2 +- examples/webgl_materials_texture_manualmipmap.html | 2 +- examples/webgl_materials_video.html | 2 +- examples/webgl_morphtargets_horse.html | 2 +- examples/webgl_panorama_equirectangular.html | 2 +- examples/webgl_performance.html | 2 +- examples/webgl_points_dynamic.html | 4 ++-- examples/webgl_points_sprites.html | 2 +- examples/webgl_postprocessing_3dlut.html | 2 +- examples/webgl_postprocessing_backgrounds.html | 2 +- examples/webgl_postprocessing_dof2.html | 2 +- examples/webgl_postprocessing_outline.html | 2 +- examples/webgl_postprocessing_procedural.html | 2 +- examples/webgl_postprocessing_sao.html | 2 +- examples/webgl_postprocessing_ssaa.html | 2 +- examples/webgl_postprocessing_taa.html | 2 +- examples/webgl_postprocessing_unreal_bloom.html | 4 ++-- examples/webgl_postprocessing_unreal_bloom_selective.html | 2 +- examples/webgl_renderer_pathtracer.html | 4 ++-- examples/webgl_shader_lava.html | 2 +- examples/webgl_shadowmap.html | 2 +- examples/webgl_shadowmap_pcss.html | 2 +- examples/webgl_shadowmap_performance.html | 2 +- examples/webgl_shadowmap_progressive.html | 2 +- examples/webgl_simple_gi.html | 2 +- examples/webgpu_animation_retargeting_readyplayer.html | 2 +- examples/webgpu_compute_rasterizer_ibl.html | 2 +- examples/webgpu_compute_reduce.html | 2 +- examples/webgpu_cubemap_adjustments.html | 2 +- examples/webgpu_cubemap_mix.html | 2 +- examples/webgpu_custom_fog_background.html | 2 +- examples/webgpu_equirectangular.html | 2 +- examples/webgpu_lensflares.html | 2 +- examples/webgpu_lights_physical.html | 2 +- examples/webgpu_lights_rectarealight.html | 2 +- examples/webgpu_loader_gltf_anisotropy.html | 2 +- examples/webgpu_loader_gltf_transmission.html | 2 +- examples/webgpu_materials_displacementmap.html | 2 +- examples/webgpu_materials_envmaps.html | 2 +- examples/webgpu_materials_texture_manualmipmap.html | 2 +- examples/webgpu_materials_video.html | 2 +- examples/webgpu_performance.html | 2 +- examples/webgpu_postprocessing_bloom.html | 4 ++-- examples/webgpu_postprocessing_outline.html | 2 +- examples/webgpu_postprocessing_ssaa.html | 2 +- examples/webgpu_postprocessing_ssr_denoise.html | 2 +- examples/webgpu_shadowmap_progressive.html | 2 +- 78 files changed, 85 insertions(+), 85 deletions(-) diff --git a/examples/misc_controls_arcball.html b/examples/misc_controls_arcball.html index a9547544dec343..a4b3fa3b16f868 100644 --- a/examples/misc_controls_arcball.html +++ b/examples/misc_controls_arcball.html @@ -15,7 +15,7 @@
three.js - arcball controls
- Cerberus(FFVII Gun) model by Andrew Maximov. + Cerberus(FFVII Gun) model by Andrew Maximov.
- - -
-
-

Aligner les éléments HTML en 3D

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le premier article -est les bases de three.js. Si vous ne l'avez pas -encore lu et que vous débutez avec three.js, vous pourriez vouloir commencer par là.

-

Parfois, vous aimeriez afficher du texte dans votre scène 3D. Vous avez plusieurs options, -chacune avec ses avantages et ses inconvénients.

-
    -
  • Utiliser du texte 3D

    -

    Si vous regardez l'article sur les primitives, vous verrez la TextGeometry qui -permet de créer du texte 3D. Cela peut être utile pour des logos volants, mais probablement moins pour des statistiques, des informations, -ou l'étiquetage de nombreux éléments.

    -
  • -
  • Utiliser une texture avec du texte 2D dessiné dessus.

    -

    L'article sur l'utilisation d'un Canvas comme texture montre comment utiliser -un canvas comme texture. Vous pouvez dessiner du texte dans un canvas et l'afficher comme un panneau (billboard). -L'avantage ici pourrait être que le texte est intégré à la scène 3D. Pour quelque chose comme un terminal d'ordinateur -montré dans une scène 3D, cela pourrait être parfait.

    -
  • -
  • Utiliser des éléments HTML et les positionner pour correspondre à la 3D

    -

    L'avantage de cette approche est que vous pouvez utiliser tout le HTML. Votre HTML peut contenir plusieurs éléments. Il peut -être stylisé avec du CSS. Il peut également être sélectionné par l'utilisateur car c'est du vrai texte.

    -
  • -
-

Cet article couvrira cette dernière approche.

-

Commençons simplement. Nous allons créer une scène 3D avec quelques primitives et ajouter une étiquette à chaque primitive. Nous commencerons -avec un exemple tiré de l'article sur les pages responsives

-

Nous allons ajouter des OrbitControls comme nous l'avons fait dans l'article sur l'éclairage.

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 0, 0);
-controls.update();
-
-

Nous devons fournir un élément HTML pour contenir nos éléments d'étiquette

-
<body>
--  <canvas id="c"></canvas>
-+  <div id="container">
-+    <canvas id="c"></canvas>
-+    <div id="labels"></div>
-+  </div>
-</body>
-
-

En plaçant à la fois le canvas et le <div id="labels"> à l'intérieur d'un -conteneur parent, nous pouvons les faire se superposer avec ce CSS

-
#c {
--    width: 100%;
--    height: 100%;
-+    width: 100%;  /* laisser notre conteneur décider de notre taille */
-+    height: 100%;
-    display: block;
-}
-+#container {
-+  position: relative;  /* fait de ceci l'origine de ses enfants */
-+  width: 100%;
-+  height: 100%;
-+  overflow: hidden;
-+}
-+#labels {
-+  position: absolute;  /* nous permet de nous positionner à l'intérieur du conteneur */
-+  left: 0;             /* place notre position en haut à gauche du conteneur */
-+  top: 0;
-+  color: white;
-+}
-
-

ajoutons également du CSS pour les étiquettes elles-mêmes

-
#labels>div {
-  position: absolute;  /* nous permet de les positionner à l'intérieur du conteneur */
-  left: 0;             /* place leur position par défaut en haut à gauche du conteneur */
-  top: 0;
-  cursor: pointer;     /* change le curseur en main quand la souris est dessus */
-  font-size: large;
-  user-select: none;   /* empêche la sélection du texte */
-  text-shadow:         /* crée un contour noir */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-#labels>div:hover {
-  color: red;
-}
-
-

Maintenant, dans notre code, nous n'avons pas grand-chose à ajouter. Nous avions une fonction -makeInstance que nous utilisions pour générer des cubes. Faisons en sorte -qu'elle ajoute également un élément d'étiquette.

-
+const labelContainerElem = document.querySelector('#labels');
-
--function makeInstance(geometry, color, x) {
-+function makeInstance(geometry, color, x, name) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const elem = document.createElement('div');
-+  elem.textContent = name;
-+  labelContainerElem.appendChild(elem);
-
--  return cube;
-+  return {cube, elem};
-}
-
-

Comme vous pouvez le voir, nous ajoutons un <div> au conteneur, un pour chaque cube. Nous -retournons également un objet avec à la fois le cube et l'elem pour l'étiquette.

-

Pour l'appeler, nous devons fournir un nom pour chacun

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
-+  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-];
-
-

Ce qui reste est le positionnement des éléments d'étiquette au moment du rendu

-
const tempV = new THREE.Vector3();
-
-...
-
--cubes.forEach((cube, ndx) => {
-+cubes.forEach((cubeInfo, ndx) => {
-+  const {cube, elem} = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-+  // obtient la position du centre du cube
-+  cube.updateWorldMatrix(true, false);
-+  cube.getWorldPosition(tempV);
-+
-+  // obtient la coordonnée d'écran normalisée de cette position
-+  // x et y seront dans la plage de -1 à +1, avec x = -1 étant
-+  // à gauche et y = -1 étant en bas
-+  tempV.project(camera);
-+
-+  // convertit la position normalisée en coordonnées CSS
-+  const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-+  const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-+
-+  // déplace l'élément à cette position
-+  elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-});
-
-

Et avec cela, nous avons des étiquettes alignées sur leurs objets correspondants.

-

- -

-

Il y a quelques problèmes que nous voudrons probablement résoudre.

-

L'un d'eux est que si nous faisons pivoter les objets de manière à ce qu'ils se chevauchent, toutes les étiquettes -se chevauchent également.

-
- -

Un autre est que si nous dézoomons beaucoup, de sorte que les objets sortent -du frustum, les étiquettes apparaîtront toujours.

-

Une solution possible au problème des objets qui se chevauchent est d'utiliser -le code de sélection (picking) de l'article sur la sélection. -Nous passerons la position de l'objet à l'écran, puis nous demanderons -au RayCaster de nous dire quels objets ont été intersectés. -Si notre objet n'est pas le premier, alors il n'est pas à l'avant.

-
const tempV = new THREE.Vector3();
-+const raycaster = new THREE.Raycaster();
-
-...
-
-cubes.forEach((cubeInfo, ndx) => {
-  const {cube, elem} = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-  // obtient la position du centre du cube
-  cube.updateWorldMatrix(true, false);
-  cube.getWorldPosition(tempV);
-
-  // obtient la coordonnée d'écran normalisée de cette position
-  // x et y seront dans la plage de -1 à +1, avec x = -1 étant
-  // à gauche et y = -1 étant en bas
-  tempV.project(camera);
-
-+  // demande au raycaster tous les objets qui intersectent
-+  // depuis l'œil vers la position de cet objet
-+  raycaster.setFromCamera(tempV, camera);
-+  const intersectedObjects = raycaster.intersectObjects(scene.children);
-+  // Nous sommes visibles si la première intersection est cet objet.
-+  const show = intersectedObjects.length && cube === intersectedObjects[0].object;
-+
-+  if (!show) {
-+    // cache l'étiquette
-+    elem.style.display = 'none';
-+  } else {
-+    // affiche l'étiquette
-+    elem.style.display = '';
-
-    // convertit la position normalisée en coordonnées CSS
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // déplace l'élément à cette position
-    elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-+  }
-});
-
-

Cela gère le chevauchement.

-

Pour gérer la sortie du frustum, nous pouvons ajouter cette vérification si l'origine de -l'objet est en dehors du frustum en vérifiant tempV.z

-
-  if (!show) {
-+  if (!show || Math.abs(tempV.z) > 1) {
-    // cache l'étiquette
-    elem.style.display = 'none';
-
-

Cela fonctionne plus ou moins car les coordonnées normalisées que nous avons calculées incluent une valeur z -qui va de -1 lorsqu'elle est à la partie near de notre frustum de caméra à +1 lorsqu'elle est -à la partie far de notre frustum de caméra.

-

- -

-

Pour la vérification du frustum, la solution ci-dessus échoue car nous ne vérifions que l'origine de l'objet. Pour un objet -volumineux, cette origine pourrait sortir du frustum, mais la moitié de l'objet pourrait encore s'y trouver.

-

Une solution plus correcte serait de vérifier si l'objet lui-même est dans le frustum -ou non. Malheureusement, cette vérification est lente. Pour 3 cubes, ce ne sera pas un problème, -mais pour de nombreux objets, cela pourrait l'être.

-

Three.js fournit quelques fonctions pour vérifier si la sphère englobante d'un objet est -dans un frustum

-
// au moment de l'initialisation
-const frustum = new THREE.Frustum();
-const viewProjection = new THREE.Matrix4();
-
-...
-
-// avant de vérifier
-camera.updateMatrix();
-camera.updateMatrixWorld();
-camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
-
-...
-
-// puis pour chaque maillage
-someMesh.updateMatrix();
-someMesh.updateMatrixWorld();
-
-viewProjection.multiplyMatrices(
-    camera.projectionMatrix, camera.matrixWorldInverse);
-frustum.setFromProjectionMatrix(viewProjection);
-const inFrustum = frustum.contains(someMesh));
-
-

Notre solution actuelle de chevauchement a des problèmes similaires. La sélection est lente. Nous pourrions -utiliser la sélection basée sur le GPU comme nous l'avons vu dans l'article sur -la sélection, mais ce n'est pas non plus gratuit. La solution que vous -choisirez dépend de vos besoins.

-

Un autre problème est l'ordre d'apparition des étiquettes. Si nous modifions le code pour avoir -des étiquettes plus longues

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
--  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
--  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-+  makeInstance(geometry, 0x44aa88,  0, 'Boîte Couleur Aqua'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Boîte Couleur Violet'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Boîte Couleur Or'),
-];
-
-

et définir le CSS de manière à ce qu'elles ne s'enroulent pas (wrap)

-
#labels>div {
-+  white-space: nowrap;
-
-

Alors nous pouvons rencontrer ce problème

-
- -

Vous pouvez voir ci-dessus que la boîte violette est à l'arrière, mais son étiquette est devant la boîte aqua.

-

Nous pouvons résoudre ce problème en définissant le zIndex de chaque élément. La position projetée a une valeur z -qui va de -1 à l'avant à +1 à l'arrière. Le zIndex doit être un entier et va dans la direction -opposée, ce qui signifie que pour le zIndex, les valeurs plus grandes sont à l'avant, donc le code suivant devrait fonctionner.

-
// convertit la position normalisée en coordonnées CSS
-const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-// déplace l'élément à cette position
-elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-+// définit le zIndex pour le tri
-+elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-
-

En raison de la façon dont fonctionne la valeur z projetée, nous devons choisir un grand nombre pour étaler les valeurs, -sinon beaucoup auront la même valeur. Pour s'assurer que les étiquettes ne se chevauchent pas avec d'autres parties de -la page, nous pouvons demander au navigateur de créer un nouveau contexte d'empilement -en définissant le z-index du conteneur des étiquettes

-
#labels {
-  position: absolute;  /* nous permet de nous positionner à l'intérieur du conteneur */
-+  z-index: 0;          /* crée un nouveau contexte d'empilement pour que les enfants ne soient pas triés avec le reste de la page */
-  left: 0;             /* place notre position en haut à gauche du conteneur */
-  top: 0;
-  color: white;
-  z-index: 0;
-}
-
-

et maintenant les étiquettes devraient toujours être dans le bon ordre.

-

- -

-

Tant que nous y sommes, faisons un autre exemple pour montrer un problème supplémentaire. -Dessinons un globe comme Google Maps et étiquetons les pays.

-

J'ai trouvé ces données -qui contiennent les frontières des pays. Elles sont sous licence -CC-BY-SA.

-

J'ai écrit du code -pour charger les données et générer les contours des pays ainsi que des données JSON avec les noms -des pays et leurs emplacements.

-
- -

Les données JSON sont un tableau d'entrées ressemblant à ceci

-
[
-  {
-    "name": "Algeria",
-    "min": [
-      -8.667223,
-      18.976387
-    ],
-    "max": [
-      11.986475,
-      37.091385
-    ],
-    "area": 238174,
-    "lat": 28.163,
-    "lon": 2.632,
-    "population": {
-      "2005": 32854159
-    }
-  },
-  ...
-
-

où min, max, lat, lon sont tous en degrés de latitude et de longitude.

-

Chargeons-les. Le code est basé sur les exemples de l'optimisation de nombreux -objets. Bien que nous ne dessinions pas beaucoup -d'objets, nous utiliserons les mêmes solutions pour le rendu à la demande.

-

La première chose est de créer une sphère et d'utiliser la texture des contours.

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

Ensuite, chargeons le fichier JSON en créant d'abord un chargeur

-
async function loadJSON(url) {
-  const req = await fetch(url);
-  return req.json();
-}
-
-

puis en l'appelant

-
let countryInfos;
-async function loadCountryData() {
-  countryInfos = await loadJSON('resources/data/world/country-info.json');
-     ...
-  }
-  requestRenderIfNotRequested();
-}
-loadCountryData();
-
-

Maintenant, utilisons ces données pour générer et placer les étiquettes.

-

Dans l'article sur l'optimisation de nombreux objets, -nous avions mis en place un petit graphe de scène d'objets auxiliaires pour faciliter le -calcul des positions de latitude et de longitude sur notre globe. Consultez cet article -pour une explication de leur fonctionnement.

-
const lonFudge = Math.PI * 1.5;
-const latFudge = Math.PI;
-// ces helpers (aides) faciliteront le positionnement des boîtes
-// Nous pouvons faire pivoter le lon helper sur son axe Y pour la longitude
-const lonHelper = new THREE.Object3D();
-// Nous faisons pivoter le latHelper sur son axe X pour la latitude
-const latHelper = new THREE.Object3D();
-lonHelper.add(latHelper);
-// Le position helper déplace l'objet vers le bord de la sphère
-const positionHelper = new THREE.Object3D();
-positionHelper.position.z = 1;
-latHelper.add(positionHelper);
-
-

Nous utiliserons cela pour calculer une position pour chaque étiquette

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const {lat, lon, name} = countryInfo;
-
-  // ajuste les aides pour pointer vers la latitude et la longitude
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // obtient la position de la lat/lon
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-  // ajoute un élément pour chaque pays
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-
-

Le code ci-dessus ressemble beaucoup au code que nous avons écrit pour créer les étiquettes de cube, -créant un élément par étiquette. Lorsque nous avons terminé, nous avons un tableau, countryInfos, -avec une entrée pour chaque pays, à laquelle nous avons ajouté une propriété elem pour -l'élément d'étiquette de ce pays et une position avec sa position sur le -globe.

-

Tout comme nous l'avons fait pour les cubes, nous devons mettre à jour la position des -étiquettes et le temps de rendu.

-
const tempV = new THREE.Vector3();
-
-function updateLabels() {
-  // quitte si nous n'avons pas encore chargé le fichier JSON
-  if (!countryInfos) {
-    return;
-  }
-
-  for (const countryInfo of countryInfos) {
-    const {position, elem} = countryInfo;
-
-    // obtient la coordonnée d'écran normalisée de cette position
-    // x et y seront dans la plage de -1 à +1, avec x = -1 étant
-    // à gauche et y = -1 étant en bas
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // convertit la position normalisée en coordonnées CSS
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // déplace l'élément à cette position
-    elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-    // définit le zIndex pour le tri
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

Vous pouvez voir que le code ci-dessus est sensiblement similaire à l'exemple des cubes précédent. -La seule différence majeure est que nous avons précalculé les positions des étiquettes au moment de l'initialisation. -Nous pouvons le faire car le globe ne bouge jamais. Seule notre caméra bouge.

-

Enfin, nous devons appeler updateLabels dans notre boucle de rendu

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  controls.update();
-
-+  updateLabels();
-
-  renderer.render(scene, camera);
-}
-
-

Et voici ce que nous obtenons

-

- -

-

Il y a beaucoup trop d'étiquettes !

-

Nous avons 2 problèmes.

-
    -
  1. Les étiquettes qui font face à l'opposé de nous apparaissent.

    -
  2. -
  3. Il y a trop d'étiquettes.

    -
  4. -
-

Pour le problème n°1, nous ne pouvons pas vraiment utiliser le RayCaster comme nous l'avons fait ci-dessus car il n'y a -rien à intersecter, à part la sphère. Au lieu de cela, ce que nous pouvons faire est de vérifier si ce -pays particulier est tourné vers l'opposé de nous ou non. Cela fonctionne car les positions des étiquettes -sont autour d'une sphère. En fait, nous utilisons une sphère unitaire, une sphère avec -un rayon de 1,0. Cela signifie que les positions sont déjà des vecteurs unitaires, ce qui -rend les calculs relativement faciles.

-
const tempV = new THREE.Vector3();
-+const cameraToPoint = new THREE.Vector3();
-+const cameraPosition = new THREE.Vector3();
-+const normalMatrix = new THREE.Matrix3();
-
-function updateLabels() {
-  // quitte si nous n'avons pas encore chargé le fichier JSON
-  if (!countryInfos) {
-    return;
-  }
-
-+  const minVisibleDot = 0.2;
-+  // obtient une matrice qui représente une orientation relative de la caméra
-+  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-+  // obtient la position de la caméra
-+  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-    const {position, elem} = countryInfo;
-
-+    // Oriente la position en fonction de l'orientation de la caméra.
-+    // Comme la sphère est à l'origine et que la sphère est une sphère unitaire
-+    // cela nous donne un vecteur direction relatif à la caméra pour la position.
-+    tempV.copy(position);
-+    tempV.applyMatrix3(normalMatrix);
-+
-+    // calcule la direction vers cette position depuis la caméra
-+    cameraToPoint.copy(position);
-+    cameraToPoint.applyMatrix4(camera.matrixWorldInverse).normalize();
-+
-+    // obtient le produit scalaire de la direction relative à la caméra vers cette position
-+    // sur le globe avec la direction de la caméra vers ce point.
-+    // 1 = fait face directement à la caméra
-+    // 0 = exactement tangente à la sphère vue de la caméra
-+    // < 0 = fait face à l'opposé
-+    const dot = tempV.dot(cameraToPoint);
-+
-+    // si l'orientation ne nous fait pas face, la cacher.
-+    if (dot < minVisibleDot) {
-+      elem.style.display = 'none';
-+      continue;
-+    }
-+
-+    // restaure le style d'affichage par défaut de l'élément
-+    elem.style.display = '';
-
-    // obtient la coordonnée d'écran normalisée de cette position
-    // x et y seront dans la plage de -1 à +1, avec x = -1 étant
-    // à gauche et y = -1 étant en bas
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // convertit la position normalisée en coordonnées CSS
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // déplace l'élément à cette position
-    countryInfo.elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-    // définit le zIndex pour le tri
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

Ci-dessus, nous utilisons les positions comme direction et obtenons cette direction par rapport à la -caméra. Ensuite, nous obtenons la direction relative à la caméra depuis la caméra vers cette position sur le globe et calculons le produit scalaire. Le produit scalaire renvoie le cosinus -de l'angle entre les deux vecteurs. Cela nous donne une valeur de -1 -à +1, où -1 signifie que l'étiquette fait face à la caméra, 0 signifie que l'étiquette est exactement -sur le bord de la sphère par rapport à la caméra, et toute valeur supérieure à zéro est -derrière. Nous utilisons ensuite cette valeur pour afficher ou masquer l'élément.

-
-
-
-
-
- -

Dans le diagramme ci-dessus, nous pouvons voir le produit scalaire de la direction vers laquelle l'étiquette est -orientée et de la direction de la caméra vers cette position. Si vous faites pivoter la -direction, vous verrez que le produit scalaire est de -1,0 lorsque la direction est directement -face à la caméra, il est de 0,0 lorsqu'il est exactement tangent à la sphère par rapport -à la caméra, ou pour le dire autrement, il est de 0 lorsque les 2 vecteurs sont -perpendiculaires l'un à l'autre, à 90 degrés. Il est supérieur à zéro lorsque l'étiquette est -derrière la sphère.

-

Pour le problème n°2, trop d'étiquettes, nous avons besoin d'un moyen de décider quelles étiquettes -afficher. Une façon serait de n'afficher les étiquettes que pour les grands pays. -Les données que nous chargeons contiennent les valeurs min et max pour la superficie qu'un -pays couvre. À partir de là, nous pouvons calculer une superficie, puis utiliser cette -superficie pour décider d'afficher ou non le pays.

-

Au moment de l'initialisation, calculons la superficie

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const {lat, lon, min, max, name} = countryInfo;
-
-  // ajuste les aides pour pointer vers la latitude et la longitude
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // obtient la position de la lat/lon
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-+  // calcule la superficie pour chaque pays
-+  const width = max[0] - min[0];
-+  const height = max[1] - min[1];
-+  const area = width * height;
-+  countryInfo.area = area;
-
-  // ajoute un élément pour chaque pays
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-}
-
-

Puis au moment du rendu, utilisons la superficie pour décider d'afficher l'étiquette -ou non

-
+const large = 20 * 20;
-const maxVisibleDot = 0.2;
-// obtient une matrice qui représente une orientation relative de la caméra
-normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-// obtient la position de la caméra
-camera.getWorldPosition(cameraPosition);
-for (const countryInfo of countryInfos) {
--  const {position, elem} = countryInfo;
-+  const {position, elem, area} = countryInfo;
-+  // assez grand ?
-+  if (area < large) {
-+    elem.style.display = 'none';
-+    continue;
-+  }
-
-  ...
-
-

Enfin, comme je ne suis pas sûr des bonnes valeurs pour ces paramètres, ajoutons -une GUI pour que nous puissions jouer avec elles

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-
+const settings = {
-+  minArea: 20,
-+  maxVisibleDot: -0.2,
-+};
-+const gui = new GUI({width: 300});
-+gui.add(settings, 'minArea', 0, 50).onChange(requestRenderIfNotRequested);
-+gui.add(settings, 'maxVisibleDot', -1, 1, 0.01).onChange(requestRenderIfNotRequested);
-
-function updateLabels() {
-  if (!countryInfos) {
-    return;
-  }
-
--  const large = 20 * 20;
--  const maxVisibleDot = -0.2;
-+  const large = settings.minArea * settings.minArea;
-  // obtient une matrice qui représente une orientation relative de la caméra
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // obtient la position de la caméra
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-
-    ...
-
-    // si l'orientation ne nous fait pas face, la cacher.
--    if (dot > maxVisibleDot) {
-+    if (dot > settings.maxVisibleDot) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-

et voici le résultat

-

- -

-

Vous pouvez voir qu'en faisant pivoter la Terre, les étiquettes qui passent derrière disparaissent. -Ajustez le minVisibleDot pour voir le changement de seuil. -Vous pouvez également ajuster la valeur de minArea pour voir apparaître des pays plus grands ou plus petits.

-

Plus j'ai travaillé là-dessus, plus j'ai réalisé l'énorme travail -investi dans Google Maps. Eux aussi doivent décider quelles étiquettes afficher. Je suis à peu près sûr qu'ils utilisent toutes sortes de critères. Par exemple, votre position actuelle, votre paramètre de langue par défaut, les paramètres de votre compte si vous en avez un, ils utilisent probablement la population ou la popularité, ils pourraient donner la priorité aux pays au centre de la vue, etc... Beaucoup de choses à considérer.

-

En tout cas, j'espère que ces exemples vous ont donné une idée de la façon d'aligner les éléments HTML -avec votre 3D. Quelques choses que je pourrais changer.

-

Prochaine étape, faisons en sorte que vous puissiez sélectionner et surligner un pays.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/animation-system.html b/manual/fr/animation-system.html deleted file mode 100644 index af31ce1b9eaee2..00000000000000 --- a/manual/fr/animation-system.html +++ /dev/null @@ -1,173 +0,0 @@ - - - Système d'Animation - - - - - - - - - - - - - -
-
-

Système d'Animation

-
-
-
- -

Vue d'ensemble

- -

- Au sein du système d'animation de three.js, vous pouvez animer diverses propriétés de vos modèles : - les os d'un modèle skinné et riggé, les morph targets, différentes propriétés de matériaux - (couleurs, opacité, booléens), la visibilité et les transformations. Les propriétés animées peuvent être introduites en fondu, - dissoutes en fondu, fondues enchaînées et déformées. L'influence (weight) et l'échelle temporelle (time scales) de différentes animations simultanées - sur le même objet ainsi que sur différents objets peuvent être modifiées - indépendamment. Diverses animations sur le même objet et sur différents objets peuvent être - synchronisées.

- - Pour atteindre tout cela dans un seul système homogène, le système d'animation de three.js - [link:https://github.com/mrdoob/three.js/issues/6881 a complètement changé en 2015] - (méfiez-vous des informations obsolètes !), et il a maintenant une architecture similaire à - Unity/Unreal Engine 4. Cette page donne un bref aperçu des principaux composants du - système et de leur fonctionnement ensemble. - -

- -

Clips d'Animation

- -

- - Si vous avez importé avec succès un objet 3D animé (peu importe qu'il ait des - os, des morph targets, ou les deux) — par exemple en l'exportant depuis Blender avec l' - [link:https://github.com/KhronosGroup/glTF-Blender-IO exportateur glTF pour Blender] et - en le chargeant dans une scène three.js à l'aide de `GLTFLoader` — l'un des champs de réponse - devrait être un tableau nommé "animations", contenant les clips d'animation - pour ce modèle (voir une liste des chargeurs possibles ci-dessous).

- - Chaque `AnimationClip` contient généralement les données pour une certaine activité de l'objet. Si le - mesh est un personnage, par exemple, il peut y avoir un AnimationClip pour un cycle de marche, un second - pour un saut, un troisième pour un pas de côté, et ainsi de suite. - -

- -

Pistes d'Images Clés

- -

- - À l'intérieur d'un tel `AnimationClip`, les données pour chaque propriété animée sont stockées dans une - `KeyframeTrack` séparée. En supposant qu'un objet personnage a un squelette, - une piste d'images clés pourrait stocker les données des changements de position de l'os de l'avant-bras - au fil du temps, une piste différente les données des changements de rotation du même os, une troisième - la position, la rotation ou l'échelle d'un autre os, et ainsi de suite. Il devrait être clair - qu'un AnimationClip peut être composé de nombreuses pistes de ce type.

- - En supposant que le modèle a des morph targets (par exemple un morph - target montrant un visage amical et un autre montrant un visage en colère), chaque piste contient les - informations sur la manière dont l'influence d'un certain morph target change pendant la performance - du clip. - -

- -

Mixeur d'Animation

- -

- - Les données stockées ne forment que la base des animations - la lecture réelle est contrôlée par le - `AnimationMixer`. Vous pouvez l'imaginer non seulement comme un lecteur d'animations, mais - comme une simulation d'un matériel comme une véritable console de mixage, qui peut contrôler plusieurs animations - simultanément, en les mélangeant et en les fusionnant. - -

- -

Actions d'Animation

- -

- - Le `AnimationMixer` lui-même n'a que très peu de propriétés et de méthodes (générales), car il - peut être contrôlé par les actions d'animation. En configurant une - `AnimationAction`, vous pouvez déterminer quand un certain `AnimationClip` doit être lu, mis en pause - ou arrêté sur l'un des mixeurs, si et combien de fois le clip doit être répété, s'il - doit être exécuté avec un fondu ou une échelle temporelle, et quelques éléments supplémentaires, tels que le fondu enchaîné - ou la synchronisation. - -

- -

Groupes d'Objets d'Animation

- -

- - Si vous souhaitez qu'un groupe d'objets reçoive un état d'animation partagé, vous pouvez utiliser un - `AnimationObjectGroup`. - -

- -

Formats et Chargeurs Pris en Charge

- -

- Notez que tous les formats de modèle n'incluent pas l'animation (OBJ notamment ne le fait pas), et que seuls certains - chargeurs three.js supportent les séquences `AnimationClip`. Plusieurs qui supportent - ce type d'animation : -

- -
    -
  • THREE.ObjectLoader
  • -
  • THREE.BVHLoader
  • -
  • THREE.ColladaLoader
  • -
  • THREE.FBXLoader
  • -
  • THREE.GLTFLoader
  • -
- -

- Notez que 3ds max et Maya ne peuvent actuellement pas exporter plusieurs animations (c'est-à-dire des animations qui ne sont pas - sur la même ligne de temps) directement dans un seul fichier. -

- -

Exemple

- -
-let mesh;
-
-// Créer un AnimationMixer, et obtenir la liste des instances de AnimationClip
-const mixer = new THREE.AnimationMixer( mesh );
-const clips = mesh.animations;
-
-// Mettre à jour le mixeur à chaque image
-function update () {
-  mixer.update( deltaSeconds );
-}
-
-// Jouer une animation spécifique
-const clip = THREE.AnimationClip.findByName( clips, 'dance' );
-const action = mixer.clipAction( clip );
-action.play();
-
-// Jouer toutes les animations
-clips.forEach( function ( clip ) {
-  mixer.clipAction( clip ).play();
-} );
-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/backgrounds.html b/manual/fr/backgrounds.html deleted file mode 100644 index e8616c326c9e3d..00000000000000 --- a/manual/fr/backgrounds.html +++ /dev/null @@ -1,254 +0,0 @@ - - - Arrière-plans et Skyboxes - - - - - - - - - - - - - -
-
-

Arrière-plans et Skyboxes

-
-
-
-

La plupart des articles ici utilisent une couleur unie pour l'arrière-plan.

-

Ajouter un arrière-plan statique peut être aussi simple que de définir du CSS. En prenant -un exemple de l'article sur comment rendre THREE.js responsive -nous n'avons besoin de changer que 2 choses.

-

Nous devons ajouter du CSS à notre canvas pour définir son arrière-plan comme une image.

-
<style>
-body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-+    background: url(resources/images/daikanyama.jpg) no-repeat center center;
-+    background-size: cover;
-}
-</style>
-
-

et nous devons dire au WebGLRenderer d'utiliser alpha pour que les endroits où nous ne dessinons rien soient transparents.

-
function main() {
-  const canvas = document.querySelector('#c');
--  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const renderer = new THREE.WebGLRenderer({
-+    antialias: true,
-+    canvas,
-+    alpha: true,
-+  });
-
-

Et nous obtenons un arrière-plan.

-

- -

-

Si nous voulons que l'arrière-plan puisse être affecté par des effets de post-traitement -alors nous devons dessiner l'arrière-plan en utilisant -THREE.js.

-

THREE.js rend cela quelque peu simple. Nous pouvons simplement définir l'arrière-plan de la scène sur -une texture.

-
const loader = new THREE.TextureLoader();
-const bgTexture = loader.load('resources/images/daikanyama.jpg');
-bgTexture.colorSpace = THREE.SRGBColorSpace;
-scene.background = bgTexture;
-
-

ce qui nous donne

-

- -

-

Cela nous donne une image de fond, mais elle est étirée pour s'adapter à l'écran.

-

Nous pouvons résoudre ce problème en définissant les propriétés repeat et offset de -la texture pour n'afficher qu'une partie de l'image.

-
function render(time) {
-
-   ...
-
-+  // Définir les propriétés repeat et offset de la texture de fond
-+  // pour maintenir l'aspect correct de l'image.
-+  // Note : l'image peut ne pas avoir encore été chargée.
-+  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
-+  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
-+  const aspect = imageAspect / canvasAspect;
-+
-+  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
-+  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
-+
-+  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
-+  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

et maintenant THREE.js dessine l'arrière-plan. Il n'y a pas de différence visible avec -la version CSS en haut, mais maintenant si nous utilisions un effet de post-traitement -l'arrière-plan serait également affecté.

-

- -

-

Bien sûr, un arrière-plan statique n'est généralement pas ce que l'on souhaite dans une scène 3D. Au lieu -de cela, nous voulons généralement une sorte de skybox. Une skybox est exactement cela, une boîte avec le ciel -dessiné dessus. Nous plaçons la caméra à l'intérieur de la boîte et on dirait qu'il y a un ciel en arrière-plan.

-

La manière la plus courante d'implémenter une skybox est de créer un cube, d'y appliquer une texture, -et de le dessiner depuis l'intérieur. Sur chaque côté du cube, placez une texture (en utilisant -les coordonnées de texture) qui ressemble à une image de l'horizon. Il est également fréquent -d'utiliser une sphère ou un dôme céleste avec une texture dessinée dessus. Vous pouvez -probablement le comprendre par vous-même. Il suffit de faire un cube ou une sphère, -appliquer une texture, le marquer comme THREE.BackSide pour que nous -rendions l'intérieur au lieu de l'extérieur, et soit de le mettre directement dans votre scène -comme ci-dessus, soit de créer 2 scènes : une spéciale pour dessiner la skybox/sphère/dôme et la -scène normale pour dessiner tout le reste. Vous utiliseriez votre PerspectiveCamera normale pour -dessiner. Pas besoin de la OrthographicCamera.

-

Une autre solution consiste à utiliser une Cubemap. Une Cubemap est un type de texture -spécial qui a 6 côtés, les côtés d'un cube. Au lieu d'utiliser des coordonnées de texture -standard, elle utilise une direction depuis le centre pointant vers l'extérieur pour décider -où obtenir une couleur.

-

Voici les 6 images d'une cubemap provenant du musée d'histoire de l'ordinateur à Mountain -View, Californie.

-
- - - -
-
- - - -
- -

Pour les utiliser, nous utilisons le CubeTextureLoader pour les charger, puis nous l'utilisons comme arrière-plan de la scène.

-
{
-  const loader = new THREE.CubeTextureLoader();
-  const texture = loader.load([
-    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
-  ]);
-  scene.background = texture;
-}
-
-

Au moment du rendu, nous n'avons pas besoin d'ajuster la texture comme nous l'avons fait ci-dessus

-
function render(time) {
-
-   ...
-
--  // Définir les propriétés repeat et offset de la texture de fond
--  // pour maintenir l'aspect correct de l'image.
--  // Note : l'image peut ne pas avoir encore été chargée.
--  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
--  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
--  const aspect = imageAspect / canvasAspect;
--
--  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
--  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
--
--  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
--  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

Ajoutons des contrôles pour pouvoir faire pivoter la caméra.

-
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 3;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

et essayez-le. Faites glisser l'exemple pour faire pivoter la caméra et voir la cubemap nous entourer.

-

- -

-

Une autre option consiste à utiliser une carte équirectangulaire. C'est le type d'image qu'une caméra 360 prend.

-

En voici une que j'ai trouvée sur ce site.

-
- -
{
--  const loader = new THREE.CubeTextureLoader();
--  const texture = loader.load([
--    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
--  ]);
--  scene.background = texture;
-+  const loader = new THREE.TextureLoader();
-+  const texture = loader.load(
-+    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
-+    () => {
-+      texture.mapping = THREE.EquirectangularReflectionMapping;
-+      texture.colorSpace = THREE.SRGBColorSpace;
-+      scene.background = texture;
-+    });
-}
-
-

Et c'est tout ce qu'il y a à faire.

-

- -

-

Plutôt que de le faire au moment du chargement, vous pouvez également convertir une image équirectangulaire -en cubemap au préalable. Voici un site qui le fera pour vous.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/billboards.html b/manual/fr/billboards.html deleted file mode 100644 index 783bcef0b0533b..00000000000000 --- a/manual/fr/billboards.html +++ /dev/null @@ -1,320 +0,0 @@ - - - Panneaux - - - - - - - - - - - - - -
-
-

Panneaux

-
-
-
-

Dans un article précédent nous avons utilisé une CanvasTexture -pour créer des étiquettes / badges sur les personnages. Parfois, nous aimerions créer des étiquettes ou -d'autres éléments qui font toujours face à la caméra. Three.js fournit le Sprite et le -SpriteMaterial pour y parvenir.

-

Modifions l'exemple de badge de l'article sur les textures de canevas -pour utiliser Sprite et le SpriteMaterial

-
function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // car notre canevas n'est probablement pas une puissance de 2
-  // dans les deux dimensions, définissez le filtrage de manière appropriée.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-
--  const labelMaterial = new THREE.MeshBasicMaterial({
-+  const labelMaterial = new THREE.SpriteMaterial({
-    map: texture,
--    side: THREE.DoubleSide,
-    transparent: true,
-  });
-
-  const root = new THREE.Object3D();
-  root.position.x = x;
-
-  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-  root.add(body);
-  body.position.y = bodyHeight / 2;
-
-  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-  root.add(head);
-  head.position.y = bodyHeight + headRadius * 1.1;
-
--  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  const label = new THREE.Sprite(labelMaterial);
-  root.add(label);
-  label.position.y = bodyHeight * 4 / 5;
-  label.position.z = bodyRadiusTop * 1.01;
-
-

et les étiquettes font maintenant toujours face à la caméra

-

- -

-

Un problème est que, sous certains angles, les étiquettes intersectent maintenant les -personnages.

-
- -

Nous pouvons déplacer la position des étiquettes pour corriger cela.

-
+// si les unités sont des mètres, alors 0.01 ici donne une taille
-+// de l'étiquette en centimètres.
-+const labelBaseScale = 0.01;
-const label = new THREE.Sprite(labelMaterial);
-root.add(label);
--label.position.y = bodyHeight * 4 / 5;
--label.position.z = bodyRadiusTop * 1.01;
-+label.position.y = head.position.y + headRadius + size * labelBaseScale;
-
--// si les unités sont des mètres, alors 0.01 ici donne une taille
--// de l'étiquette en centimètres.
--const labelBaseScale = 0.01;
-label.scale.x = canvas.width  * labelBaseScale;
-label.scale.y = canvas.height * labelBaseScale;
-
-

- -

-

Une autre chose que nous pouvons faire avec les panneaux d'affichage est de dessiner des façades.

-

Au lieu de dessiner des objets 3D, nous dessinons des plans 2D avec une image -d'objets 3D. C'est souvent plus rapide que de dessiner des objets 3D.

-

Par exemple, créons une scène avec une grille d'arbres. Nous allons créer chaque -arbre à partir d'un cylindre pour la base et d'un cône pour le sommet.

-

Nous créons d'abord la géométrie du cône et du cylindre ainsi que les matériaux que -tous les arbres partageront

-
const trunkRadius = .2;
-const trunkHeight = 1;
-const trunkRadialSegments = 12;
-const trunkGeometry = new THREE.CylinderGeometry(
-    trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments);
-
-const topRadius = trunkRadius * 4;
-const topHeight = trunkHeight * 2;
-const topSegments = 12;
-const topGeometry = new THREE.ConeGeometry(
-    topRadius, topHeight, topSegments);
-
-const trunkMaterial = new THREE.MeshPhongMaterial({color: 'brown'});
-const topMaterial = new THREE.MeshPhongMaterial({color: 'green'});
-
-

Ensuite, nous allons créer une fonction qui crée un Mesh -chacun pour le tronc et le sommet d'un arbre -et les parentent à un Object3D.

-
function makeTree(x, z) {
-  const root = new THREE.Object3D();
-  const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
-  trunk.position.y = trunkHeight / 2;
-  root.add(trunk);
-
-  const top = new THREE.Mesh(topGeometry, topMaterial);
-  top.position.y = trunkHeight + topHeight / 2;
-  root.add(top);
-
-  root.position.set(x, 0, z);
-  scene.add(root);
-
-  return root;
-}
-
-

Ensuite, nous allons créer une boucle pour placer une grille d'arbres.

-
for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
-    makeTree(x, z);
-  }
-}
-
-

Ajoutons également un plan de sol tant que nous y sommes

-
// ajouter le sol
-{
-  const size = 400;
-  const geometry = new THREE.PlaneGeometry(size, size);
-  const material = new THREE.MeshPhongMaterial({color: 'gray'});
-  const mesh = new THREE.Mesh(geometry, material);
-  mesh.rotation.x = Math.PI * -0.5;
-  scene.add(mesh);
-}
-
-

et changeons l'arrière-plan en bleu clair

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('white');
-+scene.background = new THREE.Color('lightblue');
-
-

et nous obtenons une grille d'arbres

-

- -

-

Il y a 11x11 ou 121 arbres. Chaque arbre est constitué d'un cône de 12 polygones -et d'un tronc de 48 polygones, donc chaque arbre fait 60 polygones. 121 * 60 -= 7260 polygones. Ce n'est pas énorme, mais bien sûr, un arbre 3D plus détaillé -pourrait avoir entre 1000 et 3000 polygones. S'ils avaient 3000 polygones chacun, -alors 121 arbres représenteraient 363000 polygones à dessiner.

-

En utilisant des façades, nous pouvons réduire ce nombre.

-

Nous pourrions créer manuellement une façade dans un logiciel de dessin, mais écrivons -du code pour essayer d'en générer une.

-

Écrivons du code pour rendre un objet dans une texture -en utilisant un RenderTarget. Nous avons abordé le rendu vers une RenderTarget -dans l'article sur les cibles de rendu.

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  camera.position.copy(boxCenter);
-  camera.position.z += distance;
-
-  // choisir des valeurs proches et éloignées pour le frustum qui
-  // contiendra la boîte.
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-}
-
-function makeSpriteTexture(textureSize, obj) {
-  const rt = new THREE.WebGLRenderTarget(textureSize, textureSize);
-
-  const aspect = 1;  // car la cible de rendu est carrée
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-  scene.add(obj);
-
-  // calculer la boîte qui contient obj
-  const box = new THREE.Box3().setFromObject(obj);
-
-  const boxSize = box.getSize(new THREE.Vector3());
-  const boxCenter = box.getCenter(new THREE.Vector3());
-
-  // régler la caméra pour cadrer la boîte
-  const fudge = 1.1;
-  const size = Math.max(...boxSize.toArray()) * fudge;
-  frameArea(size, size, boxCenter, camera);
-
-  renderer.autoClear = false;
-  renderer.setRenderTarget(rt);
-  renderer.render(scene, camera);
-  renderer.setRenderTarget(null);
-  renderer.autoClear = true;
-
-  scene.remove(obj);
-
-  return {
-    position: boxCenter.multiplyScalar(fudge),
-    scale: size,
-    texture: rt.texture,
-  };
-}
-
-

Quelques points à noter concernant le code ci-dessus :

-

Nous utilisons le champ de vision (fov) défini au-dessus de ce code.

-

Nous calculons une boîte qui contient l'arbre de la même manière -que nous l'avons fait dans l'article sur le chargement d'un fichier .obj -avec quelques modifications mineures.

-

Nous appelons frameArea à nouveau, adapté de l'article sur le chargement d'un fichier .obj. -Dans ce cas, nous calculons à quelle distance la caméra doit se trouver de l'objet, -compte tenu de son champ de vision, pour contenir l'objet. Nous positionnons ensuite la caméra en -z à cette distance -du centre de la boîte qui contient l'objet.

-

Nous multiplions la taille que nous voulons ajuster par 1,1 (fudge) pour nous assurer que l'arbre rentre -complètement dans la cible de rendu. Le problème ici est que la taille que nous utilisons pour -calculer si l'objet rentre dans la vue de la caméra ne prend pas en compte -que les bords mêmes de l'objet finiront par sortir de la zone que nous avons calculée. -Nous pourrions calculer comment faire rentrer 100% de la boîte, mais cela gaspillerait aussi de l'espace, -alors au lieu de cela, nous 'truquons' un peu.

-

Ensuite, nous rendons sur la cible de rendu et retirons l'objet de -la scène.

-

Il est important de noter que nous avons besoin des lumières dans la scène, mais nous -devons nous assurer que rien d'autre n'est dans la scène.

-

Nous devons également ne pas définir de couleur d'arrière-plan sur la scène

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('lightblue');
-
-

Enfin, nous avons créé la texture, nous la renvoyons ainsi que la position et l'échelle -dont nous avons besoin pour créer la façade afin qu'elle apparaisse au même endroit.

-

Nous créons ensuite un arbre et appelons ce code en le lui passant

-
// créer la texture du panneau d'affichage
-const tree = makeTree(0, 0);
-const facadeSize = 64;
-const treeSpriteInfo = makeSpriteTexture(facadeSize, tree);
-
-

Nous pouvons ensuite créer une grille de façades au lieu d'une grille de modèles d'arbres

-
+function makeSprite(spriteInfo, x, z) {
-+  const {texture, offset, scale} = spriteInfo;
-+  const mat = new THREE.SpriteMaterial({
-+    map: texture,
-+    transparent: true,
-+  });
-+  const sprite = new THREE.Sprite(mat);
-+  scene.add(sprite);
-+  sprite.position.set(
-+      offset.x + x,
-+      offset.y,
-+      offset.z + z);
-+  sprite.scale.set(scale, scale, scale);
-+}
-
-for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
--    makeTree(x, z);
-+    makeSprite(treeSpriteInfo, x, z);
-  }
-}
-
-

Dans le code ci-dessus, nous appliquons le décalage et l'échelle nécessaires pour positionner la façade afin qu'elle -apparaisse au même endroit où l'arbre d'origine aurait apparu.

-

Maintenant que nous avons terminé de créer la texture de la façade de l'arbre, nous pouvons à nouveau définir l'arrière-plan

-
scene.background = new THREE.Color('lightblue');
-
-

et maintenant nous obtenons une scène de façades d'arbres

-

- -

-

Comparez avec les modèles d'arbres ci-dessus et vous pouvez voir que l'apparence est assez similaire. -Nous avons utilisé une texture basse résolution, seulement 64x64 pixels, donc les façades sont pixelisées. -Vous pourriez augmenter la résolution. Souvent, les façades ne sont utilisées qu'à grande distance lorsqu'elles sont assez petites, -donc une texture basse résolution est suffisante et cela permet d'éviter de dessiner des arbres détaillés qui ne font -que quelques pixels de taille lorsqu'ils sont loin.

-

Un autre problème est que nous ne voyons l'arbre que d'un côté. -Cela est souvent résolu en rendant plus de façades, par exemple depuis 8 directions autour de l'objet, -puis en définissant quelle façade afficher en fonction de la direction depuis laquelle la caméra regarde la façade.

-

Que vous utilisiez des façades ou non, cela dépend de vous, mais j'espère que cet article -vous a donné des idées et suggéré des solutions si vous décidez de les utiliser.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/cameras.html b/manual/fr/cameras.html deleted file mode 100644 index 96862a03cf8dc6..00000000000000 --- a/manual/fr/cameras.html +++ /dev/null @@ -1,567 +0,0 @@ - - - Caméras - - - - - - - - - - - - - -
-
-

Caméras

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. -Le premier article traitait des bases. -Si vous ne l'avez pas encore lu, vous pourriez vouloir commencer par là.

-

Parlons des caméras dans three.js. Nous avons abordé une partie de cela dans le premier article, mais nous allons le couvrir plus en détail ici.

-

La caméra la plus courante dans three.js, et celle que nous avons utilisée jusqu'à présent, est -la PerspectiveCamera. Elle donne une vue 3D où les objets au loin apparaissent -plus petits que les objets proches.

-

La PerspectiveCamera définit un frustum. Un frustum est une forme pyramidale solide dont l'extrémité est coupée. -Par nom de solide, j'entends par exemple qu'un cube, un cône, une sphère, un cylindre -et un frustum sont tous des noms de différents types de solides.

-
-
cube
-
cône
-
sphère
-
cylindre
-
frustum
-
- -

Je ne le signale que parce que je ne le savais pas pendant des années. Un livre ou une page mentionnait -frustum et mes yeux se voilaient. Comprendre que c'est le nom d'un type de forme solide -a rendu ces descriptions soudainement plus logiques 😅

-

Une PerspectiveCamera définit son frustum en fonction de 4 propriétés. near définit où -commence l'avant du frustum. far définit où il se termine. fov, le champ de vision, définit -la hauteur de l'avant et de l'arrière du frustum en calculant la hauteur correcte pour obtenir -le champ de vision spécifié à near unités de la caméra. L'aspect définit -la largeur de l'avant et de l'arrière du frustum. La largeur du frustum est simplement la hauteur -multipliée par l'aspect.

-

-

Utilisons la scène de l'article précédent qui contient un plan au sol, -une sphère et un cube, et faisons en sorte de pouvoir ajuster les paramètres de la caméra.

-

Pour ce faire, nous allons créer un MinMaxGUIHelper pour les paramètres near et far afin que far -soit toujours supérieur à near. Il aura des propriétés min et max que lil-gui -ajustera. Lorsqu'elles seront ajustées, elles définiront les 2 propriétés que nous spécifions.

-
class MinMaxGUIHelper {
-  constructor(obj, minProp, maxProp, minDif) {
-    this.obj = obj;
-    this.minProp = minProp;
-    this.maxProp = maxProp;
-    this.minDif = minDif;
-  }
-  get min() {
-    return this.obj[this.minProp];
-  }
-  set min(v) {
-    this.obj[this.minProp] = v;
-    this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-  }
-  get max() {
-    return this.obj[this.maxProp];
-  }
-  set max(v) {
-    this.obj[this.maxProp] = v;
-    this.min = this.min;  // ceci appellera le setter de min
-  }
-}
-
-

Maintenant, nous pouvons configurer notre interface graphique comme ceci

-
function updateCamera() {
-  camera.updateProjectionMatrix();
-}
-
-const gui = new GUI();
-gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-

Chaque fois que les paramètres de la caméra changent, nous devons appeler la fonction -updateProjectionMatrix de la caméra. -Nous avons donc créé une fonction nommée updateCamera et l'avons passée à lil-gui pour qu'elle soit appelée lorsque les choses changent.

-

- -

-

Vous pouvez ajuster les valeurs et voir comment elles fonctionnent. Notez que nous n'avons pas rendu l'aspect modifiable car -il est tiré de la taille de la fenêtre. Donc, si vous voulez ajuster l'aspect, ouvrez l'exemple -dans une nouvelle fenêtre et redimensionnez-la.

-

Néanmoins, je pense que c'est un peu difficile à voir, alors changeons l'exemple pour qu'il comporte 2 caméras. -L'une montrera notre scène telle que nous la voyons ci-dessus, l'autre montrera une autre caméra regardant la -scène que la première caméra dessine et affichant le frustum de cette caméra.

-

Pour ce faire, nous pouvons utiliser la fonction scissor de three.js. -Changeons-le pour dessiner 2 scènes avec 2 caméras côte à côte en utilisant la fonction scissor.

-

Tout d'abord, utilisons du HTML et du CSS pour définir 2 éléments côte à côte. Cela nous -aidera également avec les événements afin que les deux caméras puissent facilement avoir leurs propres OrbitControls.

-
<body>
-  <canvas id="c"></canvas>
-+  <div class="split">
-+     <div id="view1" tabindex="1"></div>
-+     <div id="view2" tabindex="2"></div>
-+  </div>
-</body>
-
-

Et le CSS qui fera apparaître ces 2 vues côte à côte superposées sur -le canvas

-
.split {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-}
-.split>div {
-  width: 100%;
-  height: 100%;
-}
-
-

Puis dans notre code, nous ajouterons un CameraHelper. Un CameraHelper dessine le frustum d'une Camera

-
const cameraHelper = new THREE.CameraHelper(camera);
-
-...
-
-scene.add(cameraHelper);
-
-

Maintenant, cherchons les 2 éléments de vue.

-
const view1Elem = document.querySelector('#view1');
-const view2Elem = document.querySelector('#view2');
-
-

Et nous configurerons nos OrbitControls existants pour qu'ils ne répondent qu'au premier -élément de vue.

-
-const controls = new OrbitControls(camera, canvas);
-+const controls = new OrbitControls(camera, view1Elem);
-
-

Créons une deuxième PerspectiveCamera et un deuxième OrbitControls. -Le deuxième OrbitControls est lié à la deuxième caméra et reçoit l'entrée -du deuxième élément de vue.

-
const camera2 = new THREE.PerspectiveCamera(
-  60,  // fov
-  2,   // aspect
-  0.1, // near
-  500, // far
-);
-camera2.position.set(40, 10, 30);
-camera2.lookAt(0, 5, 0);
-
-const controls2 = new OrbitControls(camera2, view2Elem);
-controls2.target.set(0, 5, 0);
-controls2.update();
-
-

Enfin, nous devons rendre la scène du point de vue de chaque -caméra en utilisant la fonction scissor pour ne rendre qu'une partie du canvas.

-

Voici une fonction qui, étant donné un élément, calculera le rectangle -de cet élément qui chevauche le canvas. Elle définira ensuite le scissor -et le viewport sur ce rectangle et renverra l'aspect pour cette taille.

-
function setScissorForElement(elem) {
-  const canvasRect = canvas.getBoundingClientRect();
-  const elemRect = elem.getBoundingClientRect();
-
-  // calculer un rectangle relatif au canvas
-  const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
-  const left = Math.max(0, elemRect.left - canvasRect.left);
-  const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
-  const top = Math.max(0, elemRect.top - canvasRect.top);
-
-  const width = Math.min(canvasRect.width, right - left);
-  const height = Math.min(canvasRect.height, bottom - top);
-
-  // configurer le scissor pour ne rendre que cette partie du canvas
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  // retourner l'aspect
-  return width / height;
-}
-
-

Et maintenant, nous pouvons utiliser cette fonction pour dessiner la scène deux fois dans notre fonction render.

-
  function render() {
-
--    if (resizeRendererToDisplaySize(renderer)) {
--      const canvas = renderer.domElement;
--      camera.aspect = canvas.clientWidth / canvas.clientHeight;
--      camera.updateProjectionMatrix();
--    }
-
-+    resizeRendererToDisplaySize(renderer);
-+
-+    // activer le scissor
-+    renderer.setScissorTest(true);
-+
-+    // rendre la vue originale
-+    {
-+      const aspect = setScissorForElement(view1Elem);
-+
-+      // ajuster la caméra pour cet aspect
-+      camera.aspect = aspect;
-+      camera.updateProjectionMatrix();
-+      cameraHelper.update();
-+
-+      // ne pas dessiner l'helper de caméra dans la vue originale
-+      cameraHelper.visible = false;
-+
-+      scene.background.set(0x000000);
-+
-+      // rendre
-+      renderer.render(scene, camera);
-+    }
-+
-+    // rendre depuis la 2ème caméra
-+    {
-+      const aspect = setScissorForElement(view2Elem);
-+
-+      // ajuster la caméra pour cet aspect
-+      camera2.aspect = aspect;
-+      camera2.updateProjectionMatrix();
-+
-+      // dessiner l'helper de caméra dans la 2ème vue
-+      cameraHelper.visible = true;
-+
-+      scene.background.set(0x000040);
-+
-+      renderer.render(scene, camera2);
-+    }
-
--    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-

Le code ci-dessus définit la couleur de fond de la scène lors du rendu de la -deuxième vue sur bleu foncé juste pour faciliter la distinction entre les deux vues.

-

Nous pouvons également supprimer notre code updateCamera puisque nous mettons tout à jour -dans la fonction render.

-
-function updateCamera() {
--  camera.updateProjectionMatrix();
--}
-
-const gui = new GUI();
--gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-+gui.add(camera, 'fov', 1, 180);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
--gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
--gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
-+gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-
-

Et maintenant, vous pouvez utiliser une vue pour voir le frustum de l'autre.

-

- -

-

À gauche, vous pouvez voir la vue originale et à droite, vous pouvez -voir une vue montrant le frustum de la caméra de gauche. En ajustant -near, far, fov et en déplaçant la caméra avec la souris, vous pouvez voir que -seul ce qui se trouve à l'intérieur du frustum affiché à droite apparaît dans la scène de -gauche.

-

Ajustez near jusqu'à environ 20 et vous verrez facilement l'avant des objets -disparaître car ils ne sont plus dans le frustum. Ajustez far en dessous d'environ 35 -et vous commencerez à voir le plan au sol disparaître car il n'est plus dans -le frustum.

-

Cela soulève la question : pourquoi ne pas simplement régler near sur 0.0000000001 et far -sur 10000000000000 ou quelque chose de similaire afin de tout voir ? -La raison est que votre GPU n'a qu'une précision limitée pour décider si quelque chose -est devant ou derrière autre chose. Cette précision est répartie entre -near et far. Pire encore, par défaut, la précision près de la caméra est détaillée -et la précision loin de la caméra est grossière. Les unités commencent à near -et s'étendent lentement à mesure qu'elles s'approchent de far.

-

En partant de l'exemple du haut, changeons le code pour insérer 20 sphères d'affilée.

-
{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const numSpheres = 20;
-  for (let i = 0; i < numSpheres; ++i) {
-    const sphereMat = new THREE.MeshPhongMaterial();
-    sphereMat.color.setHSL(i * .73, 1, 0.5);
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, i * sphereRadius * -2.2);
-    scene.add(mesh);
-  }
-}
-
-

et réglons near sur 0.00001

-
const fov = 45;
-const aspect = 2;  // the canvas default
--const near = 0.1;
-+const near = 0.00001;
-const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

Nous devons également ajuster un peu le code de l'interface graphique pour permettre 0.00001 si la valeur est éditée.

-
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-
-

Que pensez-vous qu'il va se passer ?

-

- -

-

C'est un exemple de z-fighting (chevauchement en Z) où le GPU de votre ordinateur n'a pas -assez de précision pour décider quels pixels sont devant et quels pixels sont derrière.

-

Juste au cas où le problème n'apparaîtrait pas sur votre machine, voici ce que je vois sur la mienne

-
- -

Une solution consiste à indiquer à three.js d'utiliser une méthode différente pour calculer quels -pixels sont devant et quels pixels sont derrière. Nous pouvons le faire en activant -logarithmicDepthBuffer lorsque nous créons le WebGLRenderer

-
-const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  antialias: true,
-+  canvas,
-+  logarithmicDepthBuffer: true,
-+});
-
-

et avec cela, cela pourrait fonctionner

-

- -

-

Si cela n'a pas résolu le problème pour vous, alors vous avez rencontré l'une des raisons pour lesquelles -vous ne pouvez pas toujours utiliser cette solution. Cette raison est que seuls certains GPU -la supportent. En septembre 2018, presque aucun appareil mobile ne supportait cette -solution, alors que la plupart des ordinateurs de bureau le faisaient.

-

Une autre raison de ne pas choisir cette solution est qu'elle peut être significativement plus lente -que la solution standard.

-

Même avec cette solution, la résolution reste limitée. Rendez near encore -plus petit ou far encore plus grand et vous rencontrerez finalement les mêmes problèmes.

-

Ce que cela signifie, c'est que vous devriez toujours faire un effort pour choisir un paramètre near -et far qui convient à votre cas d'utilisation. Réglez near aussi loin de la caméra -que possible sans que les objets ne disparaissent. Réglez far aussi près de la caméra -que possible sans que les objets ne disparaissent. Si vous essayez de dessiner une scène géante -et de montrer un gros plan du visage de quelqu'un afin que vous puissiez voir ses cils -tout en voyant à l'arrière-plan des montagnes à 50 kilomètres -de distance, eh bien, vous devrez alors trouver d'autres solutions créatives que -nous aborderons peut-être plus tard. Pour l'instant, sachez simplement que vous devez faire attention -à choisir des valeurs near et far appropriées à vos besoins.

-

La deuxième caméra la plus courante est l'OrthographicCamera. Au lieu -de spécifier un frustum, elle spécifie une boîte avec les paramètres left, right -top, bottom, near et far. Comme elle projette une boîte, -il n'y a pas de perspective.

-

Changeons l'exemple à 2 vues ci-dessus pour utiliser une OrthographicCamera -dans la première vue.

-

Tout d'abord, configurons une OrthographicCamera.

-
const left = -1;
-const right = 1;
-const top = 1;
-const bottom = -1;
-const near = 5;
-const far = 50;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 0.2;
-
-

Nous réglons left et bottom à -1 et right et top à 1. Cela créerait -une boîte de 2 unités de large et 2 unités de haut, mais nous allons ajuster left et top -en fonction de l'aspect du rectangle dans lequel nous dessinons. Nous utiliserons la propriété -zoom pour faciliter l'ajustement du nombre d'unités réellement affichées par la caméra.

-

Ajoutons un paramètre GUI pour zoom.

-
const gui = new GUI();
-+gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
-
-

L'appel à listen indique à lil-gui de surveiller les changements. Ceci est ici car -les OrbitControls peuvent également contrôler le zoom. Par exemple, la molette de la souris effectuera -un zoom via les OrbitControls.

-

Enfin, il nous suffit de modifier la partie qui rend le côté -gauche pour mettre à jour l'OrthographicCamera.

-
{
-  const aspect = setScissorForElement(view1Elem);
-
-  // mettre à jour la caméra pour cet aspect
--  camera.aspect = aspect;
-+  camera.left   = -aspect;
-+  camera.right  =  aspect;
-  camera.updateProjectionMatrix();
-  cameraHelper.update();
-
-  // ne pas dessiner l'helper de caméra dans la vue originale
-  cameraHelper.visible = false;
-
-  scene.background.set(0x000000);
-  renderer.render(scene, camera);
-}
-
-

et maintenant vous pouvez voir une OrthographicCamera en action.

-

- -

-

Une autre utilisation courante pour une OrthographicCamera est de dessiner les -vues du dessus, du dessous, de gauche, de droite, de face, d'arrière d'un programme de modélisation -3D ou de l'éditeur d'un moteur de jeu.

-
- -

Dans la capture d'écran ci-dessus, vous pouvez voir qu'une vue est une vue en perspective et 3 vues sont -des vues orthographiques.

-

Une OrthographicCamera est le plus souvent utilisée si vous utilisez three.js -pour dessiner des éléments 2D. Vous décidez combien d'unités vous voulez que la caméra -affiche. Par exemple, si vous voulez qu'un pixel du canvas corresponde -à une unité dans la caméra, vous pourriez faire quelque chose comme

-

Pour placer l'origine au centre et avoir 1 pixel = 1 unité three.js, quelque chose comme

-
camera.left = -canvas.width / 2;
-camera.right = canvas.width / 2;
-camera.top = canvas.height / 2;
-camera.bottom = -canvas.height / 2;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

Ou si nous voulions que l'origine soit en haut à gauche, comme sur un -canvas 2D, nous pourrions utiliser ceci

-
camera.left = 0;
-camera.right = canvas.width;
-camera.top = 0;
-camera.bottom = canvas.height;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

Dans ce cas, le coin supérieur gauche serait 0,0, comme sur un canvas 2D.

-

Essayons ! Tout d'abord, configurons la caméra.

-
const left = 0;
-const right = 300;  // taille par défaut du canvas
-const top = 0;
-const bottom = 150;  // taille par défaut du canvas
-const near = -1;
-const far = 1;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 1;
-
-

Puis chargeons 6 textures et créons 6 plans, un pour chaque texture. -Nous associerons chaque plan à un THREE.Object3D pour faciliter le décalage -du plan afin que son centre apparaisse à son coin supérieur gauche.

-

Si vous l'exécutez localement, vous devrez également avoir effectué la configuration. -Vous pourriez également vouloir lire l'article sur l'utilisation des textures.

-
const loader = new THREE.TextureLoader();
-const textures = [
-  loader.load('resources/images/flower-1.jpg'),
-  loader.load('resources/images/flower-2.jpg'),
-  loader.load('resources/images/flower-3.jpg'),
-  loader.load('resources/images/flower-4.jpg'),
-  loader.load('resources/images/flower-5.jpg'),
-  loader.load('resources/images/flower-6.jpg'),
-];
-const planeSize = 256;
-const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planes = textures.map((texture) => {
-  const planePivot = new THREE.Object3D();
-  scene.add(planePivot);
-  texture.magFilter = THREE.NearestFilter;
-  const planeMat = new THREE.MeshBasicMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  planePivot.add(mesh);
-  // déplacer le plan pour que le coin supérieur gauche soit l'origine
-  mesh.position.set(planeSize / 2, planeSize / 2, 0);
-  return planePivot;
-});
-
-

et nous devons mettre à jour la caméra si la taille du canvas -change.

-
function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    camera.right = canvas.width;
-    camera.bottom = canvas.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

planes est un tableau de THREE.Mesh, un pour chaque plan. -Déplaçons-les en fonction du temps.

-
function render(time) {
-  time *= 0.001;  // convertir en secondes ;
-
-  ...
-
-  const distAcross = Math.max(20, canvas.width - planeSize);
-  const distDown = Math.max(20, canvas.height - planeSize);
-
-  // distance totale pour se déplacer en travers et en arrière
-  const xRange = distAcross * 2;
-  const yRange = distDown * 2;
-  const speed = 180;
-
-  planes.forEach((plane, ndx) => {
-    // calculer un temps unique pour chaque plan
-    const t = time * speed + ndx * 300;
-
-    // obtenir une valeur entre 0 et la plage
-    const xt = t % xRange;
-    const yt = t % yRange;
-
-    // définir notre position en avant si 0 à la moitié de la plage
-    // et en arrière si la moitié de la plage à la plage
-    const x = xt < distAcross ? xt : xRange - xt;
-    const y = yt < distDown   ? yt : yRange - yt;
-
-    plane.position.set(x, y, 0);
-  });
-
-  renderer.render(scene, camera);
-
-

Et vous pouvez voir les images rebondir parfaitement au pixel près sur les bords du -canvas en utilisant des calculs de pixels, tout comme un canvas 2D.

-

- -

-

Une autre utilisation courante pour une OrthographicCamera est de dessiner les -vues du dessus, du dessous, de gauche, de droite, de face, d'arrière d'un programme de modélisation -3D ou de l'éditeur d'un moteur de jeu.

-
- -

Dans la capture d'écran ci-dessus, vous pouvez voir qu'une vue est une vue en perspective et 3 vues sont -des vues orthographiques.

-

Voilà les bases des caméras. Nous aborderons quelques méthodes courantes pour déplacer les caméras -dans d'autres articles. Pour l'instant, passons aux ombres.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/canvas-textures.html b/manual/fr/canvas-textures.html deleted file mode 100644 index f39829bcc97b9a..00000000000000 --- a/manual/fr/canvas-textures.html +++ /dev/null @@ -1,403 +0,0 @@ - - - Textures sur Canvas - - - - - - - - - - - - - -
-
-

Textures sur Canvas

-
-
-
-

Cet article fait suite à l'article sur les textures. -Si vous ne l'avez pas encore lu, vous devriez probablement commencer par là.

-

Dans l'article précédent sur les textures, nous avons principalement utilisé -des fichiers image pour les textures. Cependant, il arrive parfois que nous souhaitions générer une texture -à l'exécution. Une façon de procéder est d'utiliser une CanvasTexture.

-

Une texture sur canvas prend un <canvas> en entrée. Si vous ne savez pas comment -dessiner avec l'API canvas 2D sur un canvas, il existe un bon tutoriel sur MDN.

-

Créons un simple programme canvas. En voici un qui dessine des points à des endroits aléatoires et dans des couleurs aléatoires.

-
const ctx = document.createElement('canvas').getContext('2d');
-document.body.appendChild(ctx.canvas);
-ctx.canvas.width = 256;
-ctx.canvas.height = 256;
-ctx.fillStyle = '#FFF';
-ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-
-function randInt(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min | 0;
-}
-
-function drawRandomDot() {
-  ctx.fillStyle = `#${randInt(0x1000000).toString(16).padStart(6, '0')}`;
-  ctx.beginPath();
-
-  const x = randInt(256);
-  const y = randInt(256);
-  const radius = randInt(10, 64);
-  ctx.arc(x, y, radius, 0, Math.PI * 2);
-  ctx.fill();
-}
-
-function render() {
-  drawRandomDot();
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

C'est assez simple.

-

- -

-

Utilisons-le maintenant pour texturer quelque chose. Nous allons commencer avec l'exemple de texturation -d'un cube tiré de l'article précédent. -Nous allons supprimer le code qui charge une image et utiliser à la place -notre canvas en créant une CanvasTexture et en lui passant le canvas que nous avons créé.

-
const cubes = [];  // juste un tableau que nous pouvons utiliser pour faire tourner les cubes
--const loader = new THREE.TextureLoader();
--
-+const ctx = document.createElement('canvas').getContext('2d');
-+ctx.canvas.width = 256;
-+ctx.canvas.height = 256;
-+ctx.fillStyle = '#FFF';
-+ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-+const texture = new THREE.CanvasTexture(ctx.canvas);
-
-const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg'),
-+  map: texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-cubes.push(cube);  // add to our list of cubes to rotate
-
-

Puis appelez le code pour dessiner un point aléatoire dans notre boucle de rendu.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  drawRandomDot();
-+  texture.needsUpdate = true;
-
-  cubes.forEach((cube, ndx) => {
-    const speed = .2 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

La seule chose supplémentaire que nous devons faire est de définir la propriété needsUpdate -de la CanvasTexture pour indiquer à three.js de mettre à jour la texture avec -le contenu le plus récent du canvas.

-

Et avec cela, nous avons un cube texturé sur canvas.

-

- -

-

Notez que si vous souhaitez utiliser three.js pour dessiner dans le canvas, vous êtes -il est préférable d'utiliser un RenderTarget, ce qui est abordé dans cet article.

-

Un cas d'utilisation courant pour les textures sur canvas est d'afficher du texte dans une scène. -Par exemple, si vous vouliez afficher le nom d'une personne sur le badge de son personnage, -vous pourriez utiliser une texture sur canvas pour texturer le badge.

-

Créons une scène avec 3 personnes et donnons à chaque personne un badge -ou une étiquette.

-

Reprenons l'exemple ci-dessus et supprimons tout ce qui est lié au cube. Ensuite, mettons le fond en blanc et ajoutons deux lumières.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-+
-+function addLight(position) {
-+  const color = 0xFFFFFF;
-+  const intensity = 1;
-+  const light = new THREE.DirectionalLight(color, intensity);
-+  light.position.set(...position);
-+  scene.add(light);
-+  scene.add(light.target);
-+}
-+addLight([-3, 1, 1]);
-+addLight([ 2, 1, .5]);
-
-

Écrivons du code pour créer une étiquette en utilisant le canvas 2D.

-
+function makeLabelCanvas(size, name) {
-+  const borderSize = 2;
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  const font =  `${size}px bold sans-serif`;
-+  ctx.font = font;
-+  // mesurer la longueur du nom
-+  const doubleBorderSize = borderSize * 2;
-+  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const height = size + doubleBorderSize;
-+  ctx.canvas.width = width;
-+  ctx.canvas.height = height;
-+
-+  // besoin de redéfinir la police après avoir redimensionné le canvas
-+  ctx.font = font;
-+  ctx.textBaseline = 'top';
-+
-+  ctx.fillStyle = 'blue';
-+  ctx.fillRect(0, 0, width, height);
-+  ctx.fillStyle = 'white';
-+  ctx.fillText(name, borderSize, borderSize);
-+
-+  return ctx.canvas;
-+}
-
-

Ensuite, nous allons créer des personnages simples à partir d'un cylindre pour le corps, d'une sphère -pour la tête et d'un plan pour l'étiquette.

-

Commençons par créer la géométrie partagée.

-
+const bodyRadiusTop = .4;
-+const bodyRadiusBottom = .2;
-+const bodyHeight = 2;
-+const bodyRadialSegments = 6;
-+const bodyGeometry = new THREE.CylinderGeometry(
-+    bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-+
-+const headRadius = bodyRadiusTop * 0.8;
-+const headLonSegments = 12;
-+const headLatSegments = 5;
-+const headGeometry = new THREE.SphereGeometry(
-+    headRadius, headLonSegments, headLatSegments);
-+
-+const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-

Ensuite, créons une fonction pour construire une personne à partir de ces -éléments.

-
+function makePerson(x, size, name, color) {
-+  const canvas = makeLabelCanvas(size, name);
-+  const texture = new THREE.CanvasTexture(canvas);
-+  // parce que notre canvas n'est probablement pas une puissance de 2
-+  // dans les deux dimensions, définissez le filtrage de manière appropriée.
-+  texture.minFilter = THREE.LinearFilter;
-+  texture.wrapS = THREE.ClampToEdgeWrapping;
-+  texture.wrapT = THREE.ClampToEdgeWrapping;
-+
-+  const labelMaterial = new THREE.MeshBasicMaterial({
-+    map: texture,
-+    side: THREE.DoubleSide,
-+    transparent: true,
-+  });
-+  const bodyMaterial = new THREE.MeshPhongMaterial({
-+    color,
-+    flatShading: true,
-+  });
-+
-+  const root = new THREE.Object3D();
-+  root.position.x = x;
-+
-+  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-+  root.add(body);
-+  body.position.y = bodyHeight / 2;
-+
-+  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-+  root.add(head);
-+  head.position.y = bodyHeight + headRadius * 1.1;
-+
-+  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  root.add(label);
-+  label.position.y = bodyHeight * 4 / 5;
-+  label.position.z = bodyRadiusTop * 1.01;
-+
-+  // si les unités sont des mètres, alors 0.01 ici ajuste la taille
-+  // de l'étiquette en centimètres.
-+  const labelBaseScale = 0.01;
-+  label.scale.x = canvas.width  * labelBaseScale;
-+  label.scale.y = canvas.height * labelBaseScale;
-+
-+  scene.add(root);
-+  return root;
-+}
-
-

Vous pouvez voir ci-dessus que nous plaçons le corps, la tête et l'étiquette sur un Object3D racine et ajustons leurs positions. Cela nous permettrait de déplacer l'objet racine si nous voulions déplacer les personnages. Le corps mesure 2 unités de haut. Si 1 unité équivaut à 1 mètre, alors le code ci-dessus tente de créer l'étiquette en centimètres, de sorte qu'elle mesurera 'size' centimètres de haut et la largeur nécessaire pour contenir le texte.

-

Nous pouvons ensuite créer des personnages avec des étiquettes.

-
+makePerson(-3, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 32, 'Green Machine', 'green');
-+makePerson(+3, 32, 'Red Menace', 'red');
-
-

Il ne reste plus qu'à ajouter des OrbitControls -afin de pouvoir déplacer la caméra.

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 50;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.set(0, 2, 5);
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 2, 0);
-+controls.update();
-
-

et nous obtenons des étiquettes simples.

-

- -

-

Quelques points à noter.

-
    -
  • Si vous zoomez, les étiquettes deviennent de faible résolution.
  • -
-

Il n'y a pas de solution simple. Il existe des techniques de rendu de police plus complexes, mais je ne connais pas de solutions sous forme de plugin. De plus, elles nécessiteraient que l'utilisateur télécharge les données de la police, ce qui serait lent.

-

Une solution consiste à augmenter la résolution des étiquettes. -Essayez de doubler la taille passée en paramètre et de diviser par deux la valeur actuelle de labelBaseScale.

-
    -
  • Les étiquettes s'allongent plus le nom est long.
  • -
-

Si vous vouliez résoudre ce problème, vous choisiriez plutôt une étiquette de taille fixe et compresseriez le texte.

-

C'est assez facile. Passez une largeur de base et adaptez le texte à cette largeur comme ceci :

-
-function makeLabelCanvas(size, name) {
-+function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
--  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${size}px bold sans-serif`;
-  ctx.font = font;
-  // mesurer la longueur du nom
-+  const textWidth = ctx.measureText(name).width;
-
-  const doubleBorderSize = borderSize * 2;
--  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const width = baseWidth + doubleBorderSize;
-  const height = size + doubleBorderSize;
-  ctx.canvas.width = width;
-  ctx.canvas.height = height;
-
-  // besoin de redéfinir la police après avoir redimensionné le canvas
-  ctx.font = font;
--  ctx.textBaseline = 'top';
-+  ctx.textBaseline = 'middle';
-+  ctx.textAlign = 'center';
-
-  ctx.fillStyle = 'blue';
-  ctx.fillRect(0, 0, width, height);
-
-+  // adapter à la taille mais ne pas étirer
-+  const scaleFactor = Math.min(1, baseWidth / textWidth);
-+  ctx.translate(width / 2, height / 2);
-+  ctx.scale(scaleFactor, 1);
-  ctx.fillStyle = 'white';
-  ctx.fillText(name, borderSize, borderSize);
-
-  return ctx.canvas;
-}
-
-

Nous pouvons ensuite passer une largeur pour les étiquettes.

-
-function makePerson(x, size, name, color) {
--  const canvas = makeLabelCanvas(size, name);
-+function makePerson(x, labelWidth, size, name, color) {
-+  const canvas = makeLabelCanvas(labelWidth, size, name);
-
-...
-
-}
-
--makePerson(-3, 32, 'Purple People Eater', 'purple');
--makePerson(-0, 32, 'Green Machine', 'green');
--makePerson(+3, 32, 'Red Menace', 'red');
-+makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 150, 32, 'Green Machine', 'green');
-+makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-

et nous obtenons des étiquettes dont le texte est centré et adapté à la taille.

-

- -

-

Ci-dessus, nous avons utilisé un nouveau canvas pour chaque texture. Utiliser ou non un canvas par texture dépend de vous. Si vous avez besoin de les mettre à jour souvent, avoir un canvas par texture est probablement la meilleure option. Si elles sont rarement ou jamais mises à jour, vous pouvez choisir d'utiliser un seul canvas pour plusieurs textures en forçant three.js à utiliser la texture. Modifions le code ci-dessus pour faire exactement cela.

-
+const ctx = document.createElement('canvas').getContext('2d');
-
-function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
--  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${size}px bold sans-serif`;
-
-  ...
-
-}
-
-+const forceTextureInitialization = function() {
-+  const material = new THREE.MeshBasicMaterial();
-+  const geometry = new THREE.PlaneGeometry();
-+  const scene = new THREE.Scene();
-+  scene.add(new THREE.Mesh(geometry, material));
-+  const camera = new THREE.Camera();
-+
-+  return function forceTextureInitialization(texture) {
-+    material.map = texture;
-+    renderer.render(scene, camera);
-+  };
-+}();
-
-function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // parce que notre canvas n'est probablement pas une puissance de 2
-  // dans les deux dimensions, définissez le filtrage de manière appropriée.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-+  forceTextureInitialization(texture);
-
-  ...
-
-

- -

-

Un autre problème est que les étiquettes ne font pas toujours face à la caméra. Si vous utilisez les étiquettes comme des badges, c'est probablement une bonne chose. Si vous utilisez les étiquettes pour afficher les noms des joueurs dans un jeu en 3D, vous pourriez vouloir que les étiquettes fassent toujours face à la caméra. Nous aborderons comment faire cela dans un article sur les billboards.

-

Pour les étiquettes en particulier, une autre solution consiste à utiliser le HTML. Les étiquettes dans cet article sont à l'intérieur du monde 3D, ce qui est bien si vous voulez qu'elles soient cachées par d'autres objets, tandis que les étiquettes HTML sont toujours au-dessus.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/cleanup.html b/manual/fr/cleanup.html deleted file mode 100644 index fb5f53a021082b..00000000000000 --- a/manual/fr/cleanup.html +++ /dev/null @@ -1,452 +0,0 @@ - - - Nettoyage - - - - - - - - - - - - - -
-
-

Nettoyage

-
-
-
-

Les applications Three.js utilisent souvent beaucoup de mémoire. Un modèle 3D -peut occuper de 1 à 20 Mo de mémoire pour l'ensemble de ses sommets. -Un modèle peut utiliser de nombreuses textures qui, même si elles sont -compressées en fichiers jpg, doivent être décompressées -pour être utilisées. Chaque texture 1024x1024 prend 4 à 6 Mo -de mémoire.

-

La plupart des applications three.js chargent les ressources au moment -de l'initialisation et les utilisent ensuite indéfiniment jusqu'à ce que la page soit -fermée. Mais que se passe-t-il si vous souhaitez charger et modifier des ressources -au fil du temps ?

-

Contrairement à la plupart des codes JavaScript, three.js ne peut pas nettoyer -automatiquement ces ressources. Le navigateur les nettoiera -si vous changez de page, mais sinon, c'est à vous -de les gérer. C'est un problème lié à la conception de WebGL, -et three.js n'a donc d'autre choix que de vous confier la -responsabilité de libérer les ressources.

-

Vous libérez les ressources three.js en appelant la fonction dispose sur -les textures, -les géométries, et les -matériaux.

-

Vous pourriez le faire manuellement. Au début, vous pourriez créer -certaines de ces ressources

-
const boxGeometry = new THREE.BoxGeometry(...);
-const boxTexture = textureLoader.load(...);
-const boxMaterial = new THREE.MeshPhongMaterial({map: texture});
-
-

puis, lorsque vous avez terminé avec elles, vous les libéreriez

-
boxGeometry.dispose();
-boxTexture.dispose();
-boxMaterial.dispose();
-
-

À mesure que vous utilisez de plus en plus de ressources, cela deviendrait de plus en -plus fastidieux.

-

Pour aider à réduire cette tâche fastidieuse, créons une classe pour suivre -les ressources. Nous demanderons ensuite à cette classe de faire le nettoyage -pour nous.

-

Voici une première ébauche d'une telle classe

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (resource.dispose) {
-      this.resources.add(resource);
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
-      resource.dispose();
-    }
-    this.resources.clear();
-  }
-}
-
-

Utilisons cette classe avec le premier exemple de l'article sur les textures. -Nous pouvons créer une instance de cette classe

-
const resTracker = new ResourceTracker();
-
-

et pour faciliter son utilisation, créons une fonction liée pour la méthode track

-
const resTracker = new ResourceTracker();
-+const track = resTracker.track.bind(resTracker);
-
-

Maintenant, pour l'utiliser, il suffit d'appeler track pour chaque géométrie, texture, et matériau -que nous créons

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
--const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-+const geometry = track(new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth));
-
-const cubes = [];  // an array we can use to rotate the cubes
-const loader = new THREE.TextureLoader();
-
--const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg'),
--});
-+const material = track(new THREE.MeshBasicMaterial({
-+  map: track(loader.load('resources/images/wall.jpg')),
-+}));
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-cubes.push(cube);  // add to our list of cubes to rotate
-
-

Et ensuite, pour les libérer, nous voudrions retirer les cubes de la scène -et appeler resTracker.dispose

-
for (const cube of cubes) {
-  scene.remove(cube);
-}
-cubes.length = 0;  // clears the cubes array
-resTracker.dispose();
-
-

Cela fonctionnerait, mais je trouve fastidieux de devoir retirer les cubes de la -scène. Ajoutons cette fonctionnalité au ResourceTracker.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
--    if (resource.dispose) {
-+    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
--      resource.dispose();
-+      if (resource instanceof THREE.Object3D) {
-+        if (resource.parent) {
-+          resource.parent.remove(resource);
-+        }
-+      }
-+      if (resource.dispose) {
-+        resource.dispose();
-+      }
-+    }
-    this.resources.clear();
-  }
-}
-
-

Et maintenant nous pouvons suivre les cubes

-
const material = track(new THREE.MeshBasicMaterial({
-  map: track(loader.load('resources/images/wall.jpg')),
-}));
-const cube = track(new THREE.Mesh(geometry, material));
-scene.add(cube);
-cubes.push(cube);  // add to our list of cubes to rotate
-
-

Nous n'avons plus besoin du code pour retirer les cubes de la scène.

-
-for (const cube of cubes) {
--  scene.remove(cube);
--}
-cubes.length = 0;  // clears the cube array
-resTracker.dispose();
-
-

Organisons ce code afin de pouvoir rajouter le cube, -la texture et le matériau.

-
const scene = new THREE.Scene();
-*const cubes = [];  // just an array we can use to rotate the cubes
-
-+function addStuffToScene() {
-  const resTracker = new ResourceTracker();
-  const track = resTracker.track.bind(resTracker);
-
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = track(new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth));
-
-  const loader = new THREE.TextureLoader();
-
-  const material = track(new THREE.MeshBasicMaterial({
-    map: track(loader.load('resources/images/wall.jpg')),
-  }));
-  const cube = track(new THREE.Mesh(geometry, material));
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-+  return resTracker;
-+}
-
-

Et ensuite, écrivons du code pour ajouter et supprimer des choses au fil du temps.

-
function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-}
-
-async function process() {
-  for (;;) {
-    const resTracker = addStuffToScene();
-    await wait(2);
-    cubes.length = 0;  // remove the cubes
-    resTracker.dispose();
-    await wait(1);
-  }
-}
-process();
-
-

Ce code va créer le cube, la texture et le matériau, attendre 2 secondes, puis les libérer et attendre 1 seconde -et répéter.

-

- -

-

Cela semble donc fonctionner.

-

Cependant, pour un fichier chargé, le travail est un peu plus conséquent. La plupart des chargeurs ne renvoient qu'un Object3D -comme racine de la hiérarchie des objets qu'ils chargent, nous devons donc découvrir toutes les ressources -qu'il contient.

-

Mettons à jour notre ResourceTracker pour essayer de faire cela.

-

Nous allons d'abord vérifier si l'objet est un Object3D, puis suivre sa géométrie, son matériau et ses enfants.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-+    if (resource instanceof THREE.Object3D) {
-+      this.track(resource.geometry);
-+      this.track(resource.material);
-+      this.track(resource.children);
-+    }
-    return resource;
-  }
-  ...
-}
-
-

Maintenant, comme resource.geometry, resource.material et resource.children -peuvent être nuls ou indéfinis, nous allons vérifier en haut de track.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-+    if (!resource) {
-+      return resource;
-+    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
-    }
-    return resource;
-  }
-  ...
-}
-
-

De plus, comme resource.children est un tableau et que resource.material peut être -un tableau, vérifions s'il s'agit de tableaux.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (!resource) {
-      return resource;
-    }
-
-*    // handle children and when material is an array of materials.
-*    // Gérer les enfants et lorsque le matériau est un tableau de matériaux.
-    if (Array.isArray(resource)) {
-      resource.forEach(resource => this.track(resource));
-      return resource;
-    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
-    }
-    return resource;
-  }
-  ...
-}
-
-

Et enfin, nous devons parcourir les propriétés et les uniformes -d'un matériau à la recherche de textures.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (!resource) {
-      return resource;
-    }
-
-*    // handle children and when material is an array of materials or
-*    // uniform is array of textures
-*    // Gérer les enfants et lorsque le matériau est un tableau de matériaux ou
-*    // qu'un uniforme est un tableau de textures
-    if (Array.isArray(resource)) {
-      resource.forEach(resource => this.track(resource));
-      return resource;
-    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
--    }
-+    } else if (resource instanceof THREE.Material) {
-+      // We have to check if there are any textures on the material
-+      // Nous devons vérifier s'il y a des textures sur le matériau
-+      for (const value of Object.values(resource)) {
-+        if (value instanceof THREE.Texture) {
-+          this.track(value);
-+        }
-+      }
-+      // We also have to check if any uniforms reference textures or arrays of textures
-+      // Nous devons aussi vérifier si des uniformes font référence à des textures ou à des tableaux de textures
-+      if (resource.uniforms) {
-+        for (const value of Object.values(resource.uniforms)) {
-+          if (value) {
-+            const uniformValue = value.value;
-+            if (uniformValue instanceof THREE.Texture ||
-+                Array.isArray(uniformValue)) {
-+              this.track(uniformValue);
-+            }
-+          }
-+        }
-+      }
-+    }
-    return resource;
-  }
-  ...
-}
-
-

Et avec cela, prenons un exemple de l'article sur le chargement de fichiers gltf -et faisons-le charger et libérer des fichiers.

-
const gltfLoader = new GLTFLoader();
-function loadGLTF(url) {
-  return new Promise((resolve, reject) => {
-    gltfLoader.load(url, resolve, undefined, reject);
-  });
-}
-
-function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-}
-
-const fileURLs = [
-  'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf',
-  'resources/models/3dbustchallange_submission/scene.gltf',
-  'resources/models/mountain_landscape/scene.gltf',
-  'resources/models/simple_house_scene/scene.gltf',
-];
-
-async function loadFiles() {
-  for (;;) {
-    for (const url of fileURLs) {
-      const resMgr = new ResourceTracker();
-      const track = resMgr.track.bind(resMgr);
-      const gltf = await loadGLTF(url);
-      const root = track(gltf.scene);
-      scene.add(root);
-
-      // compute the box that contains all the stuff
-      // from root and below
-      // calculer la boîte qui contient tout le contenu
-      // à partir de la racine et en dessous
-      const box = new THREE.Box3().setFromObject(root);
-
-      const boxSize = box.getSize(new THREE.Vector3()).length();
-      const boxCenter = box.getCenter(new THREE.Vector3());
-
-      // set the camera to frame the box
-      // définir la caméra pour cadrer la boîte
-      frameArea(boxSize * 1.1, boxSize, boxCenter, camera);
-
-      await waitSeconds(2);
-      renderer.render(scene, camera);
-
-      resMgr.dispose();
-
-      await waitSeconds(1);
-
-    }
-  }
-}
-loadFiles();
-
-

et nous obtenons

-

- -

-

Quelques notes sur le code.

-

Si nous voulions charger 2 fichiers ou plus à la fois et les libérer à -tout moment, nous utiliserions un ResourceTracker par fichier.

-

Ci-dessus, nous suivons uniquement gltf.scene juste après le chargement. -Sur la base de notre implémentation actuelle de ResourceTracker, -cela suivra toutes les ressources juste chargées. Si nous ajoutions plus -d'éléments à la scène, nous devrions décider de les suivre ou non.

-

Par exemple, disons qu'après avoir chargé un personnage, nous mettons un outil -dans sa main en faisant de l'outil un enfant de sa main. Tel quel, -cet outil ne sera pas libéré. Je suppose que la plupart du temps, -c'est ce que nous voulons.

-

Cela soulève un point. À l'origine, lorsque j'ai écrit pour la première fois le ResourceTracker -ci-dessus, je parcourais tout à l'intérieur de la méthode dispose au lieu de track. -Ce n'est que plus tard, en réfléchissant au cas de l'outil en tant qu'enfant de la main ci-dessus, -qu'il est devenu clair que suivre exactement ce qu'il faut libérer dans track était plus -flexible et sans doute plus correct, car nous pouvions alors suivre ce qui avait été chargé -depuis le fichier plutôt que de simplement libérer l'état du graphe de scène plus tard.

-

Honnêtement, je ne suis pas satisfait à 100% de ResourceTracker. Faire les choses de cette -manière n'est pas courant dans les moteurs 3D. Nous ne devrions pas avoir à deviner quelles -ressources ont été chargées, nous devrions le savoir. Il serait bien que three.js -change de sorte que tous les chargeurs de fichiers renvoient un objet standard avec -des références à toutes les ressources chargées. Du moins pour l'instant, -three.js ne nous donne pas plus d'informations lors du chargement d'une scène, donc cette -solution semble fonctionner.

-

J'espère que vous trouverez cet exemple utile ou du moins une bonne référence pour ce qui est -nécessaire pour libérer des ressources dans three.js

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/color-management.html b/manual/fr/color-management.html deleted file mode 100644 index 1c45647e936a02..00000000000000 --- a/manual/fr/color-management.html +++ /dev/null @@ -1,354 +0,0 @@ - - - Gestion des couleurs - - - - - - - - - - - - - - -
-
-

Gestion des couleurs

-
-
-
- -

Qu'est-ce qu'un espace couleur ?

- -

- Chaque espace couleur est une collection de plusieurs décisions de conception, choisies ensemble pour prendre en charge une - vaste gamme de couleurs tout en satisfaisant aux contraintes techniques liées à la précision et aux technologies - d'affichage. Lors de la création d'un actif 3D, ou de l'assemblage d'actifs 3D dans une scène, il est - important de connaître ces propriétés et la façon dont les propriétés d'un espace couleur sont liées - aux autres espaces couleur de la scène. -

- -
- -
- Couleurs sRGB et point blanc (D65) affichés dans le diagramme de chromaticité de référence CIE 1931. - La région colorée représente une projection 2D du gamut sRGB, qui est un volume 3D. - Source : Wikipedia -
-
- -
    -
  • - Primaires de couleur : Les couleurs primaires (par exemple rouge, vert, bleu) ne sont pas absolues ; elles sont - sélectionnées à partir du spectre visible en fonction des contraintes de précision limitée et des capacités des - périphériques d'affichage disponibles. Les couleurs sont exprimées comme un ratio des couleurs primaires. -
  • -
  • - Point blanc : La plupart des espaces couleur sont conçus de telle sorte qu'une somme pondérée égale des - primaires R = G = B apparaisse sans couleur, ou "achromatique". L'apparence - des valeurs achromatiques (comme le blanc ou le gris) dépend de la perception humaine, qui à son tour dépend - fortement du contexte de l'observateur. Un espace couleur spécifie son "point blanc" pour équilibrer - ces besoins. Le point blanc défini par l'espace couleur sRGB est - [link:https://en.wikipedia.org/wiki/Illuminant_D65 D65]. -
  • -
  • - Fonctions de transfert : Après avoir choisi le gamut et un modèle de couleur, nous devons encore - définir des correspondances ("fonctions de transfert") des valeurs numériques vers/depuis l'espace couleur. Est-ce que r = 0.5 - représente 50 % moins d'éclairage physique que r = 1.0 ? Ou 50 % moins lumineux, tel que perçu - par un œil humain moyen ? Ce sont des choses différentes, et cette différence peut être représentée par - une fonction mathématique. Les fonctions de transfert peuvent être linéaires ou non linéaires, en fonction - des objectifs de l'espace couleur. sRGB définit des fonctions de transfert non linéaires. Ces - fonctions sont parfois approximées par des fonctions gamma, mais le terme "gamma" est - ambigu et doit être évité dans ce contexte. -
  • -
- - Ces trois paramètres — primaires de couleur, point blanc et fonctions de transfert — définissent un espace - couleur, chacun choisi pour des objectifs particuliers. Ayant défini les paramètres, quelques termes supplémentaires - sont utiles : - -
    -
  • - Modèle de couleur : Syntaxe pour identifier numériquement les couleurs dans le gamut choisi — - un système de coordonnées pour les couleurs. Dans three.js, nous sommes principalement concernés par le modèle de couleur - RGB, ayant trois coordonnées r, g, b ∈ [0,1] ("domaine fermé") ou - r, g, b ∈ [0,∞] ("domaine ouvert") représentant chacune une fraction d'une couleur - primaire. D'autres modèles de couleur (HSL, Lab, LCH) sont couramment utilisés pour le contrôle artistique. -
  • -
  • - Gamut de couleur : Une fois que les primaires de couleur et un point blanc ont été choisis, ceux-ci représentent - un volume dans le spectre visible (un "gamut"). Les couleurs ne se trouvant pas dans ce volume ("hors gamut") - ne peuvent pas être exprimées par des valeurs RGB [0,1] en domaine fermé. Dans le domaine ouvert [0,∞], le gamut est - techniquement infini. -
  • -
- -

- Considérez deux espaces couleur très courants : `SRGBColorSpace` ("sRGB") et - `LinearSRGBColorSpace` ("Linear-sRGB"). Les deux utilisent les mêmes primaires et le même point blanc, - et ont donc le même gamut de couleur. Les deux utilisent le modèle de couleur RGB. Ils ne diffèrent que par - les fonctions de transfert — Linear-sRGB est linéaire par rapport à l'intensité lumineuse physique. - sRGB utilise les fonctions de transfert sRGB non linéaires, et ressemble plus étroitement à la façon dont - l'œil humain perçoit la lumière et à la réactivité des périphériques d'affichage courants. -

- -

- Cette différence est importante. Les calculs d'éclairage et autres opérations de rendu doivent - généralement avoir lieu dans un espace couleur linéaire. Cependant, les couleurs linéaires sont moins efficaces pour - être stockées dans une image ou un framebuffer, et ne paraissent pas correctes lorsqu'elles sont visualisées par un observateur humain. - En conséquence, les textures d'entrée et l'image finale rendue utiliseront généralement l'espace couleur sRGB non linéaire. -

- -
-

- ℹ️ AVIS : Bien que certains écrans modernes prennent en charge des gamuts plus larges comme Display-P3, - les API graphiques de la plateforme web reposent largement sur sRGB. Les applications utilisant three.js - aujourd'hui utiliseront généralement uniquement les espaces couleur sRGB et Linear-sRGB. -

-
- -

Rôles des espaces couleur

- -

- Les flux de travail linéaires — requis pour les méthodes de rendu modernes — impliquent généralement plus d'un - espace couleur, chacun assigné à un rôle particulier. Les espaces couleur linéaires et non linéaires sont - appropriés pour différents rôles, expliqués ci-dessous. -

- -

Espace couleur d'entrée

- -

- Les couleurs fournies à three.js — à partir de sélecteurs de couleur, de textures, de modèles 3D et d'autres sources — - ont chacune un espace couleur associé. Celles qui ne sont pas déjà dans l'espace couleur de travail Linear-sRGB - doivent être converties, et les textures doivent recevoir l'affectation correcte texture.colorSpace. - Certaines conversions (pour les couleurs hexadécimales et CSS en sRGB) peuvent être effectuées automatiquement si - l'API THREE.ColorManagement est activée avant l'initialisation des couleurs : -

- - -THREE.ColorManagement.enabled = true; - - -

- THREE.ColorManagement est activé par défaut. -

- -
    -
  • - Matériaux, lumières et shaders : Les couleurs dans les matériaux, les lumières et les shaders stockent - les composants RGB dans l'espace couleur de travail Linear-sRGB. -
  • -
  • - Couleurs de sommet : `BufferAttribute` stockent les composants RGB dans l'espace couleur de travail - Linear-sRGB. -
  • -
  • - Textures de couleur : Les `Texture` PNG ou JPEG contenant des informations de couleur - (comme .map ou .emissiveMap) utilisent l'espace couleur sRGB en domaine fermé, et doivent être annotées avec - texture.colorSpace = SRGBColorSpace. Des formats comme OpenEXR (parfois utilisés pour .envMap ou - .lightMap) utilisent l'espace couleur Linear-sRGB indiqué par texture.colorSpace = LinearSRGBColorSpace, - et peuvent contenir des valeurs dans le domaine ouvert [0,∞]. -
  • -
  • - Textures non couleur : Les textures qui ne stockent pas d'informations de couleur (comme .normalMap - ou .roughnessMap) n'ont pas d'espace couleur associé, et utilisent généralement l'annotation de texture (par défaut) de - texture.colorSpace = NoColorSpace. Dans de rares cas, les données non couleur - peuvent être représentées avec d'autres encodages non linéaires pour des raisons techniques. -
  • -
- -
-

- ⚠️ AVERTISSEMENT : De nombreux formats de modèles 3D ne définissent pas correctement ou de manière cohérente - les informations d'espace couleur. Bien que three.js tente de gérer la plupart des cas, les problèmes - sont fréquents avec les anciens formats de fichiers. Pour de meilleurs résultats, utilisez glTF 2.0 (`GLTFLoader`) - et testez les modèles 3D dans des visualiseurs en ligne tôt pour confirmer que l'actif lui-même est correct. -

-
- -

Espace couleur de travail

- -

- Le rendu, l'interpolation et de nombreuses autres opérations doivent être effectuées dans un espace couleur de travail - linéaire en domaine ouvert, dans lequel les composants RGB sont proportionnels à l'illumination physique. - Dans three.js, l'espace couleur de travail est Linear-sRGB. -

- -

Espace couleur de sortie

- -

- La sortie vers un périphérique d'affichage, une image ou une vidéo peut impliquer une conversion de l'espace couleur de travail - Linear-sRGB en domaine ouvert vers un autre espace couleur. La conversion est définie par - (`WebGLRenderer.outputColorSpace`). Lors de l'utilisation du post-traitement, cela nécessite OutputPass. -

- -
    -
  • - Affichage : Les couleurs écrites sur un canevas WebGL pour l'affichage doivent être dans l'espace - couleur sRGB. -
  • -
  • - Image : Les couleurs écrites dans une image doivent utiliser l'espace couleur approprié pour - le format et l'utilisation. Les images entièrement rendues écrites dans des textures PNG ou JPEG utilisent généralement - l'espace couleur sRGB. Les images contenant de l'émission, des lightmaps ou d'autres données non confinées à la plage [0,1] - utiliseront généralement l'espace couleur Linear-sRGB en domaine ouvert, et un format d'image compatible comme OpenEXR. -
  • -
- -
-

- ⚠️ AVERTISSEMENT : Les cibles de rendu peuvent utiliser soit sRGB soit Linear-sRGB. sRGB utilise - mieux la précision limitée. Dans le domaine fermé, 8 bits suffisent souvent pour sRGB tandis que ≥12 bits - (half float) peuvent être nécessaires pour Linear-sRGB. Si les étapes ultérieures du pipeline nécessitent - une entrée Linear-sRGB, les conversions supplémentaires peuvent entraîner un léger coût de performance. -

-
- -

- Les matériaux personnalisés basés sur `ShaderMaterial` et `RawShaderMaterial` doivent implémenter leur propre conversion d'espace couleur de sortie. - Pour les instances de `ShaderMaterial`, ajouter le chunk de shader `colorspace_fragment` à la fonction `main()` du shader de fragment devrait être suffisant. -

- -

Utilisation des instances THREE.Color

- -

- Les méthodes lisant ou modifiant des instances `Color` supposent que les données sont déjà dans - l'espace couleur de travail de three.js, Linear-sRGB. Les composants RGB et HSL sont des - représentations directes des données stockées par l'instance Color, et ne sont jamais convertis - implicitement. Les données de couleur peuvent être explicitement converties avec .convertLinearToSRGB() - ou .convertSRGBToLinear(). -

- -
-// RGB components (no change).
-color.r = color.g = color.b = 0.5;
-console.log( color.r ); // → 0.5
-
-// Manual conversion.
-color.r = 0.5;
-color.convertSRGBToLinear();
-console.log( color.r ); // → 0.214041140
-
- -

- Avec ColorManagement.enabled = true (recommandé), certaines conversions - sont effectuées automatiquement. Comme les couleurs hexadécimales et CSS sont généralement sRGB, les méthodes `Color` - convertiront automatiquement ces entrées de sRGB vers Linear-sRGB dans les setters, ou convertiront de - Linear-sRGB vers sRGB lors du retour d'une sortie hexadécimale ou CSS à partir des getters. -

- -
-// Hexadecimal conversion.
-color.setHex( 0x808080 );
-console.log( color.r ); // → 0.214041140
-console.log( color.getHex() ); // → 0x808080
-
-// CSS conversion.
-color.setStyle( 'rgb( 0.5, 0.5, 0.5 )' );
-console.log( color.r ); // → 0.214041140
-
-// Override conversion with 'colorSpace' argument.
-color.setHex( 0x808080, LinearSRGBColorSpace );
-console.log( color.r ); // → 0.5
-console.log( color.getHex( LinearSRGBColorSpace ) ); // → 0x808080
-console.log( color.getHex( SRGBColorSpace ) ); // → 0xBCBCBC
-
- -

Erreurs courantes

- -

- Lorsqu'une couleur ou une texture individuelle est mal configurée, elle apparaîtra plus foncée ou plus claire que - prévu. Lorsque l'espace couleur de sortie du renderer est mal configuré, toute la scène peut apparaître - plus foncée (par exemple, conversion manquante vers sRGB) ou plus claire (par exemple, une double conversion vers sRGB avec - post-traitement). Dans chaque cas, le problème peut ne pas être uniforme, et simplement augmenter/diminuer - l'éclairage ne le résout pas. -

- -

- Un problème plus subtil apparaît lorsque à la fois les espaces couleur d'entrée et les espaces couleur de sortie - sont incorrects — les niveaux de luminosité globaux peuvent être corrects, mais les couleurs peuvent changer - de manière inattendue sous différents éclairages, ou l'ombrage peut sembler plus brûlé et moins doux - que prévu. Ces deux erreurs ne font pas une seule bonne chose, et il est important que l'espace - couleur de travail soit linéaire ("référé à la scène") et l'espace couleur de sortie soit non linéaire - ("référé à l'affichage"). -

- -

Pour aller plus loin

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/creating-a-scene.html b/manual/fr/creating-a-scene.html deleted file mode 100644 index 53686a7267e264..00000000000000 --- a/manual/fr/creating-a-scene.html +++ /dev/null @@ -1,179 +0,0 @@ - - - Créer une scène - - - - - - - - - - - - - -
-
-

Créer une scène

-
-
-
- -

Le but de cette section est de donner une brève introduction à three.js. Nous commencerons par configurer une scène, avec un cube en rotation. Un exemple fonctionnel est fourni en bas de la page au cas où vous seriez bloqué et auriez besoin d'aide.

- -

Avant de commencer

- -

- Si vous ne l'avez pas encore fait, parcourez le guide `Installation`. Nous supposerons que vous avez déjà configuré la même structure de projet (incluant index.html et main.js), avez installé three.js, et utilisez soit un outil de build, soit un serveur local avec un CDN et des import maps. -

- -

Créer la scène

- -

Pour pouvoir afficher quoi que ce soit avec three.js, nous avons besoin de trois éléments : une scène, une caméra et un moteur de rendu (renderer), afin que nous puissions afficher la scène avec la caméra.

- -

main.js —

- -
-import * as THREE from 'three';
-
-const scene = new THREE.Scene();
-const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
-
-const renderer = new THREE.WebGLRenderer();
-renderer.setSize( window.innerWidth, window.innerHeight );
-document.body.appendChild( renderer.domElement );
-
- -

Prenons un instant pour expliquer ce qui se passe ici. Nous avons maintenant configuré la scène, notre caméra et le moteur de rendu.

- -

Il existe plusieurs caméras différentes dans three.js. Pour l'instant, utilisons une `PerspectiveCamera`.

- -

Le premier attribut est le `champ de vision`. Le FOV est l'étendue de la scène visible sur l'écran à un moment donné. La valeur est en degrés.

- -

Le deuxième est le `rapport d'aspect`. Vous voudrez presque toujours utiliser la largeur de l'élément divisée par la hauteur, sinon vous obtiendrez le même résultat que lorsque vous regardez de vieux films sur une télévision grand écran - l'image semble écrasée.

- -

Les deux attributs suivants sont les plans de découpe `near` (proche) et `far` (éloigné). Cela signifie que les objets plus éloignés de la caméra que la valeur de `far` ou plus proches que `near` ne seront pas rendus. Vous n'avez pas à vous en soucier maintenant, mais vous pourriez vouloir utiliser d'autres valeurs dans vos applications pour obtenir de meilleures performances.

- -

Vient ensuite le moteur de rendu (renderer). En plus de créer l'instance du moteur de rendu, nous devons également définir la taille à laquelle nous voulons qu'il affiche notre application. C'est une bonne idée d'utiliser la largeur et la hauteur de la zone que nous voulons remplir avec notre application - dans ce cas, la largeur et la hauteur de la fenêtre du navigateur. Pour les applications gourmandes en performances, vous pouvez également donner des valeurs plus petites à `setSize`, comme `window.innerWidth/2` et `window.innerHeight/2`, ce qui fera afficher l'application à un quart de la taille.

- -

Si vous souhaitez conserver la taille de votre application mais l'afficher à une résolution inférieure, vous pouvez le faire en appelant `setSize` avec `false` comme argument `updateStyle` (le troisième argument). Par exemple, `setSize(window.innerWidth/2, window.innerHeight/2, false)` affichera votre application à moitié résolution, étant donné que votre <canvas> a une largeur et une hauteur de 100%.

- -

Enfin, nous ajoutons l'élément `renderer` à notre document HTML. C'est un élément <canvas> que le moteur de rendu utilise pour nous afficher la scène.

- -

"Tout ça c'est bien beau, mais où est ce cube que vous avez promis ?" Ajoutons-le maintenant.

- -
-const geometry = new THREE.BoxGeometry( 1, 1, 1 );
-const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
-const cube = new THREE.Mesh( geometry, material );
-scene.add( cube );
-
-camera.position.z = 5;
-
- -

Pour créer un cube, nous avons besoin d'une `BoxGeometry`. C'est un objet qui contient tous les points (`vertices`) et le remplissage (`faces`) du cube. Nous explorerons cela plus en détail à l'avenir.

- -

En plus de la géométrie, nous avons besoin d'un matériau pour le colorer. Three.js est livré avec plusieurs matériaux, mais nous nous en tiendrons au `MeshBasicMaterial` pour l'instant. Tous les matériaux prennent un objet de propriétés qui leur seront appliquées. Pour simplifier les choses au maximum, nous fournissons seulement un attribut de couleur `0x00ff00`, qui est le vert. Cela fonctionne de la même manière que les couleurs dans CSS ou Photoshop (`couleurs hexadécimales`).

- -

La troisième chose dont nous avons besoin est un `Mesh`. Un mesh est un objet qui prend une géométrie et lui applique un matériau, que nous pouvons ensuite insérer dans notre scène et déplacer librement.

- -

Par défaut, lorsque nous appelons `scene.add()`, l'élément que nous ajoutons sera ajouté aux coordonnées `(0,0,0)`. Cela entraînerait la caméra et le cube à être l'un dans l'autre. Pour éviter cela, nous déplaçons simplement un peu la caméra.

- -

Afficher la scène

- -

Si vous copiez le code ci-dessus dans le fichier main.js que nous avons créé précédemment, vous ne pourrez rien voir. C'est parce que nous n'affichons encore rien. Pour cela, nous avons besoin de ce qu'on appelle une boucle de rendu ou d'animation.

- -
-function animate( time ) {
-  renderer.render( scene, camera );
-}
-renderer.setAnimationLoop( animate );
-
- -

Cela créera une boucle qui fait que le moteur de rendu dessine la scène à chaque rafraîchissement de l'écran (sur un écran typique, cela signifie 60 fois par seconde). Si vous débutez dans l'écriture de jeux dans le navigateur, vous pourriez dire "pourquoi ne pas simplement créer un setInterval ?" Le fait est que - nous pourrions, mais `requestAnimationFrame` qui est utilisé en interne dans `WebGLRenderer` présente un certain nombre d'avantages. Le plus important est peut-être qu'il se met en pause lorsque l'utilisateur navigue vers un autre onglet du navigateur, évitant ainsi de gaspiller sa précieuse puissance de traitement et l'autonomie de sa batterie.

- -

Animer le cube

- -

Si vous insérez tout le code ci-dessus dans le fichier que vous avez créé avant de commencer, vous devriez voir une boîte verte. Rendons le tout un peu plus intéressant en le faisant pivoter.

- -

Ajoutez le code suivant juste au-dessus de l'appel `renderer.render` dans votre fonction `animate` :

- -
-cube.rotation.x = time / 2000;
-cube.rotation.y = time / 1000;
-
- -

Cela sera exécuté à chaque image (normalement 60 fois par seconde) et donnera au cube une belle animation de rotation. En gros, tout ce que vous voulez déplacer ou modifier pendant que l'application est en cours d'exécution doit passer par la boucle d'animation. Vous pouvez bien sûr appeler d'autres fonctions à partir de là, afin de ne pas vous retrouver avec une fonction `animate` de plusieurs centaines de lignes.

- -

Le résultat

-

Félicitations ! Vous avez maintenant terminé votre première application three.js. C'est simple, mais il faut bien commencer quelque part.

- -

Le code complet est disponible ci-dessous et sous forme d'un [link:https://jsfiddle.net/zycqb61k/ exemple live] modifiable. Jouez avec pour mieux comprendre comment cela fonctionne.

- -

index.html —

- -
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>Ma première application three.js</title>
-    <style>
-      body { margin: 0; }
-    </style>
-  </head>
-  <body>
-    <script type="module" src="/main.js"></script>
-  </body>
-</html>
-
- -

main.js —

- -
-import * as THREE from 'three';
-
-const scene = new THREE.Scene();
-const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
-
-const renderer = new THREE.WebGLRenderer();
-renderer.setSize( window.innerWidth, window.innerHeight );
-renderer.setAnimationLoop( animate );
-document.body.appendChild( renderer.domElement );
-
-const geometry = new THREE.BoxGeometry( 1, 1, 1 );
-const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
-const cube = new THREE.Mesh( geometry, material );
-scene.add( cube );
-
-camera.position.z = 5;
-
-function animate( time ) {
-
-  cube.rotation.x = time / 2000;
-  cube.rotation.y = time / 1000;
-
-  renderer.render( scene, camera );
-
-}
-
- -
-
-
- - - - - - - - diff --git a/manual/fr/creating-text.html b/manual/fr/creating-text.html deleted file mode 100644 index ede41a986e21c2..00000000000000 --- a/manual/fr/creating-text.html +++ /dev/null @@ -1,170 +0,0 @@ - - - Création de texte - - - - - - - - - - - - - -
-
-

Création de texte

-
-
-
- -
-

- Il y a souvent des moments où vous pourriez avoir besoin d'utiliser du texte dans votre application three.js - voici - quelques façons de le faire. -

-
- -

1. DOM + CSS

-
-

- L'utilisation de HTML est généralement la manière la plus simple et la plus rapide d'ajouter du texte. C'est la méthode - utilisée pour les superpositions descriptives dans la plupart des exemples three.js. -

-

Vous pouvez ajouter du contenu à un

-
-<div id="info">Description</div>
-
-

- et utiliser du balisage CSS pour le positionner absolument à une position au-dessus de tous les autres avec un - z-index, surtout si vous exécutez three.js en plein écran. -

- -
-#info {
-  position: absolute;
-  top: 10px;
-  width: 100%;
-  text-align: center;
-  z-index: 100;
-  display:block;
-}
-
- -
- - -

2. Utiliser `CSS2DRenderer` ou `CSS3DRenderer`

-
-

- Utilisez ces moteurs de rendu pour dessiner du texte de haute qualité contenu dans des éléments DOM dans votre scène three.js. - C'est similaire à 1., sauf qu'avec ces moteurs de rendu, les éléments peuvent être intégrés de manière plus étroite et dynamique dans la scène. -

-
- - -

3. Dessiner du texte sur un canvas et l'utiliser comme `Texture`

-
-

Utilisez cette méthode si vous souhaitez dessiner facilement du texte sur un plan dans votre scène three.js.

-
- - -

4. Créer un modèle dans votre application 3D préférée et exporter vers three.js

-
-

Utilisez cette méthode si vous préférez travailler avec vos applications 3D et importer les modèles dans three.js.

-
- - -

5. Géométrie de Texte Procédurale

-
-

- Si vous préférez travailler purement en THREE.js ou créer des géométries de texte 3D procédurales et dynamiques, - vous pouvez créer un maillage dont la géométrie est une instance de THREE.TextGeometry : -

-

- new THREE.TextGeometry( text, parameters ); -

-

- Pour que cela fonctionne, cependant, votre TextGeometry aura besoin d'une instance de THREE.Font - à définir sur son paramètre « font ». - - Consultez la page `TextGeometry` pour plus d'informations sur la manière dont cela peut être fait, des descriptions de chaque - paramètre accepté, et une liste des polices JSON qui sont incluses dans la distribution THREE.js elle-même. -

- -

Exemples

- -

- [example:webgl_geometry_text WebGL / géométrie / texte]
- [example:webgl_shadowmap WebGL / shadowmap] -

- -

- Si Typeface est indisponible, ou si vous souhaitez utiliser une police qui ne s'y trouve pas, il existe un tutoriel - avec un script python pour blender qui vous permet d'exporter du texte au format JSON de Three.js : - [link:http://www.jaanga.com/2012/03/blender-to-threejs-create-3d-text-with.html] -

- -
- - -

6. Polices bitmap

-
-

- Les BMFonts (polices bitmap) permettent de regrouper les glyphes dans une seule BufferGeometry. Le rendu BMFont - prend en charge le retour à la ligne, l'espacement des lettres, le crénage, les champs de distance signés avec dérivées standard, - les champs de distance signés multicanaux, les polices multi-textures, et plus encore. - Voir [link:https://github.com/felixmariotto/three-mesh-ui three-mesh-ui] ou [link:https://github.com/Jam3/three-bmfont-text three-bmfont-text]. -

-

- Des polices standard sont disponibles dans des projets comme - [link:https://github.com/etiennepinchon/aframe-fonts A-Frame Fonts], ou vous pouvez créer les vôtres - à partir de n'importe quelle police .TTF, en optimisant pour n'inclure que les caractères requis pour un projet. -

-

- Quelques outils utiles : -

-
    -
  • [link:http://msdf-bmfont.donmccurdy.com/ msdf-bmfont-web] (basé sur le web)
  • -
  • [link:https://github.com/soimy/msdf-bmfont-xml msdf-bmfont-xml] (ligne de commande)
  • -
  • [link:https://github.com/libgdx/libgdx/wiki/Hiero hiero] (application de bureau)
  • -
-
- - -

7. Troika Text

-
-

- Le paquet [link:https://www.npmjs.com/package/troika-three-text troika-three-text] rend - du texte antialiasé de qualité en utilisant une technique similaire à celle des BMFonts, mais fonctionne directement - avec n'importe quel fichier de police .TTF ou .WOFF, vous n'avez donc pas à prégénérer une texture de glyphe hors ligne. Il ajoute - également des capacités, notamment : -

-
    -
  • Effets comme les contours, les ombres portées et la courbure
  • -
  • La possibilité d'appliquer n'importe quel Material three.js, même un ShaderMaterial personnalisé
  • -
  • Prise en charge des ligatures de police, des scripts avec lettres jointes et de la mise en page de droite à gauche/bidirectionnelle
  • -
  • Optimisation pour de grandes quantités de texte dynamique, effectuant la majeure partie du travail hors du thread principal dans un web worker
  • -
-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/custom-buffergeometry.html b/manual/fr/custom-buffergeometry.html deleted file mode 100644 index 30438ec64dd9e8..00000000000000 --- a/manual/fr/custom-buffergeometry.html +++ /dev/null @@ -1,447 +0,0 @@ - - - BufferGeometry Personnalisée - - - - - - - - - - - - - -
-
-

BufferGeometry Personnalisée

-
-
-
-

BufferGeometry est la manière dont three.js représente toute la géométrie. Une BufferGeometry -est essentiellement une collection nommée de BufferAttributes. -Chaque BufferAttribute représente un tableau d'un type de données : positions, -normales, couleurs, uv, etc... Ensemble, les BufferAttributes nommées représentent -des tableaux parallèles de toutes les données pour chaque sommet.

-
- -

Ci-dessus, vous pouvez voir que nous avons 4 attributs : position, normal, color, uv. -Ils représentent des tableaux parallèles, ce qui signifie que le N-ième ensemble de données de chaque -attribut appartient au même sommet. Le sommet à l'index = 4 est mis en évidence -pour montrer que les données parallèles à travers tous les attributs définissent un seul sommet.

-

Cela soulève un point, voici un diagramme d'un cube avec un coin mis en évidence.

-
- -

En y réfléchissant, ce coin unique nécessite une normale différente pour chaque face du -cube. Une normale est une information sur la direction vers laquelle quelque chose fait face. Dans le diagramme, -les normales sont représentées par les flèches autour du sommet d'angle, montrant que chaque -face qui partage cette position de sommet a besoin d'une normale qui pointe dans une direction différente.

-

Ce coin a également besoin d'UV différents pour chaque face. Les UV sont des coordonnées de texture -qui spécifient quelle partie d'une texture dessinée sur un triangle correspond à cette -position de sommet. Vous pouvez voir que la face verte a besoin que ce sommet ait une UV qui corresponde -au coin supérieur droit de la texture F, la face bleue a besoin d'une UV qui corresponde au -coin supérieur gauche de la texture F, et la face rouge a besoin d'une UV qui corresponde au coin -inférieur gauche de la texture F.

-

Un seul sommet est la combinaison de toutes ses parties. Si un sommet a besoin d'une -partie différente, alors il doit s'agir d'un sommet différent.

-

Comme exemple simple, créons un cube en utilisant BufferGeometry. Un cube est intéressant -car il semble partager des sommets aux coins mais ce n'est pas le cas en réalité. Pour notre exemple, nous allons lister tous les sommets avec toutes leurs données, -puis convertir ces données en tableaux parallèles et enfin les utiliser pour créer des -BufferAttributes et les ajouter à une BufferGeometry.

-

Nous commençons par une liste de toutes les données nécessaires pour le cube. Rappelez-vous encore une fois -que si un sommet a des parties uniques, il doit s'agir d'un sommet distinct. En conséquence, -pour faire un cube, il faut 36 sommets. 2 triangles par face, 3 sommets par triangle, -6 faces = 36 sommets.

-
const vertices = [
-  // avant
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], },
-  // droite
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], },
-  // arrière
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], },
-  // gauche
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], },
-  // haut
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], },
-  // bas
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], },
-];
-
-

Nous pouvons ensuite traduire tout cela en 3 tableaux parallèles

-
const positions = [];
-const normals = [];
-const uvs = [];
-for (const vertex of vertices) {
-  positions.push(...vertex.pos);
-  normals.push(...vertex.norm);
-  uvs.push(...vertex.uv);
-}
-
-

Enfin, nous pouvons créer une BufferGeometry, puis une BufferAttribute pour chaque tableau -et l'ajouter à la BufferGeometry.

-
  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-
-

Notez que les noms sont importants. Vous devez nommer vos attributs avec les noms -que three.js attend (sauf si vous créez un shader personnalisé). -Dans ce cas : position, normal, et uv. Si vous voulez des couleurs de sommet, -nommez votre attribut color.

-

Ci-dessus, nous avons créé 3 tableaux natifs JavaScript, positions, normals et uvs. -Nous les avons ensuite convertis en -TypedArrays -de type Float32Array. Une BufferAttribute nécessite un TypedArray, pas un tableau natif. -Une BufferAttribute exige également que vous lui indiquiez combien de composants il y a -par sommet. Pour les positions et les normales, nous avons 3 composants par sommet, -x, y et z. Pour les UV, nous en avons 2, u et v.

-

- -

-

C'est beaucoup de données. Une petite chose que nous pouvons faire est d'utiliser des indices pour référencer -les sommets. En revenant à nos données de cube, chaque face est composée de 2 triangles -avec 3 sommets chacun, soit 6 sommets au total, mais 2 de ces sommets sont exactement les mêmes ; -La même position, la même normale et la même uv. -Nous pouvons donc supprimer les sommets correspondants et les -référencer par index. Nous commençons par supprimer les sommets correspondants.

-
const vertices = [
-  // avant
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], }, // 2
--
--  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
--  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], }, // 3
-  // droite
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], }, // 4
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], }, // 5
--
--  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
--  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], }, // 6
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], }, // 7
-  // arrière
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], }, // 8
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], }, // 9
--
--  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
--  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], }, // 10
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], }, // 11
-  // gauche
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], }, // 12
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], }, // 13
--
--  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], }, // 14
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], }, // 15
-  // haut
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], }, // 16
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], }, // 17
--
--  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
--  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], }, // 18
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], }, // 19
-  // bas
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], }, // 20
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], }, // 21
--
--  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
-];
-
-

Nous avons donc maintenant 24 sommets uniques. Ensuite, nous spécifions 36 indices -pour les 36 sommets que nous devons dessiner pour faire 12 triangles en appelant BufferGeometry.setIndex avec un tableau d'indices.

-
geometry.setAttribute(
-    'position',
-    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
-    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-+geometry.setIndex([
-+   0,  1,  2,   2,  1,  3,  // avant
-+   4,  5,  6,   6,  5,  7,  // droite
-+   8,  9, 10,  10,  9, 11,  // arrière
-+  12, 13, 14,  14, 13, 15,  // gauche
-+  16, 17, 18,  18, 17, 19,  // haut
-+  20, 21, 22,  22, 21, 23,  // bas
-+]);
-
-

- -

-

BufferGeometry a une méthode computeVertexNormals pour calculer les normales si vous -ne les fournissez pas. Malheureusement, -étant donné que les positions ne peuvent pas être partagées si une autre partie d'un sommet est différente, -les résultats de l'appel à computeVertexNormals généreront des coutures si votre -géométrie est censée se connecter à elle-même comme une sphère ou un cylindre.

-
-
-
-
-
- -

Pour le cylindre ci-dessus, les normales ont été créées à l'aide de computeVertexNormals. -Si vous regardez attentivement, il y a une couture sur le cylindre. Cela est dû au fait qu'il -n'y a aucun moyen de partager les sommets au début et à la fin du cylindre, car ils -nécessitent des UV différents, de sorte que la fonction pour les calculer n'a aucune idée qu'il -s'agit des mêmes sommets à lisser. Juste une petite chose dont il faut être conscient. -La solution est de fournir vos propres normales.

-

Nous pouvons également utiliser des TypedArrays dès le début au lieu de tableaux JavaScript natifs. -L'inconvénient des TypedArrays est que vous devez spécifier leur taille à l'avance. Bien sûr, -ce n'est pas une si grande contrainte, mais avec les tableaux natifs, nous pouvons simplement -push des valeurs et voir la taille finale en vérifiant leur -length à la fin. Avec les TypedArrays, il n'y a pas de fonction push, nous devons donc -faire notre propre gestion des données lorsque nous y ajoutons des valeurs.

-

Dans cet exemple, connaître la longueur à l'avance est assez facile, car nous utilisons -un grand bloc de données statiques pour commencer.

-
-const positions = [];
--const normals = [];
--const uvs = [];
-+const numVertices = vertices.length;
-+const positionNumComponents = 3;
-+const normalNumComponents = 3;
-+const uvNumComponents = 2;
-+const positions = new Float32Array(numVertices * positionNumComponents);
-+const normals = new Float32Array(numVertices * normalNumComponents);
-+const uvs = new Float32Array(numVertices * uvNumComponents);
-+let posNdx = 0;
-+let nrmNdx = 0;
-+let uvNdx = 0;
-for (const vertex of vertices) {
--  positions.push(...vertex.pos);
--  normals.push(...vertex.norm);
--  uvs.push(...vertex.uv);
-+  positions.set(vertex.pos, posNdx);
-+  normals.set(vertex.norm, nrmNdx);
-+  uvs.set(vertex.uv, uvNdx);
-+  posNdx += positionNumComponents;
-+  nrmNdx += normalNumComponents;
-+  uvNdx += uvNumComponents;
-}
-
-geometry.setAttribute(
-    'position',
--    new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-+    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
--    new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-+    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
--    new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-+    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-geometry.setIndex([
-   0,  1,  2,   2,  1,  3,  // avant
-   4,  5,  6,   6,  5,  7,  // droite
-   8,  9, 10,  10,  9, 11,  // arrière
-  12, 13, 14,  14, 13, 15,  // gauche
-  16, 17, 18,  18, 17, 19,  // haut
-  20, 21, 22,  22, 21, 23,  // bas
-]);
-
-

- -

-

Une bonne raison d'utiliser des typedarrays est si vous souhaitez mettre à jour dynamiquement une partie -des sommets.

-

Je n'ai pas pu trouver un très bon exemple de mise à jour dynamique des sommets, alors j'ai décidé de faire une sphère et de déplacer chaque quadricône vers l'intérieur et l'extérieur depuis le centre. J'espère que c'est un exemple utile.

-

Voici le code pour générer les positions et les indices d'une sphère. Le code -partage les sommets au sein d'un quadricône, mais ne partage pas les sommets entre -les quadricônes, car nous voulons pouvoir déplacer chaque quadricône séparément.

-

Comme je suis paresseux, j'ai utilisé une petite hiérarchie de 3 objets Object3D pour calculer -les points de la sphère. La façon dont cela fonctionne est expliquée dans l'article sur l'optimisation de nombreux objets.

-
function makeSpherePositions(segmentsAround, segmentsDown) {
-  const numVertices = segmentsAround * segmentsDown * 6;
-  const numComponents = 3;
-  const positions = new Float32Array(numVertices * numComponents);
-  const indices = [];
-
-  const longHelper = new THREE.Object3D();
-  const latHelper = new THREE.Object3D();
-  const pointHelper = new THREE.Object3D();
-  longHelper.add(latHelper);
-  latHelper.add(pointHelper);
-  pointHelper.position.z = 1;
-  const temp = new THREE.Vector3();
-
-  function getPoint(lat, long) {
-    latHelper.rotation.x = lat;
-    longHelper.rotation.y = long;
-    longHelper.updateMatrixWorld(true);
-    return pointHelper.getWorldPosition(temp).toArray();
-  }
-
-  let posNdx = 0;
-  let ndx = 0;
-  for (let down = 0; down < segmentsDown; ++down) {
-    const v0 = down / segmentsDown;
-    const v1 = (down + 1) / segmentsDown;
-    const lat0 = (v0 - 0.5) * Math.PI;
-    const lat1 = (v1 - 0.5) * Math.PI;
-
-    for (let across = 0; across < segmentsAround; ++across) {
-      const u0 = across / segmentsAround;
-      const u1 = (across + 1) / segmentsAround;
-      const long0 = u0 * Math.PI * 2;
-      const long1 = u1 * Math.PI * 2;
-
-      positions.set(getPoint(lat0, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat0, long1), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long1), posNdx);  posNdx += numComponents;
-
-      indices.push(
-        ndx, ndx + 1, ndx + 2,
-        ndx + 2, ndx + 1, ndx + 3,
-      );
-      ndx += 4;
-    }
-  }
-  return {positions, indices};
-}
-
-

Nous pouvons ensuite l'appeler comme ceci

-
const segmentsAround = 24;
-const segmentsDown = 16;
-const {positions, indices} = makeSpherePositions(segmentsAround, segmentsDown);
-
-

Comme les positions retournées sont des positions de sphère unitaire, ce sont exactement les mêmes -valeurs dont nous avons besoin pour les normales, nous pouvons donc simplement les dupliquer pour les normales.

-
const normals = positions.slice();
-
-

Et ensuite nous configurons les attributs comme auparavant

-
const geometry = new THREE.BufferGeometry();
-const positionNumComponents = 3;
-const normalNumComponents = 3;
-
-+const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents);
-+positionAttribute.setUsage(THREE.DynamicDrawUsage);
-geometry.setAttribute(
-    'position',
-+    positionAttribute);
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setIndex(indices);
-
-

J'ai mis en évidence quelques différences. Nous sauvegardons une référence à l'attribut de position. -Nous le marquons également comme dynamique. C'est une indication pour THREE.js que nous allons modifier -souvent le contenu de l'attribut.

-

Dans notre boucle de rendu, nous mettons à jour les positions en fonction de leurs normales à chaque image.

-
const temp = new THREE.Vector3();
-
-...
-
-for (let i = 0; i < positions.length; i += 3) {
-  const quad = (i / 12 | 0);
-  const ringId = quad / segmentsAround | 0;
-  const ringQuadId = quad % segmentsAround;
-  const ringU = ringQuadId / segmentsAround;
-  const angle = ringU * Math.PI * 2;
-  temp.fromArray(normals, i);
-  temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5));
-  temp.toArray(positions, i);
-}
-positionAttribute.needsUpdate = true;
-
-

Et nous réglons positionAttribute.needsUpdate à true pour dire à THREE.js d'utiliser nos changements.

-

- -

-

J'espère que ces exemples vous ont été utiles pour comprendre comment utiliser BufferGeometry directement pour -créer votre propre géométrie et comment mettre à jour dynamiquement le contenu d'un -BufferAttribute.

- -

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/debugging-glsl.html b/manual/fr/debugging-glsl.html deleted file mode 100644 index 59320839eec095..00000000000000 --- a/manual/fr/debugging-glsl.html +++ /dev/null @@ -1,78 +0,0 @@ - - - Débogage - GLSL - - - - - - - - - - - - - -
-
-

Débogage - GLSL

-
-
-
-

Ce site ne vous enseigne pas le GLSL, tout comme il ne vous enseigne pas le JavaScript. Ce sont des sujets très vastes. Si vous souhaitez apprendre le GLSL, consultez -ces articles comme point de départ.

-

Si vous connaissez déjà le GLSL, voici quelques conseils pour le débogage.

-

Lorsque je crée un nouveau shader GLSL et que rien n'apparaît, la première chose que je fais généralement est de modifier le shader de fragment pour qu'il renvoie une couleur unie. Par exemple, tout en bas du shader, je pourrais mettre

-
void main() {
-
-  ...
-
-  gl_FragColor = vec4(1, 0, 0, 1);  // red
-}
-
-

Si je vois l'objet que j'essayais de dessiner, je sais que le problème est lié à mon shader de fragment. Cela peut être n'importe quoi, comme de mauvaises textures, des uniforms non initialisés, des uniforms avec les mauvaises valeurs, mais au moins j'ai une direction où chercher.

-

Pour tester certains de ces points, je pourrais commencer par essayer de dessiner certaines des entrées. Par exemple, si j'utilise des normales dans le shader de fragment, je pourrais ajouter

-
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
-
-

Les normales vont de -1 à +1, donc en multipliant par 0,5 et en ajoutant 0,5, nous obtenons des valeurs qui vont de 0,0 à 1,0, ce qui les rend utiles pour les couleurs.

-

Essayez ceci avec des choses dont vous savez qu'elles fonctionnent et vous commencerez à avoir une idée de ce à quoi ressemblent les normales normalement. Si vos normales ne semblent pas normales, vous avez une piste où chercher. Si vous manipulez les normales dans le shader de fragment, vous pouvez utiliser la même technique pour dessiner le résultat de cette manipulation.

-
- -

De même, si nous utilisons des textures, il y aura des coordonnées de texture et nous pouvons les dessiner avec quelque chose comme

-
gl_FragColor = vec4(fract(vUv), 0, 1);
-
-

Le fract est là au cas où nous utiliserions des coordonnées de texture qui dépassent la plage 0 à 1. C'est courant si texture.repeat est défini sur une valeur supérieure à 1.

-
- -

Vous pouvez faire des choses similaires pour toutes les valeurs de votre shader de fragment. Déterminez quelle est leur plage probable, ajoutez du code pour définir gl_FragColor avec cette plage mise à l'échelle de 0,0 à 1,0

-

Pour vérifier les textures, essayez un CanvasTexture ou un DataTexture dont vous savez qu'il fonctionne.

-

Inversement, si après avoir défini gl_FragColor sur rouge je ne vois toujours rien, alors j'ai une indication que mon problème pourrait être lié aux choses relatives au shader de vertex. Certaines matrices pourraient être incorrectes ou mes attributs pourraient contenir de mauvaises données ou être mal configurés.

-

Je regarderais d'abord les matrices. Je pourrais mettre un point d'arrêt juste après mon appel à renderer.render(scene, camera) et commencer ensuite à développer les éléments dans l'inspecteur. La matrice monde et la matrice de projection de la caméra ne sont-elles pas au moins pleines de NaNs ? En développant la scène et en regardant ses children, je vérifierais que les matrices monde semblent raisonnables (pas de NaNs) et que les 4 dernières valeurs de chaque matrice semblent raisonnables pour ma scène. Si j'attends que ma scène fasse 50x50x50 unités et qu'une matrice affiche 552352623.123, il est clair que quelque chose ne va pas.

-
- -

Tout comme nous l'avons fait pour le shader de fragment, nous pouvons également dessiner les valeurs du shader de vertex en les passant au shader de fragment. Déclarez une variable varying dans les deux et passez la valeur dont vous n'êtes pas sûr qu'elle soit correcte. En fait, si mon shader utilise des normales, je modifierai le shader de fragment pour les afficher comme mentionné ci-dessus, puis je définirai simplement vNormal à la valeur que je souhaite afficher, mais mise à l'échelle de sorte que les valeurs aillent de 0,0 à 1,0. Je regarde ensuite les résultats et vois s'ils correspondent à mes attentes.

-

Une autre bonne chose à faire est d'utiliser un shader plus simple. Pouvez-vous dessiner vos données avec un MeshBasicMaterial ? Si oui, essayez-le et assurez-vous qu'il s'affiche comme prévu.

-

Sinon, quel est le shader de vertex le plus simple qui vous permettra de visualiser votre géométrie ? Généralement, c'est aussi simple que

-
gl_Position = projection * modelView * vec4(position.xyz, 1);
-
-

Si cela fonctionne, commencez à ajouter vos modifications petit à petit.

-

Une autre chose que vous pouvez faire est d'utiliser l'extension Shader Editor pour Chrome ou similaire pour d'autres navigateurs. C'est un excellent moyen de voir comment fonctionnent d'autres shaders. C'est aussi pratique car vous pouvez apporter certaines des modifications suggérées ci-dessus en direct pendant que le code s'exécute.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/debugging-javascript.html b/manual/fr/debugging-javascript.html deleted file mode 100644 index 48f5aa6913f506..00000000000000 --- a/manual/fr/debugging-javascript.html +++ /dev/null @@ -1,373 +0,0 @@ - - - Débogage JavaScript - - - - - - - - - - - - - -
-
-

Débogage JavaScript

-
-
-
-

La majeure partie de cet article ne concerne pas directement THREE.js, mais plutôt le débogage de JavaScript en général. Cela semblait important car de nombreuses personnes qui débutent avec THREE.js commencent également avec JavaScript, j'espère donc que cela pourra les aider à résoudre plus facilement les problèmes qu'ils rencontrent.

-

Le débogage est un vaste sujet et je ne peux probablement pas couvrir tout ce qu'il y a à savoir, mais si vous débutez en JavaScript, voici quelques pistes. Je vous suggère fortement de prendre le temps de les apprendre. Elles vous aideront énormément dans votre apprentissage.

-

Apprenez à utiliser les outils de développement de votre navigateur

-

Tous les navigateurs disposent d'outils de développement. -Chrome, -Firefox, -Safari, -Edge.

-

Dans Chrome, vous pouvez cliquer sur l'icône , choisir Plus d'outils -> Outils de développement pour accéder aux outils de développement. Un raccourci clavier est également affiché.

-
- -

Dans Firefox, vous cliquez sur l'icône , choisissez "Développeur Web", puis "Activer/Désactiver les outils"

-
- -

Dans Safari, vous devez d'abord activer le menu Développement depuis les Préférences avancées de Safari.

-
- -

Puis, dans le menu Développement, vous pouvez choisir "Afficher/Connecter l'inspecteur web".

-
- -

Avec Chrome, vous pouvez également utiliser Chrome sur votre ordinateur pour déboguer des pages web s'exécutant dans Chrome sur votre téléphone ou tablette Android. De même avec Safari, vous pouvez -utiliser votre ordinateur pour déboguer des pages web s'exécutant dans Safari sur des iPhones et iPads.

-

Je suis plus familier avec Chrome, donc ce guide utilisera Chrome comme exemple pour faire référence aux outils, mais la plupart des navigateurs ont des fonctionnalités similaires, il devrait donc être facile d'appliquer ce qui est dit ici à tous les navigateurs.

-

Désactiver le cache

-

Les navigateurs essaient de réutiliser les données qu'ils ont déjà téléchargées. C'est excellent pour les utilisateurs, car si vous visitez un site web une deuxième fois, de nombreux fichiers utilisés pour afficher le site n'auront pas à être téléchargés à nouveau.

-

D'autre part, cela peut être problématique pour le développement web. Vous modifiez un fichier sur votre ordinateur, rechargez la page, et vous ne voyez pas les changements car le navigateur utilise la version qu'il a obtenue la dernière fois.

-

Une solution pendant le développement web est de désactiver le cache. Ainsi, le navigateur obtiendra toujours les versions les plus récentes de vos fichiers.

-

Choisissez d'abord les paramètres dans le menu du coin

-
- -

Puis choisissez "Désactiver le cache (lorsque les outils de développement sont ouverts)".

-
- -

Utiliser la console JavaScript

-

Dans tous les outils de développement se trouve une console. Elle affiche les avertissements et les messages d'erreur.

-

LISEZ LES MESSAGES !!

-

Typiquement, il ne devrait y avoir que 1 ou 2 messages.

-
- -

Si vous en voyez d'autres, LISEZ-LES. Par exemple :

-
- -

J'ai mal orthographié "three" en "threee"

-

Vous pouvez également afficher vos propres informations dans la console avec console.log, comme ceci :

-
console.log(someObject.position.x, someObject.position.y, someObject.position.z);
-
-

Encore mieux, si vous affichez un objet, vous pouvez l'inspecter. Par exemple, si nous affichons l'objet scène racine de l'article sur les gLTF

-
  {
-    const gltfLoader = new GLTFLoader();
-    gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-      const root = gltf.scene;
-      scene.add(root);
-+      console.log(root);
-
-

Nous pouvons ensuite développer cet objet dans la console JavaScript

-
- -

Vous pouvez également utiliser console.error qui rapporte le message en rouge et inclut une trace de pile.

-

Afficher des données à l'écran

-

Une autre méthode évidente mais souvent négligée est d'ajouter des balises <div> ou <pre> et d'y insérer des données.

-

La manière la plus évidente est de créer des éléments HTML

-
<canvas id="c"></canvas>
-+<div id="debug">
-+  <div>x:<span id="x"></span></div>
-+  <div>y:<span id="y"></span></div>
-+  <div>z:<span id="z"></span></div>
-+</div>
-
-

Stylez-les pour qu'ils restent au-dessus du canevas. (en supposant que votre canevas remplisse la page)

-
<style>
-#debug {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-  padding: 1em;
-  background: rgba(0, 0, 0, 0.8);
-  color: white;
-  font-family: monospace;
-}
-</style>
-
-

Puis recherchez les éléments et définissez leur contenu.

-
// au moment de l'initialisation
-const xElem = document.querySelector('#x');
-const yElem = document.querySelector('#y');
-const zElem = document.querySelector('#z');
-
-// au moment du rendu ou de la mise à jour
-xElem.textContent = someObject.position.x.toFixed(3);
-yElem.textContent = someObject.position.y.toFixed(3);
-zElem.textContent = someObject.position.z.toFixed(3);
-
-

C'est plus utile pour les valeurs en temps réel

-

- -

-

Une autre façon d'afficher des données à l'écran est de créer un logger à effacement. Je viens d'inventer ce terme, mais de nombreux jeux sur lesquels j'ai travaillé ont utilisé cette solution. L'idée est d'avoir un tampon qui affiche des messages pour une seule image. Toute partie de votre code qui souhaite afficher des données appelle une fonction pour ajouter des données à ce tampon à chaque image. C'est beaucoup moins de travail que de créer un élément par donnée comme ci-dessus.

-

Par exemple, modifions le HTML ci-dessus pour qu'il soit juste ceci :

-
<canvas id="c"></canvas>
-<div id="debug">
-  <pre></pre>
-</div>
-
-

Et créons une classe simple pour gérer ce tampon d'effacement arrière.

-
class ClearingLogger {
-  constructor(elem) {
-    this.elem = elem;
-    this.lines = [];
-  }
-  log(...args) {
-    this.lines.push([...args].join(' '));
-  }
-  render() {
-    this.elem.textContent = this.lines.join('\n');
-    this.lines = [];
-  }
-}
-
-

Ensuite, créons un exemple simple qui, chaque fois que nous cliquons avec la souris, crée un maillage qui se déplace dans une direction aléatoire pendant 2 secondes. Nous commencerons avec l'un des exemples de l'article sur rendre les choses réactives

-

Voici le code qui ajoute un nouveau Mesh chaque fois que nous cliquons avec la souris

-
const geometry = new THREE.SphereGeometry();
-const material = new THREE.MeshBasicMaterial({color: 'red'});
-
-const things = [];
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min;
-}
-
-function createThing() {
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  things.push({
-    mesh,
-    timer: 2,
-    velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
-  });
-}
-
-canvas.addEventListener('click', createThing);
-
-

Et voici le code qui déplace les maillages que nous avons créés, les enregistre, et les supprime lorsque leur minuterie est écoulée

-
const logger = new ClearingLogger(document.querySelector('#debug pre'));
-
-let then = 0;
-function render(now) {
-  now *= 0.001;  // convertir en secondes
-  const deltaTime = now - then;
-  then = now;
-
-  ...
-
-  logger.log('fps:', (1 / deltaTime).toFixed(1));
-  logger.log('num things:', things.length);
-  for (let i = 0; i < things.length;) {
-    const thing = things[i];
-    const mesh = thing.mesh;
-    const pos = mesh.position;
-    logger.log(
-        'timer:', thing.timer.toFixed(3),
-        'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
-    thing.timer -= deltaTime;
-    if (thing.timer <= 0) {
-      // supprimer cet élément. Notez que nous n'avançons pas `i`
-      things.splice(i, 1);
-      scene.remove(mesh);
-    } else {
-      mesh.position.addScaledVector(thing.velocity, deltaTime);
-      ++i;
-    }
-  }
-
-  renderer.render(scene, camera);
-  logger.render();
-
-  requestAnimationFrame(render);
-}
-
-

Cliquez maintenant plusieurs fois avec la souris dans l'exemple ci-dessous

-

- -

-

Paramètres de requête

-

Une autre chose à retenir est que les pages web peuvent se voir passer des données soit via des paramètres de requête, soit via l'ancre, parfois appelée la recherche et le hachage.

-
https://domain/path/?query#anchor
-

Vous pouvez l'utiliser pour rendre des fonctionnalités optionnelles ou passer des paramètres.

-

Par exemple, prenons l'exemple précédent et faisons en sorte que les informations de débogage n'apparaissent que si nous mettons ?debug=true dans l'URL.

-

Nous avons d'abord besoin de code pour analyser la chaîne de requête

-
/**
-  * Renvoie les paramètres de requête sous forme d'objet clé/valeur.
-  * Exemple : Si les paramètres de requête sont
-  *
-  *    abc=123&def=456&name=gman
-  *
-  * Alors `getQuery()` renverra un objet comme
-  *
-  *    {
-  *      abc: '123',
-  *      def: '456',
-  *      name: 'gman',
-  *    }
-  */
-function getQuery() {
-  return Object.fromEntries(new URLSearchParams(window.location.search).entries());
-}
-
-

Nous pourrions ensuite faire en sorte que l'élément de débogage ne s'affiche pas par défaut

-
<canvas id="c"></canvas>
-+<div id="debug" style="display: none;">
-  <pre></pre>
-</div>
-
-

Ensuite, dans le code, nous lisons les paramètres et choisissons de rendre visible les informations de débogage si et seulement si ?debug=true est passé en paramètre

-
const query = getQuery();
-const debug = query.debug === 'true';
-const logger = debug
-   ? new ClearingLogger(document.querySelector('#debug pre'))
-   : new DummyLogger();
-if (debug) {
-  document.querySelector('#debug').style.display = '';
-}
-
-

Nous avons également créé un DummyLogger qui ne fait rien et avons choisi de l'utiliser si ?debug=true n'a pas été passé en paramètre.

-
class DummyLogger {
-  log() {}
-  render() {}
-}
-
-

Vous pouvez voir si nous utilisons cette URL :

-

debug-js-params.html

-

il n'y a pas d'informations de débogage, mais si nous utilisons cette URL :

-

debug-js-params.html?debug=true

-

il y a des informations de débogage.

-

Plusieurs paramètres peuvent être passés en les séparant par '&', comme dans somepage.html?someparam=somevalue&someotherparam=someothervalue. En utilisant des paramètres comme ceci, nous pouvons passer toutes sortes d'options. Peut-être speed=0.01 pour ralentir notre application afin de faciliter la compréhension de quelque chose, ou showHelpers=true pour indiquer s'il faut ajouter des helpers qui affichent les lumières, les ombres ou le frustum de la caméra vus dans d'autres leçons.

-

Apprenez à utiliser le Débogueur

-

Chaque navigateur dispose d'un débogueur où vous pouvez mettre votre programme en pause, l'exécuter pas à pas ligne par ligne et inspecter toutes les variables.

-

Vous apprendre à utiliser un débogueur est un sujet trop vaste pour cet article, mais voici quelques liens

- -

Vérifiez la présence de NaN dans le débogueur ou ailleurs

-

NaN est l'abréviation de Not A Number (Pas un Nombre). C'est la valeur que JavaScript attribuera lorsque vous faites quelque chose qui n'a pas de sens mathématique.

-

Voici un exemple simple :

-
- -

Souvent, quand je crée quelque chose et que rien n'apparaît à l'écran, je vérifie certaines valeurs et si je vois NaN, j'ai instantanément un point de départ pour chercher.

-

À titre d'exemple, lorsque j'ai commencé à créer le chemin pour l'article sur le chargement de fichiers gLTF, j'ai créé une courbe en utilisant la classe SplineCurve qui crée une courbe 2D.

-

J'ai ensuite utilisé cette courbe pour déplacer les voitures comme ceci :

-
curve.getPointAt(zeroToOnePointOnCurve, car.position);
-
-

En interne, curve.getPointAt appelle la fonction set sur l'objet passé comme deuxième argument. Dans ce cas, ce deuxième argument est car.position qui est un Vector3. La fonction set de Vector3 nécessite 3 arguments (x, y et z) mais SplineCurve est une courbe 2D, elle appelle donc car.position.set avec juste x et y.

-

Le résultat est que car.position.set définit x sur x, y sur y, et z sur undefined.

-

Un rapide coup d'œil dans le débogueur sur la matrixWorld de la voiture a montré un tas de valeurs NaN.

-
- -

Voir que la matrice contenait des NaN suggérait que quelque chose comme position, rotation, scale ou une autre fonction qui affecte cette matrice avait de mauvaises données. En remontant à partir de là, il a été facile de trouver le problème.

-

En plus de NaN, il y a aussi Infinity qui est un signe similaire qu'il y a un bug mathématique quelque part.

-

Regardez le code !

-

THREE.js est Open Source. N'ayez pas peur de regarder le code ! Vous pouvez regarder à l'intérieur sur github. Vous pouvez également regarder à l'intérieur en entrant dans les fonctions du débogueur.

-

Mettez requestAnimationFrame en bas de votre fonction de rendu.

-

Je vois souvent ce schéma

-
function render() {
-   requestAnimationFrame(render);
-
-   // -- faire des choses --
-
-   renderer.render(scene, camera);
-}
-requestAnimationFrame(render);
-
-

Je suggérerais de mettre l'appel à requestAnimationFrame en bas, comme ceci :

-
function render() {
-   // -- faire des choses --
-
-   renderer.render(scene, camera);
-
-   requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

La raison principale est que cela signifie que votre code s'arrêtera si vous avez une erreur. Mettre requestAnimationFrame en haut signifie que votre code continuera de s'exécuter même si vous avez une erreur puisque vous avez déjà demandé une autre image. À mon avis, il vaut mieux trouver ces erreurs que les ignorer. Elles pourraient facilement être la raison pour laquelle quelque chose n'apparaît pas comme vous l'attendez, mais à moins que votre code ne s'arrête, vous pourriez même ne pas le remarquer.

-

Vérifiez vos unités !

-

Cela signifie essentiellement savoir, par exemple, quand utiliser des degrés plutôt que des radians. Il est regrettable que THREE.js n'utilise pas uniformément les mêmes unités partout. De mémoire, le champ de vision de la caméra est en degrés. Tous les autres angles sont en radians.

-

L'autre point à surveiller est la taille de vos unités mondiales. Jusqu'à récemment, les applications 3D pouvaient choisir la taille d'unité qu'elles voulaient. Une application pouvait choisir 1 unité = 1 cm. Une autre pouvait choisir 1 unité = 1 pied. Il est toujours vrai que vous pouvez choisir les unités que vous voulez pour certaines applications. Cela dit, THREE.js suppose 1 unité = 1 mètre. C'est important pour des choses comme le rendu basé sur la physique qui utilise des mètres pour calculer les effets d'éclairage. C'est également important pour la RA et la RV qui doivent gérer des unités du monde réel, comme l'emplacement de votre téléphone ou des contrôleurs VR.

-

Créer un Exemple Minimal, Complet et Vérifiable pour Stack Overflow

-

Si vous décidez de poser une question sur THREE.js, il est presque toujours requis de fournir un MCVE, qui signifie Exemple Minimal, Complet et Vérifiable.

-

La partie Minimale est importante. Disons que vous avez un problème avec le mouvement le long du chemin dans le dernier exemple de l'article sur le chargement de gLTF. Cet exemple contient de nombreuses parties. En les listant, il y a :

-
    -
  1. Beaucoup de HTML
  2. -
  3. Du CSS
  4. -
  5. Lumières
  6. -
  7. Ombres
  8. -
  9. Code lil-gui pour manipuler les ombres
  10. -
  11. Code pour charger un fichier .GLTF
  12. -
  13. Code pour redimensionner le canevas.
  14. -
  15. Code pour déplacer les voitures le long des chemins
  16. -
-

C'est assez énorme. Si votre question ne concerne que la partie suivant le chemin, vous pouvez retirer la majeure partie du HTML car vous n'avez besoin que d'une balise <canvas> et d'une balise <script> pour THREE.js. Vous pouvez retirer le code CSS et le code de redimensionnement. Vous pouvez retirer le code .GLTF car vous ne vous souciez que du chemin. Vous pouvez retirer les lumières et les ombres en utilisant un MeshBasicMaterial. Vous pouvez certainement retirer le code lil-gui. Le code crée un plan de sol avec une texture. Il serait plus simple d'utiliser un GridHelper. Enfin, si notre question concerne le déplacement d'objets sur un chemin, nous pourrions simplement utiliser des cubes sur le chemin au lieu de modèles de voitures chargés.

-

Voici un exemple plus minimal prenant en compte tout ce qui précède. Il est passé de 271 lignes à 135. Nous pourrions envisager de le réduire encore plus en simplifiant notre chemin. Peut-être qu'un chemin avec 3 ou 4 points fonctionnerait aussi bien que notre chemin avec 21 points.

-

- -

-

J'ai gardé l'OrbitController simplement parce qu'il est utile pour que d'autres personnes puissent déplacer la caméra et comprendre ce qui se passe, mais en fonction de votre problème, vous pourriez également être en mesure de le supprimer.

-

La meilleure chose à propos de la création d'un MCVE est que nous résolvons souvent notre propre problème. Le processus consistant à supprimer tout ce qui n'est pas nécessaire et à créer le plus petit exemple possible reproduisant le problème nous conduit le plus souvent à notre bug.

-

De plus, c'est respectueux du temps de toutes les personnes à qui vous demandez de regarder votre code sur Stack Overflow. En créant l'exemple minimal, vous leur facilitez grandement la tâche de vous aider. Vous apprendrez également au cours du processus.

-

Il est également important, lorsque vous allez sur Stack Overflow pour poster votre question, de mettre votre code dans un extrait (snippet). Bien sûr, vous êtes libre d'utiliser JSFiddle ou Codepen ou un site similaire pour tester votre MCVE, mais une fois que vous postez réellement votre question sur Stack Overflow, vous êtes tenu de mettre le code pour reproduire votre problème dans la question elle-même. En créant un extrait, vous remplissez cette exigence.

-

Notez également que tous les exemples en direct sur ce site devraient fonctionner comme des extraits. Copiez simplement les parties HTML, CSS et JavaScript dans les sections respectives de l'éditeur d'extraits. N'oubliez pas d'essayer de retirer les parties qui ne sont pas pertinentes pour votre problème et d'essayer de rendre votre code le plus minimal possible.

-

Suivez ces suggestions et vous aurez beaucoup plus de chances d'obtenir de l'aide pour votre problème.

-

Utilisez un MeshBasicMaterial

-

Étant donné que le MeshBasicMaterial n'utilise pas de lumières, c'est un moyen d'éliminer les raisons pour lesquelles quelque chose pourrait ne pas s'afficher. Si vos objets s'affichent en utilisant le MeshBasicMaterial mais pas avec les matériaux que vous utilisiez, alors vous savez que le problème vient probablement des matériaux ou des lumières et non d'une autre partie du code.

-

Vérifiez les paramètres near et far de votre caméra

-

Une PerspectiveCamera a des paramètres near et far qui sont couverts dans l'article sur les caméras. Assurez-vous qu'ils sont définis pour correspondre à l'espace qui contient vos objets. Vous pourriez même les définir temporairement à quelque chose de grand comme near = 0.001 et far = 1000000. Vous rencontrerez probablement des problèmes de résolution de profondeur, mais vous pourrez au moins voir vos objets à condition qu'ils soient devant la caméra.

-

Vérifiez que votre scène est devant la caméra

-

Parfois, les choses n'apparaissent pas parce qu'elles ne sont pas devant la caméra. Si votre caméra n'est pas contrôlable, essayez d'ajouter un contrôle de caméra comme l'OrbitController afin de pouvoir regarder autour de vous et trouver votre scène. Ou, essayez de cadrer la scène en utilisant du code, comme décrit dans cet article. Ce code trouve la taille d'une partie de la scène, puis déplace la caméra et ajuste les paramètres near et far pour la rendre visible. Vous pouvez ensuite regarder dans le débogueur ou ajouter des messages console.log pour afficher la taille et le centre de la scène.

-

Mettez quelque chose devant la caméra

-

C'est juste une autre façon de dire que si tout le reste échoue, commencez par quelque chose qui fonctionne, puis ajoutez progressivement des éléments. Si vous obtenez un écran vide, essayez de mettre quelque chose directement devant la caméra. Créez une sphère ou une boîte, donnez-lui un matériau simple comme le MeshBasicMaterial et assurez-vous que vous pouvez l'afficher à l'écran. Puis commencez à ajouter des éléments petit à petit et à tester. Finalement, vous reproduirez votre bug ou vous le trouverez en chemin.

-
-

Voici quelques conseils pour le débogage de JavaScript. Passons également en revue quelques conseils pour le débogage de GLSL.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/drawing-lines.html b/manual/fr/drawing-lines.html deleted file mode 100644 index 076e61978da2eb..00000000000000 --- a/manual/fr/drawing-lines.html +++ /dev/null @@ -1,91 +0,0 @@ - - - Dessiner des lignes - - - - - - - - - - - - - -
-
-

Dessiner des lignes

-
-
-
- -

- Disons que vous voulez dessiner une ligne ou un cercle, pas un `Mesh` en fil de fer. - Nous devons d'abord configurer le renderer, la scène et la caméra (voir la page Créer une scène). -

- -

Voici le code que nous allons utiliser :

-
-const renderer = new THREE.WebGLRenderer();
-renderer.setSize( window.innerWidth, window.innerHeight );
-document.body.appendChild( renderer.domElement );
-
-const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 );
-camera.position.set( 0, 0, 100 );
-camera.lookAt( 0, 0, 0 );
-
-const scene = new THREE.Scene();
-
-

Next thing we will do is define a material. For lines we have to use `LineBasicMaterial` or `LineDashedMaterial`.

-
-//créer un LineBasicMaterial bleu
-const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
-
- -

- Après le material, nous aurons besoin d'une géométrie avec quelques sommets : -

- -
-const points = [];
-points.push( new THREE.Vector3( - 10, 0, 0 ) );
-points.push( new THREE.Vector3( 0, 10, 0 ) );
-points.push( new THREE.Vector3( 10, 0, 0 ) );
-
-const geometry = new THREE.BufferGeometry().setFromPoints( points );
-
- -

Notez que les lignes sont tracées entre chaque paire consécutive de sommets, mais pas entre le premier et le dernier (la ligne n'est pas fermée).

- -

Maintenant que nous avons des points pour deux lignes et un material, nous pouvons les assembler pour former une ligne.

-
-const line = new THREE.Line( geometry, material );
-
-

Tout ce qui reste est de l'ajouter à la scène et d'appeler `renderer.render()`.

- -
-scene.add( line );
-renderer.render( scene, camera );
-
- -

Vous devriez maintenant voir une flèche pointant vers le haut, faite de deux lignes bleues.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/faq.html b/manual/fr/faq.html deleted file mode 100644 index 7ea4d7bd2a954d..00000000000000 --- a/manual/fr/faq.html +++ /dev/null @@ -1,93 +0,0 @@ - - - Foire aux questions - - - - - - - - - - - - - -
-
-

Foire aux questions

-
-
-
- -

Quel format de modèle 3D est le mieux supporté ?

-
-

- Le format recommandé pour l'importation et l'exportation d'assets est glTF (GL Transmission Format). Comme glTF est axé sur la livraison d'assets au moment de l'exécution, il est compact à transmettre et rapide à charger. -

-

- three.js fournit également des chargeurs pour de nombreux autres formats populaires comme FBX, Collada ou OBJ. Néanmoins, vous devriez toujours essayer d'établir d'abord un workflow basé sur glTF dans vos projets. -

-
- -

Pourquoi y a-t-il des balises meta viewport dans les exemples ?

-
-
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
- -

Ces balises contrôlent la taille et l'échelle de la fenêtre d'affichage (viewport) pour les navigateurs mobiles (où le contenu de la page peut être rendu à une taille différente de la fenêtre d'affichage visible).

- -

[link:https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html Safari : Utiliser la fenêtre d'affichage]

- -

[link:https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag MDN : Utiliser la balise meta viewport]

-
- -

Comment l'échelle de la scène peut-elle être préservée lors du redimensionnement ?

-

- Nous voulons que tous les objets, quelle que soit leur distance par rapport à la caméra, apparaissent de la même taille, même lorsque la fenêtre est redimensionnée. - - L'équation clé pour résoudre cela est cette formule pour la hauteur visible à une distance donnée : - -

visible_height = 2 * Math.tan( ( Math.PI / 180 ) * camera.fov / 2 ) * distance_from_camera;
- Si nous augmentons la hauteur de la fenêtre d'un certain pourcentage, alors ce que nous voulons, c'est que la hauteur visible à toutes les distances augmente du même pourcentage. - - Cela ne peut pas être fait en changeant la position de la caméra. Au lieu de cela, vous devez changer le champ de vision de la caméra. - [link:http://jsfiddle.net/Q4Jpu/ Exemple]. -

- -

Pourquoi une partie de mon objet est-elle invisible ?

-

- Cela pourrait être dû au culling des faces (face culling). Les faces ont une orientation qui décide quel côté est lequel. Et le culling supprime le côté arrière dans des circonstances normales. - Pour voir si c'est votre problème, changez le côté du matériau en THREE.DoubleSide. -

material.side = THREE.DoubleSide
-

- -

Pourquoi three.js renvoie-t-il parfois des résultats étranges pour des entrées invalides ?

-

- Pour des raisons de performance, three.js ne valide pas les entrées dans la plupart des cas. Il est de la responsabilité de votre application de s'assurer que toutes les entrées sont valides. -

- -

Puis-je utiliser three.js dans Node.js ?

-

- Parce que three.js est conçu pour le web, il dépend d'APIs de navigateur et du DOM qui n'existent pas toujours dans Node.js. Certains de ces problèmes peuvent être évités en utilisant des shims comme - [link:https://github.com/stackgl/headless-gl headless-gl] et [link:https://github.com/rstacruz/jsdom-global jsdom-global], ou en remplaçant des composants comme `TextureLoader` - par des alternatives personnalisées. D'autres APIs du DOM peuvent être profondément liées au code qui les utilise, et seront plus difficiles à contourner. Nous accueillons favorablement les pull requests simples et maintenables pour améliorer le support de Node.js, mais recommandons d'ouvrir d'abord un issue pour discuter de vos améliorations. -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/fog.html b/manual/fr/fog.html deleted file mode 100644 index d37face92f2bf9..00000000000000 --- a/manual/fr/fog.html +++ /dev/null @@ -1,279 +0,0 @@ - - - Brouillard - - - - - - - - - - - - - -
-
-

Brouillard

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le -premier article est les fondamentaux de three.js. Si -vous ne l'avez pas encore lu et que vous débutez avec three.js, vous devriez peut-être -envisager de commencer par là. Si vous n'avez pas lu sur les caméras, vous voudrez peut-être -commencer par cet article.

-

Le brouillard dans un moteur 3D est généralement une façon de s'estomper vers une couleur spécifique -en fonction de la distance par rapport à la caméra. Dans three.js, vous ajoutez du brouillard en -créant un objet Fog ou FogExp2 et en le définissant sur la -propriété fog de la scène.

-

Fog vous permet de choisir les paramètres near et far qui sont des distances -par rapport à la caméra. Tout ce qui est plus proche que near n'est pas affecté par le brouillard. -Tout ce qui est plus loin que far prend complètement la couleur du brouillard. Les parties entre -near et far s'estompent de leur couleur de matériau à la couleur du brouillard.

-

Il y a aussi FogExp2 qui augmente de manière exponentielle avec la distance par rapport à la caméra.

-

Pour utiliser l'un ou l'autre type de brouillard, vous en créez un et l'attribuez à la scène comme dans

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;  // white
-  const near = 10;
-  const far = 100;
-  scene.fog = new THREE.Fog(color, near, far);
-}
-
-

ou pour FogExp2 ce serait

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;
-  const density = 0.1;
-  scene.fog = new THREE.FogExp2(color, density);
-}
-
-

FogExp2 est plus proche de la réalité mais Fog est utilisé -plus couramment car il vous permet de choisir un endroit où appliquer -le brouillard afin que vous puissiez décider d'afficher une scène -claire jusqu'à une certaine distance, puis de s'estomper vers une couleur -au-delà de cette distance.

-
-
-
-
THREE.Fog
-
-
-
-
THREE.FogExp2
-
-
- -

Il est important de noter que le brouillard est appliqué aux choses qui sont rendues. -Il fait partie du calcul de chaque pixel de la couleur de l'objet. -Cela signifie que si vous voulez que votre scène s'estompe vers une certaine couleur, vous -devez définir le brouillard et la couleur de fond sur la même couleur. -La couleur de fond est définie à l'aide de la -propriété scene.background. Pour choisir une couleur de fond, vous y attachez un THREE.Color. Par exemple

-
scene.background = new THREE.Color('#F00');  // rouge
-
-
-
-
-
brouillard bleu, fond rouge
-
-
-
-
brouillard bleu, fond bleu
-
-
- -

Voici l'un de nos exemples précédents avec l'ajout de brouillard. La seule addition -est juste après la mise en place de la scène, nous ajoutons le brouillard et définissons la couleur de fond de la scène

-
const scene = new THREE.Scene();
-
-+{
-+  const near = 1;
-+  const far = 2;
-+  const color = 'lightblue';
-+  scene.fog = new THREE.Fog(color, near, far);
-+  scene.background = new THREE.Color(color);
-+}
-
-

Dans l'exemple ci-dessous, near de la caméra est de 0.1 et far est de 5. -La caméra est à z = 2. Les cubes mesurent 1 unité de large et sont à Z = 0. -Cela signifie qu'avec un réglage de brouillard de near = 1 et far = 2, les cubes -s'estomperont juste autour de leur centre.

-

- -

-

Ajoutons une interface pour pouvoir ajuster le brouillard. Encore une fois, nous allons utiliser -lil-gui. lil-gui prend -un objet et une propriété et crée automatiquement une interface -pour ce type de propriété. Nous pourrions simplement le laisser manipuler -les propriétés near et far du brouillard, mais il est invalide d'avoir -near supérieur à far, alors créons un assistant pour que lil-gui -puisse manipuler une propriété near et far, mais nous nous assurerons que near -est inférieur ou égal à far et que far est supérieur ou égal à near.

-
// Nous utilisons cette classe pour la passer à lil-gui
-// ainsi quand elle manipule near ou far
-// near n'est jamais > far et far n'est jamais < near
-class FogGUIHelper {
-  constructor(fog) {
-    this.fog = fog;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-}
-
-

Nous pouvons ensuite l'ajouter comme ceci

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-+
-+  const fogGUIHelper = new FogGUIHelper(scene.fog);
-+  gui.add(fogGUIHelper, 'near', near, far).listen();
-+  gui.add(fogGUIHelper, 'far', near, far).listen();
-}
-
-

Les paramètres near et far définissent les valeurs minimum et maximum -pour l'ajustement du brouillard. Ils sont définis lorsque nous configurons la caméra.

-

Le .listen() à la fin des 2 dernières lignes indique à lil-gui d'écouter -les changements. De cette façon, lorsque nous changeons near à cause d'une modification de far -ou que nous changeons far en réponse à une modification de near, lil-gui mettra à jour -l'interface utilisateur de l'autre propriété pour nous.

-

Il pourrait également être agréable de pouvoir changer la couleur du brouillard, mais comme mentionné -ci-dessus, nous devons synchroniser la couleur du brouillard et la couleur de fond. -Ajoutons donc une autre propriété virtuelle à notre assistant qui définira les deux couleurs -lorsque lil-gui la manipulera.

-

lil-gui peut manipuler les couleurs de 4 manières : comme une chaîne hexadécimale CSS à 6 chiffres (par exemple : #112233). Comme un objet teinte, saturation, valeur (par exemple : {h: 60, s: 1, v: }). -Comme un tableau RGB (par exemple : [255, 128, 64]). Ou, comme un tableau RGBA (par exemple : [127, 200, 75, 0.3]).

-

Le plus simple pour notre objectif est d'utiliser la version chaîne hexadécimale, car de cette façon, -lil-gui ne manipule qu'une seule valeur. Heureusement, THREE.Color -dispose d'une méthode getHexString que nous pouvons utiliser pour obtenir facilement une telle chaîne, -il suffit de faire précéder d'un '#' au début.

-
// Nous utilisons cette classe pour la passer à lil-gui
-// ainsi quand elle manipule near ou far
-// near n'est jamais > far et far n'est jamais < near
-// Aussi, lorsque lil-gui manipule la couleur, nous allons
-// mettre à jour les couleurs du brouillard et de l'arrière-plan.
-class FogGUIHelper {
-*  constructor(fog, backgroundColor) {
-    this.fog = fog;
-+    this.backgroundColor = backgroundColor;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-+  get color() {
-+    return `#${this.fog.color.getHexString()}`;
-+  }
-+  set color(hexString) {
-+    this.fog.color.set(hexString);
-+    this.backgroundColor.set(hexString);
-+  }
-}
-
-

Nous appelons ensuite gui.addColor pour ajouter une interface utilisateur de couleur pour la propriété virtuelle de notre assistant.

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-
-*  const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
-  gui.add(fogGUIHelper, 'near', near, far).listen();
-  gui.add(fogGUIHelper, 'far', near, far).listen();
-+  gui.addColor(fogGUIHelper, 'color');
-}
-
-

- -

-

Vous pouvez voir que régler near à environ 1.9 et far à 2.0 donne -une transition très nette entre non-brouillardé et complètement brouillardé. -tandis que near = 1.1 et far = 2.9 devraient être à peu près -les plus lisses étant donné que nos cubes tournent à 2 unités de distance de la caméra.

-

Une dernière chose, il existe une propriété booléenne fog -sur un matériau indiquant si les objets rendus -avec ce matériau sont affectés par le brouillard. Elle est par défaut à true -pour la plupart des matériaux. À titre d'exemple de pourquoi vous pourriez vouloir -désactiver le brouillard, imaginez que vous créez un simulateur de véhicule 3D -avec une vue depuis le siège du conducteur ou le cockpit. -Vous voudrez probablement désactiver le brouillard pour tout ce qui se trouve à l'intérieur du véhicule lorsque -vous regardez depuis l'intérieur du véhicule.

-

Un meilleur exemple pourrait être une maison -et un brouillard épais à l'extérieur. Disons que le brouillard est configuré pour commencer -à 2 mètres de distance (near = 2) et complètement brouillardé à 4 mètres (far = 4). -Les pièces sont plus longues que 2 mètres et la maison est probablement plus longue -que 4 mètres, vous devez donc régler les matériaux de l'intérieur -de la maison pour ne pas appliquer de brouillard, sinon, en vous tenant à l'intérieur -de la maison et en regardant dehors le mur au fond de la pièce, cela aura l'air -d'être dans le brouillard.

-
-
-
-
brouillard : vrai, tout
-
-
- -

Remarquez que les murs et le plafond au fond de la pièce sont affectés par le brouillard. -En désactivant le brouillard sur les matériaux de la maison, nous pouvons corriger ce problème.

-
-
-
-
brouillard : vrai, seulement les matériaux extérieurs
-
-
- -

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/fundamentals.html b/manual/fr/fundamentals.html deleted file mode 100644 index 59d9b16f8767d6..00000000000000 --- a/manual/fr/fundamentals.html +++ /dev/null @@ -1,449 +0,0 @@ - - - Principes fondamentaux - - - - - - - - - - - - - -
-
-

Principes fondamentaux

-
-
-
-

Ceci est le premier article d'une série d'articles sur three.js. -Three.js est une bibliothèque 3D qui essaie de rendre -aussi facile que possible l'affichage de contenu 3D sur une page web.

-

Three.js est souvent confondu avec WebGL car la plupart du temps, -mais pas toujours, three.js utilise WebGL pour dessiner en 3D. -WebGL est un système de très bas niveau qui ne dessine que des points, des lignes et des triangles. -Pour faire quoi que ce soit d'utile avec WebGL, cela nécessite généralement beaucoup de -code et c'est là que three.js intervient. Il gère des choses -comme les scènes, les lumières, les ombres, les matériaux, les textures, les mathématiques 3D, -toutes choses que vous auriez à écrire vous-même si vous utilisiez WebGL directement.

-

Ces tutoriels supposent que vous connaissez déjà JavaScript et, pour la -plupart, ils utiliseront le style ES6. Voir ici pour une -liste concise des choses que vous êtes censé déjà connaître. -La plupart des navigateurs qui supportent three.js sont mis à jour automatiquement, donc la plupart des utilisateurs -devraient pouvoir exécuter ce code. Si vous souhaitez faire fonctionner ce code -sur de très vieux navigateurs, penchez-vous sur un transpiler comme Babel. -Bien sûr, les utilisateurs qui exécutent de très vieux navigateurs ont probablement des machines -qui ne peuvent pas exécuter three.js.

-

Lors de l'apprentissage de la plupart des langages de programmation, la première chose que les gens -font est de faire afficher "Hello World!" par l'ordinateur. Pour la 3D, -l'une des premières choses les plus courantes à faire est de créer un cube 3D. -Alors commençons par "Hello Cube !"

-

Avant de commencer, essayons de vous donner une idée de la structure -d'une application three.js. Une application three.js vous demande de créer un tas -d'objets et de les connecter ensemble. Voici un diagramme qui représente -une petite application three.js

-
- -

Points à noter concernant le diagramme ci-dessus.

-
    -
  • Il y a un Renderer. C'est sans doute l'objet principal de three.js. Vous passez une -Scene et une Camera à un Renderer et il rend (dessine) la partie -de la scène 3D qui se trouve à l'intérieur du frustum de la caméra en tant qu'image 2D sur un -canevas.

    -
  • -
  • Il y a un graphe de scène (scenegraph) qui est une structure arborescente, -composée de divers objets comme un objet Scene, plusieurs objets -Mesh, des objets Light, Group, Object3D, et des objets Camera. Un -objet Scene définit la racine du graphe de scène et contient des propriétés -comme la couleur de fond et le brouillard. Ces objets définissent une structure arborescente -hiérarchique parent/enfant et représentent où les objets apparaissent et comment ils sont -orientés. Les enfants sont positionnés et orientés par rapport à leur parent. Par -exemple, les roues d'une voiture pourraient être les enfants de la voiture de sorte que déplacer et -orienter l'objet voiture déplace automatiquement les roues. Vous pouvez en savoir plus -à ce sujet dans l'article sur les graphes de scène.

    -

    Notez dans le diagramme que la Camera est à moitié dedans et à moitié dehors du graphe de scène. Cela représente -qu'en three.js, contrairement aux autres objets, une Camera n'a pas besoin -d'être dans le graphe de scène pour fonctionner. Tout comme les autres objets, une Camera, en tant -qu'enfant d'un autre objet, se déplacera et s'orientera par rapport à son objet parent. -Il y a un exemple de mise en place de plusieurs objets Camera dans un graphe de scène à -la fin de l'article sur les graphes de scène.

    -
  • -
  • Les objets Mesh représentent le dessin d'une Geometry spécifique avec un - Material spécifique.

    -

    Les objets Material et les objets Geometry peuvent être utilisés par - plusieurs objets Mesh. Par exemple, pour dessiner deux cubes bleus à différents - endroits, nous aurions besoin de deux objets Mesh pour représenter la position et - l'orientation de chaque cube. Nous n'aurions besoin que d'une seule Geometry pour stocker les - données de sommet d'un cube et nous n'aurions besoin que d'un seul Material pour spécifier la couleur - bleue. Les deux objets Mesh pourraient référencer le même objet Geometry et le - même objet Material.

    -
  • -
  • Les objets Geometry représentent les données de sommet d'une pièce de géométrie - comme une sphère, un cube, un plan, un chien, un chat, un humain, un arbre, un bâtiment, etc... - Three.js fournit de nombreux types de - primitives de géométrie intégrées. Vous pouvez également - créer une géométrie personnalisée ainsi que - charger de la géométrie à partir de fichiers.

    -
  • -
  • Les objets Material représentent -les propriétés de surface utilisées pour dessiner la géométrie -y compris des choses comme la couleur à utiliser et à quel point elle est brillante. Un Material peut -également référencer un ou plusieurs objets Texture qui peuvent être utilisés, par exemple, -pour envelopper une image sur la surface d'une géométrie.

    -
  • -
  • Les objets Texture représentent généralement des images soit chargées à partir de fichiers image, -générées à partir d'un canevas, soit rendues à partir d'une autre scène.

    -
  • -
  • Les objets Light représentent différents types de lumières.

    -
  • -
-

Étant donné tout cela, nous allons créer la configuration *« Hello Cube »* la plus simple -qui ressemble à ceci

-
- -

Tout d'abord, chargeons three.js

-
<script type="module">
-import * as THREE from 'three';
-</script>
-
-

Il est important de mettre type="module" dans la balise script. Cela nous permet -d'utiliser le mot-clé import pour charger three.js. À partir de r147, c'est la -seule façon de charger properly three.js. Les modules ont l'avantage de pouvoir facilement -importer d'autres modules dont ils ont besoin. Cela nous évite d'avoir à -charger manuellement les scripts supplémentaires dont ils dépendent.

-

Ensuite, nous avons besoin d'une balise <canvas>, donc...

-
<body>
-  <canvas id="c"></canvas>
-</body>
-
-

Nous allons demander à three.js de dessiner dans ce canevas, nous devons donc le rechercher.

-
<script type="module">
-import * as THREE from 'three';
-
-+function main() {
-+  const canvas = document.querySelector('#c');
-+  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  ...
-</script>
-
-

Après avoir trouvé le canevas, nous créons un WebGLRenderer. Le renderer -est la chose responsable de prendre toutes les données que vous fournissez -et de les rendre sur le canevas.

-

Notez qu'il y a quelques détails ésotériques ici. Si vous ne passez pas de canevas -à three.js, il en créera un pour vous, mais vous devrez ensuite l'ajouter -à votre document. L'endroit où l'ajouter peut changer en fonction de votre cas d'utilisation -et vous devrez changer votre code. Je trouve que passer un canevas -à three.js est un peu plus flexible. Je peux placer le canevas n'importe où -et le code le trouvera, alors que si j'avais du code pour insérer le canevas -dans le document, je devrais probablement changer ce code si mon cas d'utilisation changeait.

-

Ensuite, nous avons besoin d'une caméra. Nous allons créer une PerspectiveCamera.

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

fov est l'abréviation de field of view (champ de vision). Dans ce cas, 75 degrés dans la dimension verticale. -Notez que la plupart des angles en three.js sont en radians, mais pour une raison quelconque, la caméra perspective prend des degrés.

-

aspect est le rapport d'aspect (display aspect) du canevas. Nous aborderons les détails -dans un autre article mais par défaut, un canevas est -de 300x150 pixels, ce qui donne un rapport d'aspect de 300/150, soit 2.

-

near et far représentent l'espace devant la caméra -qui sera rendu. Tout ce qui se trouve avant cette plage ou après cette plage -sera écrêté (non dessiné).

-

Ces quatre paramètres définissent un *« frustum »*.

-

Un *frustum* est le nom d'une forme 3D qui ressemble à une pyramide dont la pointe est tranchée.

-

En d'autres termes, considérez le mot "frustum" comme une autre forme 3D comme une sphère, -un cube, un prisme, un frustum.

-

-

La hauteur des plans near et far est déterminée par le champ de vision. -La largeur des deux plans est déterminée par le champ de vision et l'aspect.

-

Tout ce qui se trouve à l'intérieur du frustum défini sera dessiné. Tout ce qui se trouve à l'extérieur -ne le sera pas.

-

La caméra est orientée par défaut vers l'axe -Z avec +Y vers le haut. Nous allons placer notre cube -à l'origine, nous devons donc reculer légèrement la caméra par rapport à l'origine -afin de voir quelque chose.

-
camera.position.z = 2;
-
-

Voici ce que nous visons.

-

-

Dans le diagramme ci-dessus, nous pouvons voir que notre caméra est à z = 2. Elle regarde -vers l'axe -Z. Notre frustum commence à 0.1 unité de l'avant de la caméra -et va jusqu'à 5 unités devant la caméra. Parce que dans ce diagramme nous regardons vers le bas, -le champ de vision est affecté par l'aspect. Notre canevas est deux fois plus large -qu'il n'est haut, donc sur la largeur du canevas, le champ de vision sera beaucoup plus large que -nos 75 degrés spécifiés, qui correspondent au champ de vision vertical.

-

Ensuite, nous créons une Scene. Une Scene dans three.js est la racine d'une forme de graphe de scène. -Tout ce que vous voulez que three.js dessine doit être ajouté à la scène. Nous allons -couvrir plus de détails sur le fonctionnement des scènes dans un futur article.

-
const scene = new THREE.Scene();
-
-

Ensuite, nous créons une BoxGeometry qui contient les données pour une boîte. -Presque tout ce que nous voulons afficher dans Three.js nécessite une géométrie qui définit -les sommets qui composent notre objet 3D.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-

Nous créons ensuite un matériau de base et définissons sa couleur. Les couleurs peuvent -être spécifiées en utilisant les valeurs hexadécimales à 6 chiffres de style CSS standard.

-
const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
-
-

Nous créons ensuite un Mesh. Un Mesh en three.js représente la combinaison -de trois choses

-
    -
  1. Une Geometry (la forme de l'objet)
  2. -
  3. Un Material (comment dessiner l'objet, brillant ou plat, quelle couleur, quelle(s) texture(s) appliquer. Etc.)
  4. -
  5. La position, l'orientation et l'échelle de cet objet dans la scène par rapport à son parent. Dans le code ci-dessous, ce parent est la scène.
  6. -
-
const cube = new THREE.Mesh(geometry, material);
-
-

Et enfin, nous ajoutons ce maillage à la scène

-
scene.add(cube);
-
-

Nous pouvons ensuite rendre la scène en appelant la fonction de rendu du renderer -et en lui passant la scène et la caméra

-
renderer.render(scene, camera);
-
-

Voici un exemple fonctionnel

-

- -

-

Il est un peu difficile de voir qu'il s'agit d'un cube 3D puisque nous le visualisons -directement le long de l'axe -Z et que le cube lui-même est aligné sur les axes, -donc nous ne voyons qu'une seule face.

-

Animons-le en rotation et, espérons-le, cela montrera -clairement qu'il est dessiné en 3D. Pour l'animer, nous allons le rendre dans une boucle de rendu en utilisant -requestAnimationFrame.

-

Voici notre boucle

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cube.rotation.x = time;
-  cube.rotation.y = time;
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

requestAnimationFrame est une requête au navigateur indiquant que vous souhaitez animer quelque chose. -Vous lui passez une fonction à appeler. Dans notre cas, cette fonction est render. Le navigateur -appellera votre fonction et si vous mettez à jour quoi que ce soit lié à l'affichage de la -page, le navigateur re-rendrera la page. Dans notre cas, nous appelons la fonction -renderer.render de three, qui dessinera notre scène.

-

requestAnimationFrame passe le temps écoulé depuis le chargement de la page -à notre fonction. Ce temps est exprimé en millisecondes. Je trouve beaucoup -plus facile de travailler avec des secondes, donc ici nous convertissons cela en secondes.

-

Nous définissons ensuite les rotations X et Y du cube à l'heure actuelle. Ces rotations -sont en radians. Il y a 2 pi radians -dans un cercle, donc notre cube devrait faire un tour sur chaque axe en environ 6,28 -secondes.

-

Nous rendons ensuite la scène et demandons une autre frame d'animation pour continuer -notre boucle.

-

En dehors de la boucle, nous appelons requestAnimationFrame une seule fois pour démarrer la boucle.

-

- -

-

C'est un peu mieux, mais il est toujours difficile de voir le 3D. Ce qui aiderait, -c'est d'ajouter un peu d'éclairage, alors ajoutons une lumière. Il existe de nombreux types de lumières dans -three.js que nous aborderons dans un futur article. Pour l'instant, créons une lumière directionnelle.

-
const color = 0xFFFFFF;
-const intensity = 3;
-const light = new THREE.DirectionalLight(color, intensity);
-light.position.set(-1, 2, 4);
-scene.add(light);
-
-

Les lumières directionnelles ont une position et une cible. Les deux sont par défaut à 0, 0, 0. Dans notre -cas, nous définissons la position de la lumière à -1, 2, 4, de sorte qu'elle est légèrement sur la gauche, -au-dessus et derrière notre caméra. La cible est toujours 0, 0, 0, elle brillera donc -vers l'origine.

-

Nous devons également changer le matériau. Le MeshBasicMaterial n'est pas affecté par -les lumières. Changeons-le pour un MeshPhongMaterial qui est affecté par les lumières.

-
-const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
-+const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
-
-

Voici la structure de notre nouveau programme

-
- -

Et le voici en fonctionnement.

-

- -

-

Maintenant, il devrait être assez clairement en 3D.

-

Juste pour le plaisir, ajoutons 2 cubes de plus.

-

Nous utiliserons la même géométrie pour chaque cube mais créerons un matériau différent -afin que chaque cube puisse avoir une couleur différente.

-

Tout d'abord, nous allons créer une fonction qui crée un nouveau matériau -avec la couleur spécifiée. Ensuite, elle crée un maillage en utilisant -la géométrie spécifiée et l'ajoute à la scène et -définit sa position en X.

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-

Ensuite, nous l'appellerons 3 fois avec 3 couleurs et positions X différentes -en stockant les instances Mesh dans un tableau.

-
const cubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

Enfin, nous allons faire tourner les 3 cubes dans notre fonction de rendu. Nous -calculons une rotation légèrement différente pour chacun.

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  ...
-
-

et voici le résultat.

-

- -

-

Si vous le comparez au diagramme vu de dessus ci-dessus, vous pouvez voir -qu'il correspond à nos attentes.

-

Avec les cubes à X = -2 et X = +2, ils sont partiellement en dehors de notre frustum.

-

Ils sont également quelque peu exagérément déformés car le champ de vision -à travers le canevas est si extrême.

-

Notre programme a maintenant cette structure

-
- -

Comme vous pouvez le voir, nous avons 3 objets Mesh, chacun référençant la même BoxGeometry. -Chaque Mesh référence un MeshPhongMaterial unique afin que chaque cube puisse avoir -une couleur différente.

-

J'espère que cette courte introduction vous aidera à démarrer. Ensuite, nous verrons -comment rendre notre code réactif afin qu'il soit adaptable à plusieurs situations.

-
-

modules es6, three.js et structure de dossiers

-

À partir de la version r147, la manière préférée d'utiliser three.js est via les modules es6 et les cartes d'importation (import maps).

-

-Les modules es6 peuvent être chargés via le mot-clé import dans un script -ou en ligne via une balise <script type="module">. Voici un exemple -

-
<script type="module">
-import * as THREE from 'three';
-
-...
-
-</script>
-
-

-Notez le spécificateur 'three' ici. Si vous le laissez tel quel, il produira probablement une erreur. Une *carte d'importation* doit être utilisée pour indiquer au navigateur où trouver three.js -

-
<script type="importmap">
-{
-  "imports": {
-    "three": "./path/to/three.module.js"
-  }
-}
-</script>
-
-

-Notez que le spécificateur de chemin ne peut commencer qu'avec ./ ou ../. -

-

-Pour importer des extensions (addons) comme OrbitControls.js, utilisez ce qui suit -

-
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-

-N'oubliez pas d'ajouter les extensions (addons) à la carte d'importation comme ceci -

-
<script type="importmap">
-{
-  "imports": {
-    "three": "./path/to/three.module.js",
-    "three/addons/": "./different/path/to/examples/jsm/"
-  }
-}
-</script>
-
-

-Vous pouvez également utiliser un CDN -

-
<script type="importmap">
-{
-  "imports": {
-    "three": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.module.js",
-    "three/addons/": "https://cdn.jsdelivr.net/npm/three@<version>/examples/jsm/"
-  }
-}
-</script>
-
-

-En conclusion, la manière recommandée d'utiliser three.js est -

-
-<script type="importmap">
-{
-  "imports": {
-    "three": "./path/to/three.module.js",
-    "three/addons/": "./different/path/to/examples/jsm/"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-...
-
-</script>
-
-
- - -

-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/game.html b/manual/fr/game.html deleted file mode 100644 index 21b96c6d2c2823..00000000000000 --- a/manual/fr/game.html +++ /dev/null @@ -1,1756 +0,0 @@ - - - Créer un jeu - - - - - - - - - - - - - -
-
-

Créer un jeu

-
-
-
-

Beaucoup de gens veulent écrire des jeux en utilisant three.js. Cet article -vous donnera, je l'espère, quelques idées sur la façon de commencer.

-

Au moment où j'écris cet article, il s'agit probablement de l'article le plus long de ce site. -Il est possible que le code ici soit massivement sur-conçu, mais à mesure que j'écrivais chaque nouvelle fonctionnalité, je rencontrais un problème qui nécessitait une solution à laquelle je suis habitué depuis d'autres jeux que j'ai écrits. -En d'autres termes, chaque nouvelle solution semblait importante, je vais donc essayer de montrer pourquoi. -Bien sûr, plus votre jeu est petit, moins vous pourriez avoir besoin de certaines des solutions présentées ici, mais il s'agit d'un jeu assez petit et pourtant, avec les complexités des personnages 3D, beaucoup de choses demandent plus d'organisation qu'elles ne le feraient avec des personnages 2D.

-

Par exemple, si vous créez PacMan en 2D, lorsque PacMan tourne dans un coin, -cela se produit instantanément à 90 degrés. Il n'y a pas d'étape intermédiaire. -Mais dans un jeu 3D, nous avons souvent besoin que le personnage pivote sur plusieurs images. -Ce simple changement peut ajouter beaucoup de complexité et nécessiter des solutions différentes.

-

La majorité du code ici ne sera pas vraiment three.js et -c'est important à noter, three.js n'est pas un moteur de jeu. -Three.js est une bibliothèque 3D. Elle fournit un graphe de scène -et des fonctionnalités pour afficher les objets 3D ajoutés à ce graphe de scène, -mais elle ne fournit pas toutes les autres choses nécessaires pour créer un jeu. -Pas de collisions, pas de physique, pas de systèmes d'entrée, pas de recherche de chemin, etc., etc... -Donc, nous devrons fournir ces choses nous-mêmes.

-

J'ai fini par écrire pas mal de code pour créer cette simple chose inachevée -ressemblant à un jeu, et encore une fois, il est certainement possible que j'aie sur-conçu -et qu'il existe des solutions plus simples, mais j'ai l'impression de ne pas avoir écrit -assez de code et j'espère pouvoir expliquer ce qui, à mon avis, manque.

-

Beaucoup des idées ici sont fortement influencées par Unity. -Si vous n'êtes pas familier avec Unity, cela n'a probablement pas d'importance. -Je n'en parle que parce que des dizaines de milliers de jeux ont été publiés en utilisant -ces idées.

-

Commençons par les parties three.js. Nous devons charger des modèles pour notre jeu.

-

Sur opengameart.org j'ai trouvé ce modèle de chevalier -animé par quaternius

-
- -

quaternius a également créé ces animaux animés.

-
- -

Ceux-ci semblent être de bons modèles pour commencer, donc la première chose à -faire est de les charger.

-

Nous avons abordé le chargement de fichiers glTF auparavant. -La différence cette fois est que nous devons charger plusieurs modèles et -nous ne pouvons pas démarrer le jeu tant que tous les modèles ne sont pas chargés.

-

Heureusement, three.js fournit le LoadingManager juste à cette fin. -Nous créons un LoadingManager et le passons aux autres chargeurs. Le -LoadingManager fournit à la fois les propriétés onProgress et -onLoad auxquelles nous pouvons attacher des callbacks. -Le callback onLoad sera appelé lorsque -tous les fichiers auront été chargés. Le callback onProgress -est appelé après l'arrivée de chaque fichier individuel pour nous donner une chance de montrer -la progression du chargement.

-

En partant du code de chargement d'un fichier glTF, j'ai supprimé tout -le code lié au cadrage de la scène et ajouté ce code pour charger tous les modèles.

-
const manager = new THREE.LoadingManager();
-manager.onLoad = init;
-const models = {
-  pig:    { url: 'resources/models/animals/Pig.gltf' },
-  cow:    { url: 'resources/models/animals/Cow.gltf' },
-  llama:  { url: 'resources/models/animals/Llama.gltf' },
-  pug:    { url: 'resources/models/animals/Pug.gltf' },
-  sheep:  { url: 'resources/models/animals/Sheep.gltf' },
-  zebra:  { url: 'resources/models/animals/Zebra.gltf' },
-  horse:  { url: 'resources/models/animals/Horse.gltf' },
-  knight: { url: 'resources/models/knight/KnightCharacter.gltf' },
-};
-{
-  const gltfLoader = new GLTFLoader(manager);
-  for (const model of Object.values(models)) {
-    gltfLoader.load(model.url, (gltf) => {
-      model.gltf = gltf;
-    });
-  }
-}
-
-function init() {
-  // TBD
-}
-
-

Ce code chargera tous les modèles ci-dessus et le LoadingManager appellera -init une fois terminé. Nous utiliserons l'objet models plus tard pour accéder aux -modèles chargés, de sorte que le callback du GLTFLoader pour chaque modèle individuel attache -les données chargées aux informations de ce modèle.

-

Tous les modèles avec toutes leurs animations font actuellement environ 6,6 Mo. C'est un -téléchargement assez important. En supposant que votre serveur prenne en charge la compression (ce qui est le cas du serveur sur lequel ce site fonctionne), il peut les compresser à environ 1,4 Mo. C'est -nettement mieux que 6,6 Mo, mais ce n'est toujours pas une petite quantité de données. Il serait -probablement bon d'ajouter une barre de progression pour que l'utilisateur ait une idée du temps qu'il -lui reste à attendre.

-

Alors, ajoutons un callback onProgress. Il sera -appelé avec 3 arguments : l'url du dernier objet chargé, puis le nombre -d'éléments chargés jusqu'à présent, ainsi que le nombre total d'éléments.

-

Mettons en place du code HTML pour une barre de chargement

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="loading">
-+    <div>
-+      <div>...chargement...</div>
-+      <div class="progress"><div id="progressbar"></div></div>
-+    </div>
-+  </div>
-</body>
-
-

Nous allons rechercher la div #progressbar et nous pourrons définir la largeur de 0 % à 100 % -pour montrer notre progression. Tout ce que nous avons à faire est de définir cela dans notre callback.

-
const manager = new THREE.LoadingManager();
-manager.onLoad = init;
-
-+const progressbarElem = document.querySelector('#progressbar');
-+manager.onProgress = (url, itemsLoaded, itemsTotal) => {
-+  progressbarElem.style.width = `${itemsLoaded / itemsTotal * 100 | 0}%`;
-+};
-
-

Nous avons déjà configuré init pour être appelé lorsque tous les modèles sont chargés, nous pouvons donc -désactiver la barre de progression en masquant l'élément #loading.

-
function init() {
-+  // masquer la barre de chargement
-+  const loadingElem = document.querySelector('#loading');
-+  loadingElem.style.display = 'none';
-}
-
-

Voici un tas de CSS pour styler la barre. Le CSS rend la #loading <div> -de la taille totale de la page et centre ses enfants. Le CSS crée une zone .progress -pour contenir la barre de progression. Le CSS donne également à la barre de progression -une animation CSS de rayures diagonales.

-
#loading {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  text-align: center;
-  font-size: xx-large;
-  font-family: sans-serif;
-}
-#loading>div>div {
-  padding: 2px;
-}
-.progress {
-  width: 50vw;
-  border: 1px solid black;
-}
-#progressbar {
-  width: 0;
-  transition: width ease-out .5s;
-  height: 1em;
-  background-color: #888;
-  background-image: linear-gradient(
-    -45deg,
-    rgba(255, 255, 255, .5) 25%,
-    transparent 25%,
-    transparent 50%,
-    rgba(255, 255, 255, .5) 50%,
-    rgba(255, 255, 255, .5) 75%,
-    transparent 75%,
-    transparent
-  );
-  background-size: 50px 50px;
-  animation: progressanim 2s linear infinite;
-}
-
-@keyframes progressanim {
-  0% {
-    background-position: 50px 50px;
-  }
-  100% {
-    background-position: 0 0;
-  }
-}
-
-

Maintenant que nous avons une barre de progression, occupons-nous des modèles. Ces modèles -ont des animations et nous voulons pouvoir y accéder. -Les animations sont stockées dans un tableau par défaut, mais nous aimerions pouvoir y accéder -facilement par leur nom. Configurons donc une propriété animations pour -chaque modèle afin de faire cela. Notez bien sûr que cela signifie que les animations doivent avoir des noms uniques.

-
+function prepModelsAndAnimations() {
-+  Object.values(models).forEach(model => {
-+    const animsByName = {};
-+    model.gltf.animations.forEach((clip) => {
-+      animsByName[clip.name] = clip;
-+    });
-+    model.animations = animsByName;
-+  });
-+}
-
-function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-+  prepModelsAndAnimations();
-}
-
-

Affichons les modèles animés.

-

Contrairement à l'exemple précédent de chargement d'un fichier glTF, -cette fois-ci, nous voulons probablement pouvoir afficher plus d'une instance -de chaque modèle. Pour ce faire, au lieu d'ajouter -directement la scène glTF chargée, comme nous l'avons fait dans l'article sur le chargement d'un glTF, -nous voulons plutôt cloner la scène et, en particulier, nous voulons la cloner -pour les personnages animés avec skinning. Heureusement, il existe une fonction utilitaire, -SkeletonUtils.clone, que nous pouvons utiliser pour cela. Donc, nous devons d'abord inclure -les utilitaires.

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
-+import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';
-
-

Ensuite, nous pouvons cloner les modèles que nous venons de charger

-
function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-+  Object.values(models).forEach((model, ndx) => {
-+    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-+    const root = new THREE.Object3D();
-+    root.add(clonedScene);
-+    scene.add(root);
-+    root.position.x = (ndx - 3) * 3;
-+  });
-}
-
-

Ci-dessus, pour chaque modèle, nous clonons la gltf.scene que nous avons chargée et -nous en faisons l'enfant d'un nouveau Object3D. Nous devons l'attacher à un autre objet, -car lorsque nous jouons des animations, l'animation appliquera des positions animées aux nœuds -de la scène chargée, ce qui signifie que nous n'aurons pas le contrôle sur ces positions.

-

Pour jouer les animations, chaque modèle que nous clonons a besoin d'un AnimationMixer. -Un AnimationMixer contient 1 ou plusieurs AnimationActions. Une -AnimationAction référence un AnimationClip. Les AnimationActions -ont toutes sortes de paramètres pour jouer, puis enchaîner avec une autre -action ou faire un crossfade entre les actions. Prenons simplement le premier -AnimationClip et créons une action pour celui-ci. La valeur par défaut est qu'une -action joue son clip en boucle indéfiniment.

-
+const mixers = [];
-
-function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-  Object.values(models).forEach((model, ndx) => {
-    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-    const root = new THREE.Object3D();
-    root.add(clonedScene);
-    scene.add(root);
-    root.position.x = (ndx - 3) * 3;
-
-+    const mixer = new THREE.AnimationMixer(clonedScene);
-+    const firstClip = Object.values(model.animations)[0];
-+    const action = mixer.clipAction(firstClip);
-+    action.play();
-+    mixers.push(mixer);
-  });
-}
-
-

Nous avons appelé play pour démarrer l'action et stocké -tous les AnimationMixers dans un tableau appelé mixers. Enfin, -nous devons mettre à jour chaque AnimationMixer dans notre boucle de rendu en calculant -le temps écoulé depuis la dernière image et en le passant à AnimationMixer.update.

-
+let then = 0;
-function render(now) {
-+  now *= 0.001;  // convertir en secondes
-+  const deltaTime = now - then;
-+  then = now;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  for (const mixer of mixers) {
-+    mixer.update(deltaTime);
-+  }
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

Et avec cela, chaque modèle devrait être chargé et jouer sa première animation.

-

- -

-

Faisons en sorte que nous puissions vérifier toutes les animations. -Nous ajouterons tous les clips en tant qu'actions, puis nous n'en activerons qu'un -seul à la fois.

-
-const mixers = [];
-+const mixerInfos = [];
-
-function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-  Object.values(models).forEach((model, ndx) => {
-    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-    const root = new THREE.Object3D();
-    root.add(clonedScene);
-    scene.add(root);
-    root.position.x = (ndx - 3) * 3;
-
-    const mixer = new THREE.AnimationMixer(clonedScene);
--    const firstClip = Object.values(model.animations)[0];
--    const action = mixer.clipAction(firstClip);
--    action.play();
--    mixers.push(mixer);
-+    const actions = Object.values(model.animations).map((clip) => {
-+      return mixer.clipAction(clip);
-+    });
-+    const mixerInfo = {
-+      mixer,
-+      actions,
-+      actionNdx: -1,
-+    };
-+    mixerInfos.push(mixerInfo);
-+    playNextAction(mixerInfo);
-  });
-}
-
-+function playNextAction(mixerInfo) {
-+  const {actions, actionNdx} = mixerInfo;
-+  const nextActionNdx = (actionNdx + 1) % actions.length;
-+  mixerInfo.actionNdx = nextActionNdx;
-+  actions.forEach((action, ndx) => {
-+    const enabled = ndx === nextActionNdx;
-+    action.enabled = enabled;
-+    if (enabled) {
-+      action.play();
-+    }
-+  });
-+}
-
-

Le code ci-dessus crée un tableau de AnimationActions, -une pour chaque AnimationClip. Il crée un tableau d'objets, mixerInfos, -avec des références au AnimationMixer et à toutes les AnimationActions -pour chaque modèle. Il appelle ensuite playNextAction qui définit la propriété enabled à -l'exception d'une seule action pour ce mixeur.

-

Nous devons mettre à jour la boucle de rendu pour le nouveau tableau

-
-for (const mixer of mixers) {
-+for (const {mixer} of mixerInfos) {
-  mixer.update(deltaTime);
-}
-
-

Faisons en sorte qu'en appuyant sur une touche de 1 à 8, l'animation suivante soit jouée -pour chaque modèle

-
window.addEventListener('keydown', (e) => {
-  const mixerInfo = mixerInfos[e.keyCode - 49];
-  if (!mixerInfo) {
-    return;
-  }
-  playNextAction(mixerInfo);
-});
-
-

Maintenant, vous devriez pouvoir cliquer sur l'exemple, puis appuyer sur les touches 1 à 8 -pour faire défiler chaque modèle à travers ses animations disponibles.

-

- -

-

On peut donc dire que c'est la somme totale de la partie three.js de cet article. -Nous avons abordé le chargement de plusieurs fichiers, le clonage de modèles skinnés, -et la lecture d'animations sur ceux-ci. Dans un vrai jeu, vous auriez beaucoup plus -de manipulations à faire sur les objets AnimationAction.

-

Commençons à créer une infrastructure de jeu

-

Un modèle courant pour créer un jeu moderne est d'utiliser un -Entity Component System. -Dans un Entity Component System, un objet dans un jeu est appelé une entité qui -se compose d'un ensemble de composants. Vous construisez des entités en décidant quels composants -leur attacher. Alors, créons un Entity Component System.

-

Nous appellerons nos entités GameObject. C'est effectivement juste une collection -de composants et un Object3D de three.js.

-
function removeArrayElement(array, element) {
-  const ndx = array.indexOf(element);
-  if (ndx >= 0) {
-    array.splice(ndx, 1);
-  }
-}
-
-class GameObject {
-  constructor(parent, name) {
-    this.name = name;
-    this.components = [];
-    this.transform = new THREE.Object3D();
-    parent.add(this.transform);
-  }
-  addComponent(ComponentType, ...args) {
-    const component = new ComponentType(this, ...args);
-    this.components.push(component);
-    return component;
-  }
-  removeComponent(component) {
-    removeArrayElement(this.components, component);
-  }
-  getComponent(ComponentType) {
-    return this.components.find(c => c instanceof ComponentType);
-  }
-  update() {
-    for (const component of this.components) {
-      component.update();
-    }
-  }
-}
-
-

L'appel de GameObject.update appelle la fonction update sur tous les composants.

-

J'ai inclus un nom uniquement pour faciliter le débogage, de sorte que si j'examine un GameObject -dans le débogueur, je puisse voir un nom pour l'aider à l'identifier.

-

Quelques choses qui pourraient sembler un peu étranges :

-

GameObject.addComponent est utilisé pour créer des composants. Que ce -soit une bonne ou une mauvaise idée, je ne suis pas sûr. Ma pensée était qu'il n'a aucun sens -pour un composant d'exister en dehors d'un gameobject, alors j'ai pensé -qu'il pourrait être bon que la création d'un composant ajoute automatiquement ce composant -au gameobject et passe le gameobject au constructeur du composant. -En d'autres termes, pour ajouter un composant, vous faites ceci

-
const gameObject = new GameObject(scene, 'foo');
-gameObject.addComponent(TypeOfComponent);
-
-

Si je ne le faisais pas de cette façon, vous feriez plutôt quelque chose comme ceci

-
const gameObject = new GameObject(scene, 'foo');
-const component = new TypeOfComponent(gameObject);
-gameObject.addComponent(component);
-
-

Est-ce mieux que la première méthode soit plus courte et plus automatisée, ou est-ce pire -parce que cela sort de l'ordinaire ? Je ne sais pas.

-

GameObject.getComponent recherche les composants par type. Cela -implique que vous ne pouvez pas avoir 2 composants du même -type sur un seul objet de jeu, ou du moins si vous en avez, vous ne pouvez -rechercher que le premier sans ajouter une autre API.

-

Il est courant qu'un composant en recherche un autre, et lors de cette recherche, ils -doivent correspondre par type, sinon vous pourriez obtenir le mauvais. Nous pourrions à la place -donner un nom à chaque composant et vous pourriez les rechercher par leur nom. Ce serait -plus flexible car vous pourriez avoir plus d'un composant du même type, mais ce -serait aussi plus fastidieux. Encore une fois, je ne suis pas sûr de ce qui est le mieux.

-

Passons aux composants eux-mêmes. Voici leur classe de base.

-
// Base pour tous les composants
-class Component {
-  constructor(gameObject) {
-    this.gameObject = gameObject;
-  }
-  update() {
-  }
-}
-
-

Les composants ont-ils besoin d'une classe de base ? JavaScript n'est pas comme la plupart des langages strictement -typés, donc en pratique, nous pourrions ne pas avoir de classe de base et laisser -chaque composant faire ce qu'il veut dans son constructeur, sachant que le premier -argument est toujours le gameobject du composant. S'il ne se soucie pas du gameobject, il -ne le stockerait pas. J'ai un peu l'impression que cette base commune est bonne cependant. -Cela signifie que si vous avez une référence à un -composant, vous savez que vous pouvez toujours trouver son gameobject parent, et à partir de son -parent, vous pouvez facilement rechercher d'autres composants ainsi que regarder sa -transformation.

-

Pour gérer les gameobjects, nous avons probablement besoin d'une sorte de gestionnaire de gameobjects. Vous -pourriez penser que nous pourrions simplement garder un tableau de gameobjects, mais dans un vrai jeu, les -composants d'un gameobject pourraient ajouter et supprimer d'autres gameobjects pendant l'exécution. -Par exemple, un gameobject d'arme pourrait ajouter un gameobject de balle chaque fois que l'arme -tire. Un gameobject de monstre pourrait se supprimer s'il a été tué. Nous -aurions alors un problème : nous pourrions avoir du code comme ceci

-
for (const gameObject of globalArrayOfGameObjects) {
-  gameObject.update();
-}
-
-

La boucle ci-dessus échouerait ou ferait des choses inattendues si -des gameobjects étaient ajoutés ou supprimés de globalArrayOfGameObjects -au milieu de la boucle dans la fonction update d'un composant.

-

Pour essayer de prévenir ce problème, nous avons besoin de quelque chose d'un peu plus sûr. -Voici une tentative.

-
class SafeArray {
-  constructor() {
-    this.array = [];
-    this.addQueue = [];
-    this.removeQueue = new Set();
-  }
-  get isEmpty() {
-    return this.addQueue.length + this.array.length > 0;
-  }
-  add(element) {
-    this.addQueue.push(element);
-  }
-  remove(element) {
-    this.removeQueue.add(element);
-  }
-  forEach(fn) {
-    this._addQueued();
-    this._removeQueued();
-    for (const element of this.array) {
-      if (this.removeQueue.has(element)) {
-        continue;
-      }
-      fn(element);
-    }
-    this._removeQueued();
-  }
-  _addQueued() {
-    if (this.addQueue.length) {
-      this.array.splice(this.array.length, 0, ...this.addQueue);
-      this.addQueue = [];
-    }
-  }
-  _removeQueued() {
-    if (this.removeQueue.size) {
-      this.array = this.array.filter(element => !this.removeQueue.has(element));
-      this.removeQueue.clear();
-    }
-  }
-}
-
-

La classe ci-dessus vous permet d'ajouter ou de supprimer des éléments du SafeArray -sans altérer le tableau lui-même pendant qu'il est parcouru. Au lieu -de cela, les nouveaux éléments sont ajoutés à addQueue et les éléments supprimés -à removeQueue, puis ajoutés ou supprimés en dehors de la boucle.

-

En utilisant cela, voici notre classe pour gérer les gameobjects.

-
class GameObjectManager {
-  constructor() {
-    this.gameObjects = new SafeArray();
-  }
-  createGameObject(parent, name) {
-    const gameObject = new GameObject(parent, name);
-    this.gameObjects.add(gameObject);
-    return gameObject;
-  }
-  removeGameObject(gameObject) {
-    this.gameObjects.remove(gameObject);
-  }
-  update() {
-    this.gameObjects.forEach(gameObject => gameObject.update());
-  }
-}
-
-

Avec tout cela, créons maintenant notre premier composant. Ce composant -gérera simplement un objet three.js skinné comme ceux que nous venons de créer. -Pour rester simple, il n'aura qu'une seule méthode, setAnimation, qui -prend le nom de l'animation à jouer et la lance.

-
class SkinInstance extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-    this.model = model;
-    this.animRoot = SkeletonUtils.clone(this.model.gltf.scene);
-    this.mixer = new THREE.AnimationMixer(this.animRoot);
-    gameObject.transform.add(this.animRoot);
-    this.actions = {};
-  }
-  setAnimation(animName) {
-    const clip = this.model.animations[animName];
-    // turn off all current actions
-    for (const action of Object.values(this.actions)) {
-      action.enabled = false;
-    }
-    // get or create existing action for clip
-    const action = this.mixer.clipAction(clip);
-    action.enabled = true;
-    action.reset();
-    action.play();
-    this.actions[animName] = action;
-  }
-  update() {
-    this.mixer.update(globals.deltaTime);
-  }
-}
-
-

Vous pouvez voir qu'il s'agit essentiellement du code que nous avions auparavant qui clone la scène que nous avons chargée, -puis configure un AnimationMixer. setAnimation ajoute une AnimationAction pour un -AnimationClip particulier s'il n'existe pas déjà, et désactive toutes -les actions existantes.

-

Le code référence globals.deltaTime. Créons un objet globals

-
const globals = {
-  time: 0,
-  deltaTime: 0,
-};
-
-

Et mettons-le à jour dans la boucle de rendu

-
let then = 0;
-function render(now) {
-  // convertir en secondes
-  globals.time = now * 0.001;
-  // s'assurer que le temps delta n'est pas trop grand.
-  globals.deltaTime = Math.min(globals.time - then, 1 / 20);
-  then = globals.time;
-
-

La vérification ci-dessus pour s'assurer que deltaTime ne dépasse pas 1/20ème -de seconde est due au fait que, sinon, nous obtiendrions une valeur énorme pour deltaTime -si nous masquions l'onglet. Nous pourrions le masquer pendant des secondes ou des minutes, et ensuite, -lorsque notre onglet serait ramené au premier plan, deltaTime serait énorme -et pourrait téléporter des personnages à travers notre monde de jeu si nous avions du code comme

-
position += velocity * deltaTime;
-
-

En limitant le maximum deltaTime, ce problème est évité.

-

Créons maintenant un composant pour le joueur.

-
+const kForward = new THREE.Vector3(0, 0, 1);
-const globals = {
-  time: 0,
-  deltaTime: 0,
-+  moveSpeed: 16,
-};
-
-class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-    this.skinInstance = gameObject.addComponent(SkinInstance, model);
-    this.skinInstance.setAnimation('Run');
-+    this.turnSpeed = globals.moveSpeed / 4;
-  }
-+  update() {
-+    const {deltaTime, moveSpeed} = globals;
-+    const {transform} = this.gameObject;
-+    const delta = (inputManager.keys.left.down  ?  1 : 0) +
-+                  (inputManager.keys.right.down ? -1 : 0);
-+    transform.rotation.y += this.turnSpeed * delta * deltaTime;
-+    transform.translateOnAxis(kForward, moveSpeed * deltaTime);
-+  }
-}
-
-

Le code ci-dessus utilise Object3D.transformOnAxis pour faire avancer le joueur. -Object3D.transformOnAxis fonctionne dans l'espace local, il ne fonctionne donc que -si l'objet en question est à la racine de la scène, pas s'il est un enfant de quelque chose d'autre 1

-

Nous avons également ajouté une vitesse de déplacement globale (moveSpeed) et basé une vitesse de rotation (turnSpeed) sur la vitesse de déplacement. -La vitesse de rotation est basée sur la vitesse de déplacement pour essayer de s'assurer qu'un personnage -peut tourner assez brusquement pour atteindre sa cible. Si turnSpeed est trop faible, -un personnage tournera en rond autour de sa cible sans jamais l'atteindre. -Je n'ai pas pris la peine de faire les calculs pour déterminer la vitesse de rotation requise -pour une vitesse de déplacement donnée. J'ai juste deviné.

-

Le code jusqu'à présent fonctionnerait, mais si le joueur sort de l'écran, il n'y a -aucun moyen de savoir où il se trouve. Faisons en sorte que s'il est hors écran -pendant plus d'un certain temps, il soit téléporté à l'origine. -Nous pouvons le faire en utilisant la classe Frustum de three.js pour vérifier si un point -est à l'intérieur du frustum de vue de la caméra.

-

Nous devons construire un frustum à partir de la caméra. Nous pourrions le faire dans le composant Player, -mais d'autres objets pourraient vouloir l'utiliser également, alors ajoutons un autre -gameobject avec un composant pour gérer un frustum.

-
class CameraInfo extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    this.projScreenMatrix = new THREE.Matrix4();
-    this.frustum = new THREE.Frustum();
-  }
-  update() {
-    const {camera} = globals;
-    this.projScreenMatrix.multiplyMatrices(
-        camera.projectionMatrix,
-        camera.matrixWorldInverse);
-    this.frustum.setFromProjectionMatrix(this.projScreenMatrix);
-  }
-}
-
-

Configurons ensuite un autre gameobject au moment de l'initialisation.

-
function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-+  {
-+    const gameObject = gameObjectManager.createGameObject(camera, 'camera');
-+    globals.cameraInfo = gameObject.addComponent(CameraInfo);
-+  }
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-    gameObject.addComponent(Player);
-  }
-}
-
-

et maintenant nous pouvons l'utiliser dans le composant Player.

-
class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-    this.skinInstance = gameObject.addComponent(SkinInstance, model);
-    this.skinInstance.setAnimation('Run');
-    this.turnSpeed = globals.moveSpeed / 4;
-+    this.offscreenTimer = 0;
-+    this.maxTimeOffScreen = 3;
-  }
-  update() {
--    const {deltaTime, moveSpeed} = globals;
-+    const {deltaTime, moveSpeed, cameraInfo} = globals;
-    const {transform} = this.gameObject;
-    const delta = (inputManager.keys.left.down  ?  1 : 0) +
-                  (inputManager.keys.right.down ? -1 : 0);
-    transform.rotation.y += this.turnSpeed * delta * deltaTime;
-    transform.translateOnAxis(kForward, moveSpeed * deltaTime);
-
-+    const {frustum} = cameraInfo;
-+    if (frustum.containsPoint(transform.position)) {
-+      this.offscreenTimer = 0;
-+    } else {
-+      this.offscreenTimer += deltaTime;
-+      if (this.offscreenTimer >= this.maxTimeOffScreen) {
-+        transform.position.set(0, 0, 0);
-+      }
-+    }
-  }
-}
-
-

Une dernière chose avant d'essayer, ajoutons le support des écrans tactiles -pour mobile. Tout d'abord, ajoutons un peu de code HTML pour le toucher

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui">
-+    <div id="left"><img src="../resources/images/left.svg"></div>
-+    <div style="flex: 0 0 40px;"></div>
-+    <div id="right"><img src="../resources/images/right.svg"></div>
-+  </div>
-  <div id="loading">
-    <div>
-      <div>...chargement...</div>
-      <div class="progress"><div id="progressbar"></div></div>
-    </div>
-  </div>
-+  <div id="labels"></div>
-</body>
-
-

et un peu de CSS pour le styler

-
#ui {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-  justify-items: center;
-  align-content: stretch;
-}
-#ui>div {
-  display: flex;
-  align-items: flex-end;
-  flex: 1 1 auto;
-}
-.bright {
-  filter: brightness(2);
-}
-#left {
-  justify-content: flex-end;
-}
-#right {
-  justify-content: flex-start;
-}
-#ui img {
-  padding: 10px;
-  width: 80px;
-  height: 80px;
-  display: block;
-}
-#labels {
-  position: absolute;  /* nous permet de nous positionner à l'intérieur du conteneur */
-  left: 0;             /* fait que notre position est en haut à gauche du conteneur */
-  top: 0;
-  color: white;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  pointer-events: none;
-}
-#labels>div {
-  position: absolute;  /* nous permet de les positionner à l'intérieur du conteneur */
-  left: 0;             /* fait que leur position par défaut est en haut à gauche du conteneur */
-  top: 0;
-  font-size: large;
-  font-family: monospace;
-  user-select: none;   /* n'autorise pas la sélection du texte */
-  text-shadow:         /* crée un contour noir */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-
-

L'idée ici est d'avoir une div, #ui, qui -couvre toute la page. À l'intérieur, il y aura 2 divs, #left et #right, -chacune occupant près de la moitié de la largeur de la page et toute la hauteur de l'écran. -Entre les deux, il y a un séparateur de 40px. Si l'utilisateur glisse son doigt -sur le côté gauche ou droit, nous devons mettre à jour keys.left et keys.right -dans l'InputManager. Cela rend tout l'écran sensible au toucher, -ce qui semble mieux que de simples petites flèches.

-
class InputManager {
-  constructor() {
-    this.keys = {};
-    const keyMap = new Map();
-
-    const setKey = (keyName, pressed) => {
-      const keyState = this.keys[keyName];
-      keyState.justPressed = pressed && !keyState.down;
-      keyState.down = pressed;
-    };
-
-    const addKey = (keyCode, name) => {
-      this.keys[name] = { down: false, justPressed: false };
-      keyMap.set(keyCode, name);
-    };
-
-    const setKeyFromKeyCode = (keyCode, pressed) => {
-      const keyName = keyMap.get(keyCode);
-      if (!keyName) {
-        return;
-      }
-      setKey(keyName, pressed);
-    };
-
-    addKey(37, 'left');
-    addKey(39, 'right');
-    addKey(38, 'up');
-    addKey(40, 'down');
-    addKey(90, 'a');
-    addKey(88, 'b');
-
-    window.addEventListener('keydown', (e) => {
-      setKeyFromKeyCode(e.keyCode, true);
-    });
-    window.addEventListener('keyup', (e) => {
-      setKeyFromKeyCode(e.keyCode, false);
-    });
-
-+    const sides = [
-+      { elem: document.querySelector('#left'),  key: 'left'  },
-+      { elem: document.querySelector('#right'), key: 'right' },
-+    ];
-+
-+    const clearKeys = () => {
-+      for (const {key} of sides) {
-+          setKey(key, false);
-+      }
-+    };
-+
-+    const handleMouseMove = (e) => {
-+      e.preventDefault();
-+      // ceci est nécessaire car nous appelons preventDefault();
-+      // nous avons également donné au canvas un tabindex afin qu'il puisse
-+      // obtenir le focus
-+      canvas.focus();
-+      window.addEventListener('pointermove', handleMouseMove);
-+      window.addEventListener('pointerup', handleMouseUp);
-+
-+      for (const {elem, key} of sides) {
-+        let pressed = false;
-+        const rect = elem.getBoundingClientRect();
-+        const x = e.clientX;
-+        const y = e.clientY;
-+        const inRect = x >= rect.left && x < rect.right &&
-+                       y >= rect.top && y < rect.bottom;
-+        if (inRect) {
-+          pressed = true;
-+        }
-+        setKey(key, pressed);
-+      }
-+    };
-+
-+    function handleMouseUp() {
-+      clearKeys();
-+      window.removeEventListener('pointermove', handleMouseMove, {passive: false});
-+      window.removeEventListener('pointerup', handleMouseUp);
-+    }
-+
-+    const uiElem = document.querySelector('#ui');
-+    uiElem.addEventListener('pointerdown', handleMouseMove, {passive: false});
-+
-+    uiElem.addEventListener('touchstart', (e) => {
-+      // empêcher le défilement
-+      e.preventDefault();
-+    }, {passive: false});
-  }
-  update() {
-    for (const keyState of Object.values(this.keys)) {
-      if (keyState.justPressed) {
-        keyState.justPressed = false;
-      }
-    }
-  }
-}
-
-

Et maintenant, nous devrions pouvoir contrôler le personnage avec les touches curseur gauche et droite -ou avec nos doigts sur un écran tactile.

-

- -

-

Idéalement, nous ferions quelque chose d'autre si le joueur sortait de l'écran, comme déplacer -la caméra ou peut-être considérer que hors écran = mort, mais cet article va déjà être -trop long, donc pour l'instant, se téléporter au milieu était la chose la plus simple.

-

Ajoutons quelques animaux. Nous pouvons commencer de manière similaire au Player en créant -un composant Animal.

-
class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-    const skinInstance = gameObject.addComponent(SkinInstance, model);
-    skinInstance.mixer.timeScale = globals.moveSpeed / 4;
-    skinInstance.setAnimation('Idle');
-  }
-}
-
-

Le code ci-dessus définit le AnimationMixer.timeScale pour régler la vitesse de lecture -des animations par rapport à la vitesse de déplacement. De cette façon, si nous -ajustons la vitesse de déplacement, l'animation accélérera ou ralentira également.

-

Pour commencer, nous pourrions configurer un animal de chaque type

-
function init() {
-  // masquer la barre de chargement
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-  {
-    const gameObject = gameObjectManager.createGameObject(camera, 'camera');
-    globals.cameraInfo = gameObject.addComponent(CameraInfo);
-  }
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-    globals.player = gameObject.addComponent(Player);
-    globals.congaLine = [gameObject];
-  }
-
-+  const animalModelNames = [
-+    'pig',
-+    'cow',
-+    'llama',
-+    'pug',
-+    'sheep',
-+    'zebra',
-+    'horse',
-+  ];
-+  animalModelNames.forEach((name, ndx) => {
-+    const gameObject = gameObjectManager.createGameObject(scene, name);
-+    gameObject.addComponent(Animal, models[name]);
-+    gameObject.transform.position.x = (ndx + 1) * 5;
-+  });
-}
-
-

Et cela nous donnerait des animaux debout à l'écran, mais nous voulons qu'ils fassent quelque chose.

-

Faisons en sorte qu'ils suivent le joueur en file indienne, mais seulement si le joueur s'approche suffisamment. -Pour cela, nous avons besoin de plusieurs états.

-
    -
  • Inactif :

    -

    L'animal attend que le joueur s'approche

    -
  • -
  • Attendre la fin de la ligne :

    -

    L'animal a été "tagué" par le joueur, mais doit maintenant attendre que l'animal -au bout de la ligne arrive pour pouvoir rejoindre la fin de la ligne.

    -
  • -
  • Aller au dernier :

    -

    L'animal doit marcher jusqu'à l'endroit où se trouvait l'animal qu'il suit, -tout en enregistrant un historique de la position actuelle de l'animal qu'il suit.

    -
  • -
  • Suivre

    -

    L'animal doit continuer à enregistrer un historique de la position de l'animal qu'il suit -tout en se déplaçant vers l'endroit où se trouvait cet animal auparavant.

    -
  • -
-

Il existe de nombreuses façons de gérer différents états comme ceux-ci. Une méthode courante consiste à utiliser -une machine à états finis (Finite State Machine) et -à construire une classe pour nous aider à gérer l'état.

-

Alors, faisons cela.

-
class FiniteStateMachine {
-  constructor(states, initialState) {
-    this.states = states;
-    this.transition(initialState);
-  }
-  get state() {
-    return this.currentState;
-  }
-  transition(state) {
-    const oldState = this.states[this.currentState];
-    if (oldState && oldState.exit) {
-      oldState.exit.call(this);
-    }
-    this.currentState = state;
-    const newState = this.states[state];
-    if (newState.enter) {
-      newState.enter.call(this);
-    }
-  }
-  update() {
-    const state = this.states[this.currentState];
-    if (state.update) {
-      state.update.call(this);
-    }
-  }
-}
-
-

Voici une classe simple. Nous lui passons un objet contenant un ensemble d'états. -Chaque état a 3 fonctions optionnelles : enter, update et exit. -Pour changer d'état, nous appelons FiniteStateMachine.transition et lui passons -le nom du nouvel état. Si l'état actuel a une fonction exit, -elle est appelée. Ensuite, si le nouvel état a une fonction enter, -elle est appelée. Enfin, à chaque image, FiniteStateMachine.update appelle la fonction update -de l'état actuel.

-

Utilisons-le pour gérer les états des animaux.

-
// Retourne vrai si obj1 et obj2 sont proches
-function isClose(obj1, obj1Radius, obj2, obj2Radius) {
-  const minDist = obj1Radius + obj2Radius;
-  const dist = obj1.position.distanceTo(obj2.position);
-  return dist < minDist;
-}
-
-// maintient v entre -min et +min
-function minMagnitude(v, min) {
-  return Math.abs(v) > min
-      ? min * Math.sign(v)
-      : v;
-}
-
-const aimTowardAndGetDistance = function() {
-  const delta = new THREE.Vector3();
-
-  return function aimTowardAndGetDistance(source, targetPos, maxTurn) {
-    delta.subVectors(targetPos, source.position);
-    // calculer la direction dans laquelle nous voulons faire face
-    const targetRot = Math.atan2(delta.x, delta.z) + Math.PI * 1.5;
-    // tourner dans la direction la plus courte
-    const deltaRot = (targetRot - source.rotation.y + Math.PI * 1.5) % (Math.PI * 2) - Math.PI;
-    // s'assurer que nous ne tournons pas plus vite que maxTurn
-    const deltaRotation = minMagnitude(deltaRot, maxTurn);
-    // maintenir la rotation entre 0 et Math.PI * 2
-    source.rotation.y = THREE.MathUtils.euclideanModulo(
-        source.rotation.y + deltaRotation, Math.PI * 2);
-    // retourner la distance à la cible
-    return delta.length();
-  };
-}();
-
-class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-+    const hitRadius = model.size / 2;
-    const skinInstance = gameObject.addComponent(SkinInstance, model);
-    skinInstance.mixer.timeScale = globals.moveSpeed / 4;
-+    const transform = gameObject.transform;
-+    const playerTransform = globals.player.gameObject.transform;
-+    const maxTurnSpeed = Math.PI * (globals.moveSpeed / 4);
-+    const targetHistory = [];
-+    let targetNdx = 0;
-+
-+    function addHistory() {
-+      const targetGO = globals.congaLine[targetNdx];
-+      const newTargetPos = new THREE.Vector3();
-+      newTargetPos.copy(targetGO.transform.position);
-+      targetHistory.push(newTargetPos);
-+    }
-+
-+    this.fsm = new FiniteStateMachine({
-+      idle: {
-+        enter: () => {
-+          skinInstance.setAnimation('Idle');
-+        },
-+        update: () => {
-+          // vérifier si le joueur est proche
-+          if (isClose(transform, hitRadius, playerTransform, globals.playerRadius)) {
-+            this.fsm.transition('waitForEnd');
-+          }
-+        },
-+      },
-+      waitForEnd: {
-+        enter: () => {
-+          skinInstance.setAnimation('Jump');
-+        },
-+        update: () => {
-+          // obtenir le gameObject à la fin de la file indienne
-+          const lastGO = globals.congaLine[globals.congaLine.length - 1];
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          const targetPos = lastGO.transform.position;
-+          aimTowardAndGetDistance(transform, targetPos, deltaTurnSpeed);
-+          // vérifier si le dernier élément de la file indienne est proche
-+          if (isClose(transform, hitRadius, lastGO.transform, globals.playerRadius)) {
-+            this.fsm.transition('goToLast');
-+          }
-+        },
-+      },
-+      goToLast: {
-+        enter: () => {
-+          // se souvenir de qui nous suivons
-+          targetNdx = globals.congaLine.length - 1;
-+          // nous ajouter à la file indienne
-+          globals.congaLine.push(gameObject);
-+          skinInstance.setAnimation('Walk');
-+        },
-+        update: () => {
-+          addHistory();
-+          // marcher jusqu'au point le plus ancien de l'historique
-+          const targetPos = targetHistory[0];
-+          const maxVelocity = globals.moveSpeed * globals.deltaTime;
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          const distance = aimTowardAndGetDistance(transform, targetPos, deltaTurnSpeed);
-+          const velocity = distance;
-+          transform.translateOnAxis(kForward, Math.min(velocity, maxVelocity));
-+          if (distance <= maxVelocity) {
-+            this.fsm.transition('follow');
-+          }
-+        },
-+      },
-+      follow: {
-+        update: () => {
-+          addHistory();
-+          // supprimer l'historique le plus ancien et nous placer simplement là.
-+          const targetPos = targetHistory.shift();
-+          transform.position.copy(targetPos);
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          aimTowardAndGetDistance(transform, targetHistory[0], deltaTurnSpeed);
-+        },
-+      },
-+    }, 'idle');
-+  }
-+  update() {
-+    this.fsm.update();
-+  }
-}
-
-

C'était un gros morceau de code, mais il fait ce qui a été décrit ci-dessus. -J'espère que si vous parcourez chaque état, ce sera clair.

-

Quelques choses que nous devons ajouter. Nous devons faire en sorte que le joueur s'ajoute -aux variables globales afin que les animaux puissent le trouver, et nous devons commencer la -file indienne avec le GameObject du joueur.

-
function init() {
-
-  ...
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-+    globals.player = gameObject.addComponent(Player);
-+    globals.congaLine = [gameObject];
-  }
-
-}
-
-

Nous devons également calculer une taille pour chaque modèle

-
function prepModelsAndAnimations() {
-+  const box = new THREE.Box3();
-+  const size = new THREE.Vector3();
-  Object.values(models).forEach(model => {
-+    box.setFromObject(model.gltf.scene);
-+    box.getSize(size);
-+    model.size = size.length();
-    const animsByName = {};
-    model.gltf.animations.forEach((clip) => {
-      animsByName[clip.name] = clip;
-      // Devrait vraiment être corrigé dans le fichier .blend
-      if (clip.name === 'Walk') {
-        clip.duration /= 2;
-      }
-    });
-    model.animations = animsByName;
-  });
-}
-
-

Et nous avons besoin que le joueur enregistre sa taille

-
class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-+    globals.playerRadius = model.size / 2;
-
-

En y pensant maintenant, il aurait probablement été plus judicieux -que les animaux ciblent simplement la tête de la file indienne -au lieu du joueur spécifiquement. Peut-être que je reviendrai dessus -et modifierai cela plus tard.

-

Lorsque j'ai commencé cela, j'ai utilisé un seul rayon pour tous les animaux, -mais bien sûr, ce n'était pas bon, car le carlin est beaucoup plus petit que le cheval. -J'ai donc ajouté les différentes tailles, mais je voulais pouvoir visualiser -les choses. Pour ce faire, j'ai créé un composant StateDisplayHelper.

-

J'utilise un PolarGridHelper pour dessiner un cercle autour de chaque personnage, -et il utilise des éléments html pour permettre à chaque personnage d'afficher un certain statut en utilisant -les techniques couvertes dans l'article sur l'alignement des éléments html en 3D.

-

Nous devons d'abord ajouter du code HTML pour héberger ces éléments

-
<body>
-  <canvas id="c"></canvas>
-  <div id="ui">
-    <div id="left"><img src="../resources/images/left.svg"></div>
-    <div style="flex: 0 0 40px;"></div>
-    <div id="right"><img src="../resources/images/right.svg"></div>
-  </div>
-  <div id="loading">
-    <div>
-      <div>...chargement...</div>
-      <div class="progress"><div id="progressbar"></div></div>
-    </div>
-  </div>
-+  <div id="labels"></div>
-</body>
-
-

Et ajouter du CSS pour eux

-
#ui {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-  justify-items: center;
-  align-content: stretch;
-}
-#ui>div {
-  display: flex;
-  align-items: flex-end;
-  flex: 1 1 auto;
-}
-.bright {
-  filter: brightness(2);
-}
-#left {
-  justify-content: flex-end;
-}
-#right {
-  justify-content: flex-start;
-}
-#ui img {
-  padding: 10px;
-  width: 80px;
-  height: 80px;
-  display: block;
-}
-#labels {
-  position: absolute;  /* nous permet de nous positionner à l'intérieur du conteneur */
-  left: 0;             /* fait que notre position est en haut à gauche du conteneur */
-  top: 0;
-  color: white;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  pointer-events: none;
-}
-#labels>div {
-  position: absolute;  /* nous permet de les positionner à l'intérieur du conteneur */
-  left: 0;             /* fait que leur position par défaut est en haut à gauche du conteneur */
-  top: 0;
-  font-size: large;
-  font-family: monospace;
-  user-select: none;   /* n'autorise pas la sélection du texte */
-  text-shadow:         /* crée un contour noir */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-
-

Voici ensuite le composant

-
const labelContainerElem = document.querySelector('#labels');
-
-class StateDisplayHelper extends Component {
-  constructor(gameObject, size) {
-    super(gameObject);
-    this.elem = document.createElement('div');
-    labelContainerElem.appendChild(this.elem);
-    this.pos = new THREE.Vector3();
-
-    this.helper = new THREE.PolarGridHelper(size / 2, 1, 1, 16);
-    gameObject.transform.add(this.helper);
-  }
-  setState(s) {
-    this.elem.textContent = s;
-  }
-  setColor(cssColor) {
-    this.elem.style.color = cssColor;
-    this.helper.material.color.set(cssColor);
-  }
-  update() {
-    const {pos} = this;
-    const {transform} = this.gameObject;
-    const {canvas} = globals;
-    pos.copy(transform.position);
-
-    // obtenir les coordonnées d'écran normalisées de cette position
-    // x et y seront dans la plage -1 à +1, avec x = -1 étant
-    // à gauche et y = -1 étant en bas
-    pos.project(globals.camera);
-
-    // convertir la position normalisée en coordonnées CSS
-    const x = (pos.x *  .5 + .5) * canvas.clientWidth;
-    const y = (pos.y * -.5 + .5) * canvas.clientHeight;
-
-    // déplacer l'élément à cette position
-    this.elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-  }
-}
-
-

Et nous pouvons ensuite les ajouter aux animaux comme ceci

-
class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-+    this.helper = gameObject.addComponent(StateDisplayHelper, model.size);
-
-     ...
-
-  }
-  update() {
-    this.fsm.update();
-+    const dir = THREE.MathUtils.radToDeg(this.gameObject.transform.rotation.y);
-+    this.helper.setState(`${this.fsm.state}:${dir.toFixed(0)}`);
-  }
-}
-
-

Pendant que nous y sommes, faisons en sorte que nous puissions les activer/désactiver en utilisant lil-gui, comme -nous l'avons fait ailleurs.

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
-import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-
+const gui = new GUI();
-+gui.add(globals, 'debug').onChange(showHideDebugInfo);
-+showHideDebugInfo();
-
-const labelContainerElem = document.querySelector('#labels');
-+function showHideDebugInfo() {
-+  labelContainerElem.style.display = globals.debug ? '' : 'none';
-+}
-+showHideDebugInfo();
-
-class StateDisplayHelper extends Component {
-
-  ...
-
-  update() {
-+    this.helper.visible = globals.debug;
-+    if (!globals.debug) {
-+      return;
-+    }
-
-    ...
-  }
-}
-
-

Et avec cela, nous obtenons une sorte de début de jeu.

-

- -

-

À l'origine, j'avais l'intention de créer un jeu de serpent -où, à mesure que vous ajoutez des animaux à votre ligne, cela devient plus difficile car vous devez éviter -de les heurter. J'aurais également placé des obstacles dans la scène et peut-être une clôture ou une sorte -de barrière autour du périmètre.

-

Malheureusement, les animaux sont longs et minces. Vu d'en haut, voici le zèbre.

-
- -

Le code jusqu'à présent utilise des collisions circulaires, ce qui signifie que si nous avions des obstacles comme une clôture, -cela serait considéré comme une collision

-
- -

Ce n'est pas bon. Même d'animal à animal, nous aurions le même problème.

-

J'ai pensé à écrire un système de collision rectangle à rectangle en 2D, mais j'ai -rapidement réalisé que cela pourrait vraiment représenter beaucoup de code. Vérifier si 2 boîtes -orientées arbitrairement se chevauchent n'est pas trop de code, et pour notre jeu avec seulement quelques -objets, cela pourrait fonctionner, mais en y regardant de plus près, après quelques objets, vous -commencez rapidement à avoir besoin d'optimiser la vérification des collisions. Tout d'abord, vous pourriez parcourir tous -les objets qui peuvent potentiellement entrer en collision les uns avec les autres et vérifier leurs -sphères englobantes, leurs cercles englobants ou leurs boîtes englobantes alignées sur les axes. Une fois que vous -savez quels objets pourraient entrer en collision, vous devez faire plus de travail pour vérifier s'ils -entrent réellement en collision. Souvent, même la vérification des sphères englobantes est trop -de travail, et vous avez besoin d'une sorte de meilleure structure spatiale pour les objets afin de pouvoir -vérifier plus rapidement uniquement les objets potentiellement proches les uns des autres.

-

Ensuite, une fois que vous avez écrit le code pour vérifier si 2 objets entrent en collision, vous voulez généralement -créer un système de collision plutôt que de demander manuellement "est-ce que je collisionne avec ces -objets". Un système de collision émet des événements ou appelle des callbacks en relation avec -les collisions. L'avantage est qu'il peut vérifier toutes les collisions en une seule fois, de sorte qu'aucun -objet n'est vérifié plus d'une fois, alors que si vous appelez manuellement une fonction -"est-ce que je collisionne", les objets sont souvent vérifiés plus d'une fois, ce qui fait perdre du temps.

-

Créer ce système de collision ne représenterait probablement pas plus de 100 à 300 lignes de code -pour vérifier uniquement les rectangles orientés arbitrairement, mais c'est toujours beaucoup plus de code, -il a donc semblé préférable de l'omettre.

-

Une autre solution aurait été d'essayer de trouver d'autres personnages qui sont majoritairement -circulaires vus du dessus. D'autres personnages humanoïdes par exemple, au lieu -d'animaux, auquel cas la vérification circulaire pourrait fonctionner d'animal à animal. -Cela ne fonctionnerait pas d'animal à clôture ; eh bien, nous devrions ajouter une vérification de cercle à rectangle. J'ai -pensé à faire de la clôture une clôture de buissons ou de poteaux, quelque chose de circulaire, -mais alors il me faudrait probablement 120 à 200 d'entre eux pour entourer la zone de jeu, -ce qui entraînerait les problèmes d'optimisation mentionnés ci-dessus.

-

Ce sont des raisons pour lesquelles de nombreux jeux utilisent une solution existante. Souvent, ces solutions -font partie d'une bibliothèque de physique. La bibliothèque de physique a besoin de savoir si les objets -entrent en collision les uns avec les autres, donc en plus de fournir la physique, elles peuvent également être utilisées -pour détecter les collisions.

-

Si vous cherchez une solution, certains exemples three.js utilisent -ammo.js, cela pourrait donc être une option.

-

Une autre solution aurait pu être de placer les obstacles sur une grille -et d'essayer de faire en sorte que chaque animal et le joueur n'aient qu'à regarder -la grille. Bien que cela serait performant, j'ai estimé qu'il valait mieux laisser -cela comme un exercice pour le lecteur 😜

-

Une chose de plus, de nombreux systèmes de jeu ont ce qu'on appelle des coroutines. -Les coroutines sont des routines qui peuvent se mettre en pause pendant l'exécution et reprendre plus tard.

-

Faisons en sorte que le personnage principal émette des notes de musique comme s'il dirigeait -la ligne en chantant. Il existe de nombreuses façons de mettre cela en œuvre, mais pour l'instant, -faisons-le en utilisant des coroutines.

-

Tout d'abord, voici une classe pour gérer les coroutines

-
function* waitSeconds(duration) {
-  while (duration > 0) {
-    duration -= globals.deltaTime;
-    yield;
-  }
-}
-
-class CoroutineRunner {
-  constructor() {
-    this.generatorStacks = [];
-    this.addQueue = [];
-    this.removeQueue = new Set();
-  }
-  isBusy() {
-    return this.addQueue.length + this.generatorStacks.length > 0;
-  }
-  add(generator, delay = 0) {
-    const genStack = [generator];
-    if (delay) {
-      genStack.push(waitSeconds(delay));
-    }
-    this.addQueue.push(genStack);
-  }
-  remove(generator) {
-    this.removeQueue.add(generator);
-  }
-  update() {
-    this._addQueued();
-    this._removeQueued();
-    for (const genStack of this.generatorStacks) {
-      const main = genStack[0];
-      // Gérer si une coroutine en supprime une autre
-      if (this.removeQueue.has(main)) {
-        continue;
-      }
-      while (genStack.length) {
-        const topGen = genStack[genStack.length - 1];
-        const {value, done} = topGen.next();
-        if (done) {
-          if (genStack.length === 1) {
-            this.removeQueue.add(topGen);
-            break;
-          }
-          genStack.pop();
-        } else if (value) {
-          genStack.push(value);
-        } else {
-          break;
-        }
-      }
-    }
-    this._removeQueued();
-  }
-  _addQueued() {
-    if (this.addQueue.length) {
-      this.generatorStacks.splice(this.generatorStacks.length, 0, ...this.addQueue);
-      this.addQueue = [];
-    }
-  }
-  _removeQueued() {
-    if (this.removeQueue.size) {
-      this.generatorStacks = this.generatorStacks.filter(genStack => !this.removeQueue.has(genStack[0]));
-      this.removeQueue.clear();
-    }
-  }
-}
-
-

Il fait des choses similaires à SafeArray pour s'assurer qu'il est sûr d'ajouter ou de supprimer -des coroutines pendant que d'autres coroutines s'exécutent. Il gère également les coroutines imbriquées.

-

Pour créer une coroutine, vous créez une fonction génératrice JavaScript. -Une fonction génératrice est précédée du mot-clé function* (l'astérisque est important !)

-

Les fonctions génératrices peuvent yield (céder). Par exemple

-
function* count0To9() {
-  for (let i = 0; i < 10; ++i) {
-    console.log(i);
-    yield;
-  }
-}
-
-

Si nous ajoutions cette fonction au CoroutineRunner ci-dessus, elle imprimerait -chaque nombre, de 0 à 9, une fois par image, ou plutôt une fois par appel de runner.update.

-
const runner = new CoroutineRunner();
-runner.add(count0To9);
-while(runner.isBusy()) {
-  runner.update();
-}
-
-

Les coroutines sont supprimées automatiquement lorsqu'elles sont terminées.

-

Pour supprimer une coroutine prématurément, avant qu'elle n'atteigne la fin, vous devez conserver -une référence à son générateur comme ceci

-
const gen = count0To9();
-runner.add(gen);
-
-// plus tard
-
-runner.remove(gen);
-
-

En tout cas, dans le joueur, utilisons une coroutine pour émettre une note toutes les demi-secondes à 1 seconde.

-
class Player extends Component {
-  constructor(gameObject) {
-
-    ...
-
-+    this.runner = new CoroutineRunner();
-+
-+    function* emitNotes() {
-+      for (;;) {
-+        yield waitSeconds(rand(0.5, 1));
-+        const noteGO = gameObjectManager.createGameObject(scene, 'note');
-+        noteGO.transform.position.copy(gameObject.transform.position);
-+        noteGO.transform.position.y += 5;
-+        noteGO.addComponent(Note);
-+      }
-+    }
-+
-+    this.runner.add(emitNotes());
-  }
-  update() {
-+    this.runner.update();
-
-  ...
-
-  }
-}
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min;
-}
-
-

Vous pouvez voir que nous créons un CoroutineRunner et ajoutons une coroutine emitNotes. -Cette fonction s'exécutera indéfiniment, attendant 0,5 à 1 seconde, puis créant un objet de jeu -avec un composant Note.

-

Pour le composant Note, créons d'abord une texture avec une note dessus et, -au lieu de charger une image de note, créons-en une à l'aide d'un canvas, comme nous l'avons vu dans l'article sur les textures de canvas.

-
function makeTextTexture(str) {
-  const ctx = document.createElement('canvas').getContext('2d');
-  ctx.canvas.width = 64;
-  ctx.canvas.height = 64;
-  ctx.font = '60px sans-serif';
-  ctx.textAlign = 'center';
-  ctx.textBaseline = 'middle';
-  ctx.fillStyle = '#FFF';
-  ctx.fillText(str, ctx.canvas.width / 2, ctx.canvas.height / 2);
-  return new THREE.CanvasTexture(ctx.canvas);
-}
-const noteTexture = makeTextTexture('♪');
-
-

La texture que nous créons ci-dessus est blanche, ce qui signifie que lorsque nous l'utilisons, -nous pouvons définir la couleur du matériau et obtenir une note de n'importe quelle couleur.

-

Maintenant que nous avons une texture de note, voici le composant Note. -Il utilise SpriteMaterial et un Sprite, comme nous l'avons vu dans -l'article sur les billboards

-
class Note extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const {transform} = gameObject;
-    const noteMaterial = new THREE.SpriteMaterial({
-      color: new THREE.Color().setHSL(rand(1), 1, 0.5),
-      map: noteTexture,
-      side: THREE.DoubleSide,
-      transparent: true,
-    });
-    const note = new THREE.Sprite(noteMaterial);
-    note.scale.setScalar(3);
-    transform.add(note);
-    this.runner = new CoroutineRunner();
-    const direction = new THREE.Vector3(rand(-0.2, 0.2), 1, rand(-0.2, 0.2));
-
-    function* moveAndRemove() {
-      for (let i = 0; i < 60; ++i) {
-        transform.translateOnAxis(direction, globals.deltaTime * 10);
-        noteMaterial.opacity = 1 - (i / 60);
-        yield;
-      }
-      transform.parent.remove(transform);
-      gameObjectManager.removeGameObject(gameObject);
-    }
-
-    this.runner.add(moveAndRemove());
-  }
-  update() {
-    this.runner.update();
-  }
-}
-
-

Tout ce qu'il fait est de configurer un Sprite, puis de choisir une vitesse aléatoire et de déplacer -la transformation à cette vitesse pendant 60 images, tout en estompant la note -en définissant l'opacity du matériau. -Après la boucle, il supprime la transformation -de la scène et la note elle-même des gameobjects actifs.

-

Une dernière chose, ajoutons quelques animaux supplémentaires.

-
function init() {
-
-   ...
-
-  const animalModelNames = [
-    'pig',
-    'cow',
-    'llama',
-    'pug',
-    'sheep',
-    'zebra',
-    'horse',
-  ];
-+  const base = new THREE.Object3D();
-+  const offset = new THREE.Object3D();
-+  base.add(offset);
-+
-+  // positionner les animaux en spirale.
-+  const numAnimals = 28;
-+  const arc = 10;
-+  const b = 10 / (2 * Math.PI);
-+  let r = 10;
-+  let phi = r / b;
-+  for (let i = 0; i < numAnimals; ++i) {
-+    const name = animalModelNames[rand(animalModelNames.length) | 0];
-    const gameObject = gameObjectManager.createGameObject(scene, name);
-    gameObject.addComponent(Animal, models[name]);
-+    base.rotation.y = phi;
-+    offset.position.x = r;
-+    offset.updateWorldMatrix(true, false);
-+    offset.getWorldPosition(gameObject.transform.position);
-+    phi += arc / r;
-+    r = b * phi;
-  }
-
-

- -

-

Vous pourriez vous demander, pourquoi ne pas utiliser setTimeout ? Le problème avec setTimeout -est qu'il n'est pas lié à l'horloge du jeu. Par exemple, ci-dessus, nous avons défini le temps -maximum autorisé à s'écouler entre les images à 1/20ème de seconde. -Notre système de coroutine respectera cette limite, mais setTimeout ne le ferait pas.

-

Bien sûr, nous aurions pu créer un simple minuteur nous-mêmes

-
class Player ... {
-  update() {
-    this.noteTimer -= globals.deltaTime;
-    if (this.noteTimer <= 0) {
-      // réinitialiser le minuteur
-      this.noteTimer = rand(0.5, 1);
-      // créer un gameobject avec un composant de note
-    }
-  }
-
-

Et pour ce cas particulier, cela aurait peut-être été mieux, mais à mesure que vous ajoutez -de plus en plus de choses, vous aurez de plus en plus de variables ajoutées à vos classes, -alors qu'avec les coroutines, vous pouvez souvent simplement lancer et oublier.

-

Étant donné les états simples de nos animaux, nous aurions également pu les implémenter -avec une coroutine sous la forme de

-
// pseudo-code !
-function* animalCoroutine() {
-   setAnimation('Idle');
-   while(playerIsTooFar()) {
-     yield;
-   }
-   const target = endOfLine;
-   setAnimation('Jump');
-   while(targetIsTooFar()) {
-     aimAt(target);
-     yield;
-   }
-   setAnimation('Walk')
-   while(notAtOldestPositionOfTarget()) {
-     addHistory();
-     aimAt(target);
-     yield;
-   }
-   for(;;) {
-     addHistory();
-     const pos = history.unshift();
-     transform.position.copy(pos);
-     aimAt(history[0]);
-     yield;
-   }
-}
-
-

Cela aurait fonctionné, mais bien sûr, dès que nos états n'auraient pas été si linéaires, -nous aurions dû passer à une FiniteStateMachine.

-

Il ne m'était pas non plus clair si les coroutines devaient s'exécuter indépendamment de leurs -composants. Nous aurions pu créer un CoroutineRunner global et y placer toutes -les coroutines. Cela rendrait leur nettoyage plus difficile. En l'état actuel, -si le gameobject est supprimé, tous ses composants sont supprimés et -donc les CoroutineRunner créés ne sont plus appelés, et tout sera collecté par le -ramasse-miettes. Si nous avions un CoroutineRunner global, il incomberait alors -à chaque composant de supprimer toute coroutine qu'il aurait ajoutée, ou bien un autre -mécanisme d'enregistrement des coroutines auprès d'un composant ou d'un gameobject particulier -serait nécessaire afin que la suppression de l'un supprime les autres.

-

Il y a beaucoup d'autres problèmes qu'un -moteur de jeu normal gérerait. En l'état actuel, il n'y a pas d'ordre dans la façon dont -les gameobjects ou leurs composants sont exécutés. Ils sont simplement exécutés dans l'ordre -d'ajout. De nombreux systèmes de jeu ajoutent une priorité pour que l'ordre puisse être défini ou modifié.

-

Un autre problème que nous avons rencontré est que le composant Note supprime la transformation de son gameobject de la scène. -Cela semble être quelque chose qui devrait se produire dans GameObject puisque c'est GameObject -qui a ajouté la transformation en premier lieu. Peut-être que GameObject devrait avoir -une méthode dispose qui est appelée par GameObjectManager.removeGameObject ?

-

Encore un autre problème est la façon dont nous appelons manuellement gameObjectManager.update et inputManager.update. -Peut-être qu'il devrait y avoir un SystemManager auquel ces services globaux pourraient s'ajouter, -et chaque service aurait sa fonction update appelée. De cette façon, si nous ajoutions un nouveau -service comme CollisionManager, nous pourrions simplement l'ajouter au gestionnaire de système sans -avoir à modifier la boucle de rendu.

-

Je vous laisse le soin de régler ce genre de problèmes. -J'espère que cet article vous a donné quelques idées pour votre propre moteur de jeu.

-

Peut-être devrais-je promouvoir un game jam. Si vous cliquez sur les boutons jsfiddle ou codepen -au-dessus du dernier exemple, ils s'ouvriront sur ces sites prêts à être modifiés. Ajoutez des fonctionnalités, -changez le jeu pour qu'un carlin mène un groupe de chevaliers. Utilisez l'animation de roulade du chevalier -comme boule de bowling et faites un jeu de bowling avec des animaux. Faites une course de relais avec des animaux. -Si vous créez un jeu sympa, postez un lien dans les commentaires ci-dessous.

-
-[1] : techniquement, cela fonctionnerait toujours si aucun des parents n'a de translation, de rotation ou d'échelle §. -
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/how-to-create-vr-content.html b/manual/fr/how-to-create-vr-content.html deleted file mode 100644 index 355d550b5b4e2e..00000000000000 --- a/manual/fr/how-to-create-vr-content.html +++ /dev/null @@ -1,100 +0,0 @@ - - - Comment créer du contenu VR - - - - - - - - - - - - - -
-
-

Comment créer du contenu VR

-
-
-
- -

- Ce guide fournit un bref aperçu des composants de base d'une application VR basée sur le web réalisée avec three.js. -

- -

Flux de travail

- -

- Tout d'abord, vous devez inclure [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/VRButton.js VRButton.js] - dans votre projet. -

- -
-import { VRButton } from 'three/addons/webxr/VRButton.js';
-
- -

- *VRButton.createButton()* fait deux choses importantes : il crée un bouton qui indique la compatibilité VR. De plus, il initialise une session VR si l'utilisateur active le bouton. La seule chose que vous avez à faire est d'ajouter la ligne de code suivante à votre application. -

- -
-document.body.appendChild( VRButton.createButton( renderer ) );
-
- -

- Ensuite, vous devez indiquer à votre instance de `WebGLRenderer` d'activer le rendu XR. -

- -
-renderer.xr.enabled = true;
-
- -

- Enfin, vous devez ajuster votre boucle d'animation car nous ne pouvons pas utiliser notre fonction bien connue *window.requestAnimationFrame()*. Pour les projets VR, nous utilisons `renderer.setAnimationLoop()`. Le code minimal ressemble à ceci : -

- -
-renderer.setAnimationLoop( function () {
-
-  renderer.render( scene, camera );
-
-} );
-
- -

Étapes suivantes

- -

- Jetez un œil à l'un des exemples officiels de WebVR pour voir ce flux de travail en action.

- - [example:webxr_xr_ballshooter WebXR / XR / tireur de balles]
- [example:webxr_xr_cubes WebXR / XR / cubes]
- [example:webxr_xr_dragging WebXR / XR / glisser-déposer]
- [example:webxr_xr_marchingcubes WebXR / XR / marching cubes]
- [example:webxr_xr_paint WebXR / XR / peinture]
- [example:webxr_vr_panorama_depth WebXR / VR / panorama-profondeur]
- [example:webxr_vr_panorama WebXR / VR / panorama]
- [example:webxr_vr_rollercoaster WebXR / VR / montagnes russes]
- [example:webxr_vr_sandbox WebXR / VR / bac à sable]
- [example:webxr_vr_video WebXR / VR / vidéo] -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/how-to-dispose-of-objects.html b/manual/fr/how-to-dispose-of-objects.html deleted file mode 100644 index 0ec48728ecd91c..00000000000000 --- a/manual/fr/how-to-dispose-of-objects.html +++ /dev/null @@ -1,169 +0,0 @@ - - - Comment se débarrasser des objets - - - - - - - - - - - - - -
-
-

Comment se débarrasser des objets

-
-
-
- -

- Un aspect important pour améliorer les performances et éviter les fuites de mémoire dans votre application est la libération des entités de la librairie inutilisées. - Chaque fois que vous créez une instance d'un type *three.js*, vous allouez une certaine quantité de mémoire. Cependant, *three.js* crée pour des objets spécifiques - comme les géométries ou les matériaux des entités liées à WebGL comme des tampons (buffers) ou des programmes de shaders qui sont nécessaires au rendu. Il est important de - souligner que ces objets ne sont pas libérés automatiquement. Au lieu de cela, l'application doit utiliser une API spéciale afin de libérer de telles ressources. - Ce guide donne un bref aperçu de la manière dont cette API est utilisée et des objets pertinents dans ce contexte. -

- -

Géométries

- -

- Une géométrie représente généralement les informations de vertex définies comme une collection d'attributs. *three.js* crée en interne un objet de type [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] - pour chaque attribut. Ces entités ne sont supprimées que si vous appelez `BufferGeometry.dispose()`. Si une géométrie devient obsolète dans votre application, - exécutez la méthode pour libérer toutes les ressources associées. -

- -

Matériaux

- -

- Un matériau définit la manière dont les objets sont rendus. *three.js* utilise les informations d'une définition de matériau afin de construire un programme de shader pour le rendu. - Les programmes de shader ne peuvent être supprimés que si le matériau respectif est libéré. Pour des raisons de performance, *three.js* essaie de réutiliser les - programmes de shader existants si possible. Ainsi, un programme de shader n'est supprimé que si tous les matériaux associés sont libérés. Vous pouvez indiquer la libération d'un matériau en - exécutant `Material.dispose()`. -

- -

Textures

- -

- La libération d'un matériau n'a aucun effet sur les textures. Elles sont gérées séparément car une seule texture peut être utilisée par plusieurs matériaux en même temps. - Chaque fois que vous créez une instance de `Texture`, three.js crée en interne une instance de [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture]. - Comme pour les tampons (buffers), cet objet ne peut être supprimé qu'en appelant `Texture.dispose()`. -

- -

- Si vous utilisez un `ImageBitmap` comme source de données de la texture, vous devez appeler [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap/close ImageBitmap.close]() au niveau de l'application pour libérer toutes les ressources côté CPU. - Un appel automatique de `ImageBitmap.close()` dans `Texture.dispose()` n'est pas possible, car l'image bitmap devient inutilisable, et le moteur n'a aucun moyen de savoir si l'image bitmap est utilisée ailleurs. -

- -

Cibles de rendu

- -

- Les objets de type `WebGLRenderTarget` allouent non seulement une instance de [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture] mais aussi - des [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer WebGLFramebuffer] et des [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer WebGLRenderbuffer] - pour réaliser des destinations de rendu personnalisées. Ces objets ne sont désalloués qu'en exécutant `WebGLRenderTarget.dispose()`. -

- -

Mesh skinné

- -

- Les meshes skinnés représentent leur hiérarchie d'os comme des squelettes. Si vous n'avez plus besoin d'un mesh skinné, envisagez d'appeler `Skeleton.dispose()` sur le squelette pour libérer les ressources internes. - Gardez à l'esprit que les squelettes peuvent être partagés entre plusieurs meshes skinnés, n'appelez donc `dispose()` que si le squelette n'est pas utilisé par d'autres meshes skinnés actifs. -

- -

Divers

- -

- Il existe d'autres classes dans le répertoire d'exemples, comme les contrôles ou les passes de post-traitement, qui fournissent des méthodes `dispose()` afin de supprimer les écouteurs d'événements internes - ou les cibles de rendu. En général, il est recommandé de vérifier l'API ou la documentation d'une classe et de rechercher `dispose()`. Si présent, vous devriez l'utiliser lors du nettoyage. -

- -

FAQ

- -

Pourquoi *three.js* ne peut-il pas libérer les objets automatiquement ?

- -

- Cette question a été posée de nombreuses fois par la communauté, il est donc important de clarifier ce point. Le fait est que *three.js* ne connaît pas la durée de vie ou la portée - des entités créées par l'utilisateur, comme les géométries ou les matériaux. C'est la responsabilité de l'application. Par exemple, même si un matériau n'est actuellement pas utilisé pour le rendu, - il pourrait être nécessaire pour la prochaine image. Donc, si l'application décide qu'un certain objet peut être supprimé, elle doit en informer le moteur en appelant la méthode - `dispose()` respective. -

- -

La suppression d'un mesh de la scène libère-t-elle également sa géométrie et son matériau ?

- -

- Non, vous devez explicitement libérer la géométrie et le matériau via *dispose()*. Gardez à l'esprit que les géométries et les matériaux peuvent être partagés entre des objets 3D comme les meshes. -

- -

*three.js* fournit-il des informations sur la quantité d'objets mis en cache ?

- -

- Oui. Il est possible d'évaluer `renderer.info`, une propriété spéciale du renderer avec une série d'informations statistiques sur la mémoire de la carte graphique - et le processus de rendu. Entre autres choses, elle vous indique combien de textures, de géométries et de programmes de shader sont stockés en interne. Si vous remarquez des problèmes de performance - dans votre application, c'est une bonne idée de déboguer cette propriété afin d'identifier facilement une fuite de mémoire. -

- -

Que se passe-t-il lorsque vous appelez `dispose()` sur une texture mais que l'image n'est pas encore chargée ?

- -

- Les ressources internes d'une texture ne sont allouées que si l'image est entièrement chargée. Si vous libérez une texture avant que l'image ne soit chargée, - rien ne se passe. Aucune ressource n'a été allouée, il n'y a donc pas besoin de nettoyage. -

- -

Que se passe-t-il si j'appelle `dispose()` puis utilise l'objet respectif ultérieurement ?

- -

- Cela dépend. Pour les géométries, les matériaux, les textures, les cibles de rendu et les passes de post-traitement, les ressources internes supprimées peuvent être recréées par le moteur. - Aucune erreur d'exécution ne se produira donc, mais vous pourriez remarquer un impact négatif sur les performances pour l'image actuelle, surtout lorsque les programmes de shader doivent être compilés. - - Les contrôles et les renderers sont une exception. Les instances de ces classes ne peuvent pas être utilisées après que `dispose()` a été appelée. Vous devez créer de nouvelles instances dans ce cas. -

- -

Comment gérer les objets *three.js* dans mon application ? Quand savoir comment libérer les choses ?

- -

- En général, il n'y a pas de recommandation définitive pour cela. Cela dépend fortement du cas d'utilisation spécifique pour savoir quand appeler `dispose()` est approprié. Il est important de souligner que - il n'est pas toujours nécessaire de libérer les objets en permanence. Un bon exemple est un jeu composé de plusieurs niveaux. Un bon moment pour la libération des objets est lors du changement de niveau. - L'application pourrait parcourir l'ancienne scène et libérer tous les matériaux, géométries et textures obsolètes. Comme mentionné dans la section précédente, cela ne produit pas - d'erreur d'exécution si vous libérez un objet qui est en fait toujours utilisé. Le pire qui puisse arriver est une chute de performance pour une seule image. -

- -

Pourquoi `renderer.info.memory` rapporte toujours des géométries et des textures après avoir parcouru la scène et libéré toutes les textures et géométries accessibles ?

- -

- Dans certains cas, certaines textures et géométries utilisées en interne par Three.js - ne sont pas accessibles lors de la traversée du graphe de scène afin d'être libérées. - Il est prévu que `renderer.info.memory` les signale toujours même après un nettoyage complet de la scène. - Cependant, elles ne fuient pas, mais sont réutilisées lors des cycles consécutifs de nettoyage/repopulation de la scène. - - Ces cas peuvent être liés à l'utilisation de `material.envMap`, `scene.background`, `scene.environment`, - ou d'autres contextes qui nécessitent que le moteur crée des textures ou des géométries pour un usage interne. -

- -

Exemples illustrant l'utilisation de dispose()

- -

- [example:webgl_test_memory WebGL / test / mémoire]
- [example:webgl_test_memory2 WebGL / test / mémoire2]
-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/how-to-update-things.html b/manual/fr/how-to-update-things.html deleted file mode 100644 index 8be9e69ff74eb0..00000000000000 --- a/manual/fr/how-to-update-things.html +++ /dev/null @@ -1,275 +0,0 @@ - - - Comment mettre à jour les éléments - - - - - - - - - - - - - -
-
-

Comment mettre à jour les éléments

-
-
-
- -
-

Par défaut, tous les objets mettent automatiquement à jour leurs matrices s'ils ont été ajoutés à la scène avec

-
-const object = new THREE.Object3D();
-scene.add( object );
-
- ou s'ils sont l'enfant d'un autre objet qui a été ajouté à la scène : -
-const object1 = new THREE.Object3D();
-const object2 = new THREE.Object3D();
-
-object1.add( object2 );
-scene.add( object1 ); //object1 et object2 mettront automatiquement à jour leurs matrices
-
-
- -

Cependant, si vous savez que l'objet sera statique, vous pouvez désactiver cela et mettre à jour la matrice de transformation manuellement uniquement lorsque nécessaire.

- -
-object.matrixAutoUpdate = false;
-object.updateMatrix();
-
- -

BufferGeometry

-
-

- Les BufferGeometries stockent des informations (telles que les positions des sommets, les indices des faces, les normales, les couleurs, - les UV et tout attribut personnalisé) dans des tampons d'attributs - c'est-à-dire des - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays tableaux typés]. - Cela les rend généralement plus rapides que les Geometries standard, au prix d'être un peu plus difficiles à - utiliser. -

-

- En ce qui concerne la mise à jour des BufferGeometries, la chose la plus importante à comprendre est que - vous ne pouvez pas redimensionner les tampons (c'est très coûteux, c'est fondamentalement l'équivalent de la création d'une nouvelle géométrie). - Vous pouvez cependant mettre à jour le contenu des tampons. -

-

- Cela signifie que si vous savez qu'un attribut de votre BufferGeometry va croître, par exemple le nombre de sommets, - vous devez pré-allouer un tampon suffisamment grand pour contenir tous les nouveaux sommets qui pourraient être créés. Bien sûr, - cela signifie également qu'il y aura une taille maximale pour votre BufferGeometry - il n'y a - aucun moyen de créer une BufferGeometry qui puisse être étendue efficacement indéfiniment. -

-

- Nous utiliserons l'exemple d'une ligne qui s'étend au moment du rendu. Nous allouerons de l'espace - dans le tampon pour 500 sommets, mais n'en dessinerons que deux au début, en utilisant `BufferGeometry.drawRange`. -

-
-const MAX_POINTS = 500;
-
-// geometry
-const geometry = new THREE.BufferGeometry();
-
-// attributes
-const positions = new Float32Array( MAX_POINTS * 3 ); // 3 floats (x, y et z) par point
-geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
-
-// draw range
-const drawCount = 2; // dessine seulement les 2 premiers points, seulement
-geometry.setDrawRange( 0, drawCount );
-
-// material
-const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
-
-// line
-const line = new THREE.Line( geometry, material );
-scene.add( line );
-
-

- Ensuite, nous ajouterons aléatoirement des points à la ligne en utilisant un modèle comme : -

-
-const positionAttribute = line.geometry.getAttribute( 'position' );
-
-let x = 0, y = 0, z = 0;
-
-for ( let i = 0; i < positionAttribute.count; i ++ ) {
-
-    positionAttribute.setXYZ( i, x, y, z );
-
-    x += ( Math.random() - 0.5 ) * 30;
-    y += ( Math.random() - 0.5 ) * 30;
-    z += ( Math.random() - 0.5 ) * 30;
-
-}
-
-

- Si vous souhaitez modifier le nombre de points rendus après le premier rendu, faites ceci : -

-
-line.geometry.setDrawRange( 0, newValue );
-
-

- Si vous souhaitez modifier les valeurs des données de position après le premier rendu, vous devez - définir le drapeau needsUpdate comme suit : -

-
-positionAttribute.needsUpdate = true; // requis après le premier rendu
-
- -

- Si vous modifiez les valeurs des données de position après le rendu initial, vous pourriez avoir besoin de recalculer - les volumes englobants afin que d'autres fonctionnalités du moteur comme le culling par frustum de vue ou les assistants fonctionnent correctement. -

-
-line.geometry.computeBoundingBox();
-line.geometry.computeBoundingSphere();
-
- -

- [link:https://jsfiddle.net/t4m85pLr/1/ Voici un fiddle] montrant une ligne animée que vous pouvez adapter à votre cas d'utilisation. -

- -

Exemples

- -

- [example:webgl_custom_attributes WebGL / personnalisé / attributs]
- [example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / personnalisé / attributs / particules] -

- -
- -

Matériaux

-
-

Toutes les valeurs des uniforms peuvent être modifiées librement (par exemple couleurs, textures, opacité, etc.), les valeurs sont envoyées au shader à chaque image.

- -

De plus, les paramètres liés à l'état GL peuvent changer à tout moment (depthTest, blending, polygonOffset, etc.).

- -

Les propriétés suivantes ne peuvent pas être facilement modifiées à l'exécution (une fois que le matériau a été rendu au moins une fois) :

-
    -
  • nombre et types des uniforms
  • -
  • présence ou non de -
      -
    • texture
    • -
    • brouillard
    • -
    • couleurs de sommet
    • -
    • morphing
    • -
    • shadow map
    • -
    • test alpha
    • -
    • transparent
    • -
    -
  • -
- -

Les modifications de ces éléments nécessitent la construction d'un nouveau programme de shader. Vous devrez définir

- material.needsUpdate = true - -

Gardez à l'esprit que cela peut être assez lent et provoquer des à-coups dans la cadence d'images (surtout sous Windows, car la compilation des shaders est plus lente en DirectX qu'en OpenGL).

- -

Pour une expérience plus fluide, vous pouvez émuler dans une certaine mesure les modifications de ces fonctionnalités en utilisant des valeurs "factices" comme des lumières d'intensité nulle, des textures blanches ou un brouillard de densité nulle.

- -

Vous pouvez modifier librement le matériau utilisé pour les morceaux de géométrie, cependant, vous ne pouvez pas modifier la façon dont un objet est divisé en morceaux (selon les matériaux des faces).

- -

Si vous avez besoin d'avoir différentes configurations de matériaux pendant l'exécution :

-

Si le nombre de matériaux / morceaux est faible, vous pouvez pré-diviser l'objet à l'avance (par exemple cheveux / visage / corps / vêtements du haut / pantalon pour un humain, avant / côtés / haut / verre / pneu / intérieur pour une voiture).

- -

Si le nombre est élevé (par exemple, chaque face pourrait être potentiellement différente), envisagez une solution différente, telle que l'utilisation d'attributs / textures pour piloter un aspect différent par face.

- -

Exemples

-

- [example:webgl_materials_car WebGL / matériaux / voiture]
- [example:webgl_postprocessing_dof WebGL / webgl_postprocessing / dof] -

-
- - -

Textures

-
-

Les textures d'image, de canevas, de vidéo et de données doivent avoir le drapeau suivant défini si elles sont modifiées :

- - texture.needsUpdate = true; - -

Les cibles de rendu se mettent à jour automatiquement.

- -

Exemples

-

- [example:webgl_materials_video WebGL / matériaux / vidéo]
- [example:webgl_rtt WebGL / rtt] -

- -
- -

Caméras

-
-

La position et la cible d'une caméra sont mises à jour automatiquement. Si vous avez besoin de changer

-
    -
  • - fov -
  • -
  • - aspect -
  • -
  • - near -
  • -
  • - far -
  • -
-

- alors vous devrez recalculer la matrice de projection : -

-
-camera.aspect = window.innerWidth / window.innerHeight;
-camera.updateProjectionMatrix();
-
-
- -

InstancedMesh

-
-

- InstancedMesh est une classe permettant d'accéder facilement au rendu instancié dans three.js. Certaines fonctionnalités de la bibliothèque comme le culling par frustum de vue ou - le ray casting dépendent de volumes englobants à jour (sphère englobante et boîte englobante). En raison de la façon dont InstancedMesh fonctionne, la classe - possède ses propres propriétés boundingBox et boundingSphere qui remplacent les volumes englobants au niveau de la géométrie. -

-

- Similaire aux géométries, vous devez recalculer la boîte englobante et la sphère chaque fois que vous modifiez les données sous-jacentes. Dans le contexte de InstancedMesh, cela - se produit lorsque vous transformez des instances via setMatrixAt(). Vous pouvez utiliser le même modèle qu'avec les géométries. -

-
-instancedMesh.computeBoundingBox();
-instancedMesh.computeBoundingSphere();
-
- -
- -

SkinnedMesh

-
-

- SkinnedMesh suit les mêmes principes que InstancedMesh en ce qui concerne les volumes englobants. Cela signifie que la classe a sa propre version de - boundingBox et boundingSphere pour enfermer correctement les maillages animés. - Lors de l'appel de computeBoundingBox() et computeBoundingSphere(), la classe calcule les volumes englobants respectifs en fonction de la transformation actuelle des os (ou en d'autres termes, de l'état d'animation actuel). -

-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/how-to-use-post-processing.html b/manual/fr/how-to-use-post-processing.html deleted file mode 100644 index 60881ee8aae0f3..00000000000000 --- a/manual/fr/how-to-use-post-processing.html +++ /dev/null @@ -1,142 +0,0 @@ - - - Comment utiliser le post-traitement - - - - - - - - - - - - - -
-
-

Comment utiliser le post-traitement

-
-
-
- -

- De nombreuses applications three.js rendent leurs objets 3D directement à l'écran. Parfois, cependant, vous souhaitez appliquer un ou plusieurs effets graphiques - tels que la profondeur de champ, le Bloom, le grain de film ou divers types d'anti-aliasing. Le post-traitement est une approche largement utilisée - pour implémenter de tels effets. D'abord, la scène est rendue sur une cible de rendu qui représente un tampon dans la mémoire de la carte graphique. - À l'étape suivante, une ou plusieurs passes de post-traitement appliquent des filtres et des effets au tampon d'image avant qu'il ne soit finalement rendu à - l'écran. -

-

- three.js fournit une solution complète de post-traitement via `EffectComposer` pour implémenter un tel flux de travail. -

- -

Flux de travail

- -

- La première étape du processus consiste à importer tous les fichiers nécessaires depuis le répertoire d'exemples. Ce guide suppose que vous utilisez le - [link:https://www.npmjs.com/package/three package npm] officiel de three.js. Pour notre démo de base dans ce guide, nous avons besoin des fichiers suivants. -

- -
-import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
-import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
-import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';
-import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
-
- -

- Après l'importation réussie de tous les fichiers, nous pouvons créer notre compositeur en lui passant une instance de `WebGLRenderer`. -

- -
-const composer = new EffectComposer( renderer );
-
- -

- Lorsque vous utilisez un compositeur, il est nécessaire de modifier la boucle d'animation de l'application. Au lieu d'appeler la méthode de rendu de - `WebGLRenderer`, nous utilisons maintenant la contrepartie respective de `EffectComposer`. -

- -
-function animate() {
-
-  requestAnimationFrame( animate );
-
-  composer.render();
-
-}
-
- -

- Notre compositeur est maintenant prêt, il est donc possible de configurer la chaîne de passes de post-traitement. Ces passes sont responsables de la création - du rendu visuel final de l'application. Elles sont traitées dans l'ordre de leur ajout/insertion. Dans notre exemple, l'instance de `RenderPass` - est exécutée en premier, puis l'instance de `GlitchPass` et enfin `OutputPass`. La dernière passe activée dans la chaîne est automatiquement rendue à l'écran. - La configuration des passes ressemble à ceci : -

- -
-const renderPass = new RenderPass( scene, camera );
-composer.addPass( renderPass );
-
-const glitchPass = new GlitchPass();
-composer.addPass( glitchPass );
-
-const outputPass = new OutputPass();
-composer.addPass( outputPass );
-
- -

- `RenderPass` est normalement placée au début de la chaîne afin de fournir la scène rendue comme entrée pour l'étape de post-traitement suivante. Dans notre cas, - `GlitchPass` utilisera ces données d'image pour appliquer un effet de glitch sauvage. `OutputPass` est généralement la dernière passe de la chaîne qui effectue la conversion de l'espace colorimétrique sRGB et le mappage tonal. - Découvrez cet [link:https://threejs.org/examples/webgl_postprocessing_glitch exemple live] pour le voir en action. -

- -

Passes intégrées

- -

- Vous pouvez utiliser une large gamme de passes de post-traitement prédéfinies fournies par le moteur. Elles se trouvent dans le - répertoire [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/postprocessing postprocessing]. -

- -

Passes personnalisées

- -

- Parfois, vous souhaitez écrire un shader de post-traitement personnalisé et l'inclure dans la chaîne de passes de post-traitement. Pour ce scénario, - vous pouvez utiliser `ShaderPass`. Après avoir importé le fichier et votre shader personnalisé, vous pouvez utiliser le code suivant pour configurer la passe. -

- -
-import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
-import { LuminosityShader } from 'three/addons/shaders/LuminosityShader.js';
-
-// plus tard dans votre routine d'initialisation
-
-const luminosityPass = new ShaderPass( LuminosityShader );
-composer.addPass( luminosityPass );
-
- -

- Le dépôt fournit un fichier appelé [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/shaders/CopyShader.js CopyShader] qui constitue un - bon point de départ pour votre propre shader personnalisé. `CopyShader` copie simplement le contenu de l'image du tampon de lecture (`read buffer`) de l'`EffectComposer` - vers son tampon d'écriture (`write buffer`) sans appliquer aucun effet. -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/indexed-textures.html b/manual/fr/indexed-textures.html deleted file mode 100644 index 3a9a3bc0739a31..00000000000000 --- a/manual/fr/indexed-textures.html +++ /dev/null @@ -1,631 +0,0 @@ - - - Textures Indexées pour la Sélection et la Couleur - - - - - - - - - - - - - -
-
-

Textures Indexées pour la Sélection et la Couleur

-
-
-
-

Cet article est une continuation de un article sur l'alignement des éléments HTML en 3D. -Si vous ne l'avez pas encore lu, vous devriez commencer par là avant de continuer ici.

-

Parfois, l'utilisation de three.js nécessite de trouver des solutions créatives. -Je ne suis pas sûr que ce soit une excellente solution, mais j'ai pensé la partager et -vous pouvez voir si elle suggère des solutions pour vos besoins.

-

Dans l'article précédent, nous -avons affiché les noms de pays autour d'un globe 3D. Comment pourrions-nous permettre à -l'utilisateur de sélectionner un pays et d'afficher sa sélection ?

-

La première idée qui vient à l'esprit est de générer la géométrie pour chaque pays. -Nous pourrions utiliser une solution de picking comme nous l'avons vu précédemment. -Nous construirions une géométrie 3D pour chaque pays. Si l'utilisateur clique sur le maillage de -ce pays, nous saurions quel pays a été cliqué.

-

Donc, juste pour vérifier cette solution, j'ai essayé de générer des maillages 3D de tous les pays -en utilisant les mêmes données que celles que j'ai utilisées pour générer les contours -dans l'article précédent. -Le résultat était un fichier GLTF (.glb) binaire de 15,5 Mo. Faire télécharger 15,5 Mo -à l'utilisateur me semble excessif.

-

Il existe de nombreuses façons de compresser les données. La première serait probablement -d'appliquer un algorithme pour réduire la résolution des contours. Je n'ai pas passé -de temps à explorer cette solution. Pour les frontières des États-Unis, c'est probablement un -gain énorme. Pour les frontières du Canada, probablement beaucoup moins.

-

Une autre solution serait d'utiliser simplement la compression de données réelle. Par exemple, la compression Gzip -du fichier l'a réduit à 11 Mo. C'est 30% de moins, mais probablement pas suffisant.

-

Nous pourrions stocker toutes les données sous forme de valeurs de plage sur 16 bits au lieu de valeurs flottantes sur 32 bits. -Ou nous pourrions utiliser quelque chose comme la compression Draco -et peut-être que cela suffirait. Je n'ai pas vérifié et je vous encourage à vérifier -par vous-même et à me dire comment ça se passe, car j'aimerais le savoir. 😅

-

Dans mon cas, j'ai pensé à la solution de picking GPU -que nous avons abordée à la fin de l'article sur le picking. Dans -cette solution, nous avons dessiné chaque maillage avec une couleur unique qui représentait -l'ID de ce maillage. Nous avons ensuite dessiné tous les maillages et regardé la couleur -sur laquelle on a cliqué.

-

En nous inspirant de cela, nous pourrions pré-générer une carte des pays où -la couleur de chaque pays est son numéro d'index dans notre tableau de pays. Nous pourrions -alors utiliser une technique de picking GPU similaire. Nous dessinerions le globe hors écran en utilisant -cette texture d'index. Regarder la couleur du pixel sur lequel l'utilisateur clique -nous donnerait l'ID du pays.

-

Donc, j'ai écrit du code -pour générer une telle texture. La voici.

-
- -

Note : Les données utilisées pour générer cette texture proviennent de ce site web -et sont donc sous licence CC-BY-SA.

-

Elle ne fait que 217 Ko, bien mieux que les 14 Mo pour les maillages de pays. En fait, nous pourrions probablement -même réduire la résolution, mais 217 Ko semble suffisant pour l'instant.

-

Alors essayons de l'utiliser pour sélectionner des pays.

-

En prenant du code de l'exemple de picking GPU, nous avons besoin -d'une scène pour le picking.

-
const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

et nous devons ajouter le globe avec notre texture d'index à la -scène de picking.

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-+  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-+  indexTexture.minFilter = THREE.NearestFilter;
-+  indexTexture.magFilter = THREE.NearestFilter;
-+
-+  const pickingMaterial = new THREE.MeshBasicMaterial({map: indexTexture});
-+  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

Ensuite, copions la classe GPUPickingHelper que nous avons -utilisée précédemment avec quelques modifications mineures.

-
class GPUPickHelper {
-  constructor() {
-    // créer une cible de rendu de 1x1 pixel
-    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-    this.pixelBuffer = new Uint8Array(4);
--    this.pickedObject = null;
--    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera) {
-    const {pickingTexture, pixelBuffer} = this;
-
-    // définir le décalage de la vue pour représenter juste un seul pixel sous la souris
-    const pixelRatio = renderer.getPixelRatio();
-    camera.setViewOffset(
-        renderer.getContext().drawingBufferWidth,   // largeur totale
-        renderer.getContext().drawingBufferHeight,  // haut total
-        cssPosition.x * pixelRatio | 0,             // coordonnée x du rectangle
-        cssPosition.y * pixelRatio | 0,             // coordonnée y du rectangle
-        1,                                          // largeur du rectangle
-        1,                                          // hauteur du rectangle
-    );
-    // effectuer le rendu de la scène
-    renderer.setRenderTarget(pickingTexture);
-    renderer.render(scene, camera);
-    renderer.setRenderTarget(null);
-    // effacer le décalage de la vue pour que le rendu revienne à la normale
-    camera.clearViewOffset();
-    // lire le pixel
-    renderer.readRenderTargetPixels(
-        pickingTexture,
-        0,   // x
-        0,   // y
-        1,   // width
-        1,   // height
-        pixelBuffer);
-
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2] <<  0);
-+
-+    return id;
--    const id =
--        (pixelBuffer[0] << 16) |
--        (pixelBuffer[1] <<  8) |
--        (pixelBuffer[2]      );
--    const intersectedObject = idToObject[id];
--    if (intersectedObject) {
--      // pick the first object. It's the closest one
--      this.pickedObject = intersectedObject;
--      // save its color
--      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
--      // set its emissive color to flashing red/yellow
--      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
--    }
-  }
-}
-
-

Maintenant, nous pouvons l'utiliser pour sélectionner des pays.

-
const pickHelper = new GPUPickHelper();
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // sortir si les données ne sont pas encore chargées
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    // nous avons cliqué sur un pays. Basculer sa propriété 'selected'
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    // si nous sélectionnons ce pays et que les touches modificatrices ne sont pas
-    // enfoncées, désélectionner tout le reste.
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-  } else if (numCountriesSelected) {
-    // l'océan ou le ciel a été cliqué
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-}
-
-canvas.addEventListener('pointerup', pickCountry);
-
-

Le code ci-dessus définit/annule la propriété selected sur -le tableau de pays. Si shift ou ctrl ou cmd -est enfoncé, vous pouvez sélectionner plus d'un pays.

-

Il ne reste plus qu'à afficher les pays sélectionnés. Pour l'instant, -mettons simplement à jour les labels.

-
function updateLabels() {
-  // sortir si les données ne sont pas encore chargées
-  if (!countryInfos) {
-    return;
-  }
-
-  const large = settings.minArea * settings.minArea;
-  // obtenir une matrice qui représente une orientation relative de la caméra
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // obtenir la position de la caméra
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
--    const {position, elem, area} = countryInfo;
--    // large enough?
--    if (area < large) {
-+    const {position, elem, area, selected} = countryInfo;
-+    const largeEnough = area >= large;
-+    const show = selected || (numCountriesSelected === 0 && largeEnough);
-+    if (!show) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-    ...
-
-

et avec cela, nous devrions pouvoir sélectionner des pays

-

- -

-

Le code affiche toujours les pays en fonction de leur superficie, mais si vous -en cliquez sur un, seul celui-ci aura un label.

-

Cela semble donc une solution raisonnable pour sélectionner des pays, -mais qu'en est-il de la mise en évidence des pays sélectionnés ?

-

Pour cela, nous pouvons nous inspirer des graphiques palettisés.

-

Les graphiques palettisés -ou couleurs indexées sont -ce qu'utilisaient les anciens systèmes comme l'Atari 800, l'Amiga, la NES, -la Super Nintendo et même les anciens PC IBM. Au lieu de stocker des images bitmap -en couleurs RGBA (8 bits par couleur, 32 octets par pixel ou plus), ils stockaient -des images bitmap en valeurs de 8 bits ou moins. La valeur de chaque pixel était un index -dans une palette. Par exemple, une valeur -de 3 dans l'image signifie "afficher la couleur 3". La couleur que représente la couleur n°3 est -définie ailleurs dans ce qu'on appelle une "palette".

-

En JavaScript, vous pouvez l'imaginer comme ceci

-
const face7x7PixelImageData = [
-  0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 2, 0, 2, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 3, 3, 3, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  0, 1, 1, 1, 1, 1, 1,
-];
-
-const palette = [
-  [255, 255, 255],  // white
-  [  0,   0,   0],  // black
-  [  0, 255, 255],  // cyan
-  [255,   0,   0],  // red
-];
-
-

Où chaque pixel dans les données de l'image est un index dans la palette. Si vous interprétiez -les données de l'image à travers la palette ci-dessus, vous obtiendriez cette image

-
- -

Dans notre cas, nous avons déjà une texture ci-dessus qui a un ID différent -par pays. Ainsi, nous pourrions utiliser cette même texture à travers une texture de palette -pour donner à chaque pays sa propre couleur. En modifiant la texture de palette, -nous pouvons colorer chaque pays individuellement. Par exemple, en mettant -toute la texture de palette en noir, puis en attribuant une couleur différente à l'entrée -d'un pays dans la palette, nous pouvons mettre en évidence uniquement ce pays.

-

Pour réaliser des graphiques à index palettisés, il faut du code shader personnalisé. -Modifions les shaders par défaut dans three.js. -De cette façon, nous pourrons utiliser l'éclairage et d'autres fonctionnalités si nous le souhaitons.

-

Comme nous l'avons vu dans l'article sur l'animation de nombreux objets, -nous pouvons modifier les shaders par défaut en ajoutant une fonction à la propriété -onBeforeCompile d'un matériau.

-

Le shader de fragment par défaut ressemble à ceci avant la compilation.

-
#include <common>
-#include <color_pars_fragment>
-#include <uv_pars_fragment>
-#include <map_pars_fragment>
-#include <alphamap_pars_fragment>
-#include <aomap_pars_fragment>
-#include <lightmap_pars_fragment>
-#include <envmap_pars_fragment>
-#include <fog_pars_fragment>
-#include <specularmap_pars_fragment>
-#include <logdepthbuf_pars_fragment>
-#include <clipping_planes_pars_fragment>
-void main() {
-    #include <clipping_planes_fragment>
-    vec4 diffuseColor = vec4( diffuse, opacity );
-    #include <logdepthbuf_fragment>
-    #include <map_fragment>
-    #include <color_fragment>
-    #include <alphamap_fragment>
-    #include <alphatest_fragment>
-    #include <specularmap_fragment>
-    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
-    #ifdef USE_LIGHTMAP
-        reflectedLight.indirectDiffuse += texture2D( lightMap, vLightMapUv ).xyz * lightMapIntensity;
-    #else
-        reflectedLight.indirectDiffuse += vec3( 1.0 );
-    #endif
-    #include <aomap_fragment>
-    reflectedLight.indirectDiffuse *= diffuseColor.rgb;
-    vec3 outgoingLight = reflectedLight.indirectDiffuse;
-    #include <envmap_fragment>
-    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
-    #include <premultiplied_alpha_fragment>
-    #include <tonemapping_fragment>
-    #include <colorspace_fragment>
-    #include <fog_fragment>
-}
-
-

En fouillant dans tous ces extraits, -nous constatons que three.js utilise une variable appelée diffuseColor pour gérer la -couleur de base du matériau. Il la définit dans l'extrait <color_fragment>, -nous devrions donc pouvoir la modifier après ce point.

-

diffuseColor à ce stade du shader devrait déjà être la couleur de -notre texture de contour, nous pouvons donc chercher la couleur dans une texture de palette -et les mélanger pour le résultat final.

-

Comme nous l'avons fait précédemment, nous allons créer un tableau -de chaînes de recherche et de remplacement et les appliquer au shader dans -Material.onBeforeCompile.

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-  indexTexture.minFilter = THREE.NearestFilter;
-  indexTexture.magFilter = THREE.NearestFilter;
-
-  const pickingMaterial = new THREE.MeshBasicMaterial({map: indexTexture});
-  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-+  const fragmentShaderReplacements = [
-+    {
-+      from: '#include <common>',
-+      to: `
-+        #include <common>
-+        uniform sampler2D indexTexture;
-+        uniform sampler2D paletteTexture;
-+        uniform float paletteTextureWidth;
-+      `,
-+    },
-+    {
-+      from: '#include <color_fragment>',
-+      to: `
-+        #include <color_fragment>
-+        {
-+          vec4 indexColor = texture2D(indexTexture, vUv);
-+          float index = indexColor.r * 255.0 + indexColor.g * 255.0 * 256.0;
-+          vec2 paletteUV = vec2((index + 0.5) / paletteTextureWidth, 0.5);
-+          vec4 paletteColor = texture2D(paletteTexture, paletteUV);
-+          // diffuseColor.rgb += paletteColor.rgb;   // white outlines
-+          diffuseColor.rgb = paletteColor.rgb - diffuseColor.rgb;  // black outlines
-+        }
-+      `,
-+    },
-+  ];
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-+  material.onBeforeCompile = function(shader) {
-+    fragmentShaderReplacements.forEach((rep) => {
-+      shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-+    });
-+  };
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

Comme vous pouvez le voir ci-dessus, nous ajoutons 3 uniformes, indexTexture, paletteTexture, -et paletteTextureWidth. Nous obtenons une couleur à partir de indexTexture -et la convertissons en index. vUv sont les coordonnées de texture fournies par -three.js. Nous utilisons ensuite cet index pour obtenir une couleur à partir de la texture de palette. -Nous mélangeons ensuite le résultat avec la diffuseColor actuelle. La diffuseColor -à ce stade est notre texture de contour noir et blanc, donc si nous ajoutons les 2 couleurs, -nous obtiendrons des contours blancs. Si nous soustrayons la couleur diffuse actuelle, nous obtiendrons -des contours noirs.

-

Avant de pouvoir effectuer le rendu, nous devons configurer la texture de palette -et ces 3 uniformes.

-

Pour la texture de palette, elle doit juste être suffisamment large pour -contenir une couleur par pays + une pour l'océan (id = 0). -Il y a 240 et quelques pays. Nous pourrions attendre que la -liste des pays se charge pour obtenir un nombre exact ou le chercher. -Il n'y a pas beaucoup de mal à choisir un nombre plus grand, -donc choisissons 512.

-

Voici le code pour créer la texture de palette

-
const maxNumCountries = 512;
-const paletteTextureWidth = maxNumCountries;
-const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 4);
-const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight);
-paletteTexture.minFilter = THREE.NearestFilter;
-paletteTexture.magFilter = THREE.NearestFilter;
-
-

Une DataTexture nous permet de donner des données brutes à une texture. Dans ce cas, -nous lui donnons 512 couleurs RGBA, 4 octets chacune où chaque octet représente -respectivement le rouge, le vert et le bleu en utilisant des valeurs allant de 0 à 255.

-

Remplissons-la avec des couleurs aléatoires juste pour voir si ça fonctionne

-
for (let i = 1; i < palette.length; ++i) {
-  palette[i] = Math.random() * 256;
-}
-// définir la couleur de l'océan (index #0)
-palette.set([100, 200, 255, 255], 0);
-paletteTexture.needsUpdate = true;
-
-

Chaque fois que nous voulons que three.js mette à jour la texture de palette avec -le contenu du tableau palette, nous devons définir paletteTexture.needsUpdate -sur true.

-

Et ensuite, nous devons toujours définir les uniformes sur le matériau.

-
const geometry = new THREE.SphereGeometry(1, 64, 32);
-const material = new THREE.MeshBasicMaterial({map: texture});
-material.onBeforeCompile = function(shader) {
-  fragmentShaderReplacements.forEach((rep) => {
-    shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-  });
-+  shader.uniforms.paletteTexture = {value: paletteTexture};
-+  shader.uniforms.indexTexture = {value: indexTexture};
-+  shader.uniforms.paletteTextureWidth = {value: paletteTextureWidth};
-};
-scene.add(new THREE.Mesh(geometry, material));
-
-

et avec cela, nous obtenons des pays colorés aléatoirement.

-

- -

-

Maintenant que nous pouvons voir que les textures d'index et de palette fonctionnent, -manipulons la palette pour la mise en évidence.

-

Faisons d'abord une fonction qui nous permettra de passer une couleur de style three.js -et de nous donner les valeurs que nous pouvons mettre dans la texture de palette.

-
const tempColor = new THREE.Color();
-function get255BasedColor(color) {
-  tempColor.set(color);
-  const base = tempColor.toArray().map(v => v * 255);
-  base.push(255); // alpha
-  return base;
-}
-
-

L'appeler comme ceci color = get255BasedColor('red') retournera -un tableau comme [255, 0, 0, 255].

-

Ensuite, utilisons-la pour créer quelques couleurs et remplir la -palette.

-
const selectedColor = get255BasedColor('red');
-const unselectedColor = get255BasedColor('#444');
-const oceanColor = get255BasedColor('rgb(100,200,255)');
-resetPalette();
-
-function setPaletteColor(index, color) {
-  palette.set(color, index * 4);
-}
-
-function resetPalette() {
-  // définir toutes les couleurs sur la couleur non sélectionnée
-  for (let i = 1; i < maxNumCountries; ++i) {
-    setPaletteColor(i, unselectedColor);
-  }
-
-  // définir la couleur de l'océan (index #0)
-  setPaletteColor(0, oceanColor);
-  paletteTexture.needsUpdate = true;
-}
-
-

Maintenant, utilisons ces fonctions pour mettre à jour la palette lorsqu'un pays -est sélectionné

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // sortir si les données ne sont pas encore chargées
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-+    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-+    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-+  resetPalette();
-}
-
-

et avec cela, nous devrions pouvoir mettre en évidence 1 ou plusieurs pays.

-

- -

-

Cela semble fonctionner !

-

Un petit détail est que nous ne pouvons pas faire tourner le globe sans changer -l'état de sélection. Si nous sélectionnons un pays et voulons ensuite -faire pivoter le globe, la sélection changera.

-

Essayons de régler cela. Rapidement, nous pouvons vérifier 2 choses. -Le temps écoulé entre le clic et le lâcher. Une autre est de savoir si -l'utilisateur a réellement déplacé la souris. Si le -temps est court ou s'il n'a pas bougé la souris, c'était -probablement un clic. Sinon, il essayait probablement de -faire glisser le globe.

-
+const maxClickTimeMs = 200;
-+const maxMoveDeltaSq = 5 * 5;
-+const startPosition = {};
-+let startTimeMs;
-+
-+function recordStartTimeAndPosition(event) {
-+  startTimeMs = performance.now();
-+  const pos = getCanvasRelativePosition(event);
-+  startPosition.x = pos.x;
-+  startPosition.y = pos.y;
-+}
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // sortir si les données ne sont pas encore chargées
-  if (!countryInfos) {
-    return;
-  }
-
-+  // s'il s'est écoulé un certain temps depuis que l'utilisateur a commencé
-+  // alors supposer qu'il s'agissait d'une action de glissement, pas de sélection
-+  const clickTimeMs = performance.now() - startTimeMs;
-+  if (clickTimeMs > maxClickTimeMs) {
-+    return;
-+  }
-+
-+  // s'ils ont bougé, supposer qu'il s'agissait d'une action de glissement
-+  const position = getCanvasRelativePosition(event);
-+  const moveDeltaSq = (startPosition.x - position.x) ** 2 +
-+                      (startPosition.y - position.y) ** 2;
-+  if (moveDeltaSq > maxMoveDeltaSq) {
-+    return;
-+  }
-
--  const position = {x: event.clientX, y: event.clientY};
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-  resetPalette();
-}
-
-+canvas.addEventListener('pointerdown', recordStartTimeAndPosition);
-canvas.addEventListener('pointerup', pickCountry);
-
-

et avec ces modifications, il semble que cela fonctionne pour moi.

-

- -

-

Je ne suis pas expert en UX, donc j'aimerais savoir s'il existe une meilleure -solution.

-

J'espère que cela vous a donné une idée de l'utilité des graphiques indexés et de la façon dont vous pouvez modifier les shaders créés par three.js pour ajouter des fonctionnalités simples. L'utilisation de GLSL, le langage dans lequel les shaders sont écrits, est trop vaste pour cet article. Il y a quelques liens vers des informations dans l'article sur le post-traitement.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/installation.html b/manual/fr/installation.html deleted file mode 100644 index 2038c88ba8df8a..00000000000000 --- a/manual/fr/installation.html +++ /dev/null @@ -1,295 +0,0 @@ - - - Installation - - - - - - - - - - - - - -
-
-

Installation

-
-
-
- -

Structure du projet

- -

- Tout projet three.js nécessite au moins un fichier HTML pour définir la page web, et un fichier JavaScript pour exécuter votre code three.js. La structure et les choix de noms ci-dessous ne sont pas obligatoires, mais seront utilisés tout au long de ce guide par souci de cohérence. -

- -
    -
  • - index.html -
    -<!DOCTYPE html>
    -<html lang="en">
    -  <head>
    -    <meta charset="utf-8">
    -    <title>Ma première application three.js</title>
    -    <style>
    -      body { margin: 0; }
    -    </style>
    -  </head>
    -  <body>
    -    <script type="module" src="/main.js"></script>
    -  </body>
    -</html>
    -    
    -
  • -
  • - main.js -
    -import * as THREE from 'three';
    -
    -...
    -
    -
  • -
  • - public/ -
      -
    • - Le dossier public/ est parfois aussi appelé dossier "static", car les fichiers qu'il contient sont poussés vers le site web sans modification. Généralement, les textures, l'audio et les modèles 3D s'y trouvent. -
    • -
    -
  • -
- -

- Maintenant que nous avons mis en place la structure de base du projet, nous avons besoin d'un moyen pour exécuter le projet localement et y accéder via un navigateur web. L'installation et le développement local peuvent être accomplis avec npm et un outil de build, ou en important three.js depuis un CDN. Les deux options sont expliquées dans les sections ci-dessous. -

- -

Option 1 : Installation avec NPM et un outil de build

- -

Développement

- -

- L'installation depuis le [link:https://www.npmjs.com/ registre de packages npm] et l'utilisation d'un [link:https://eloquentjavascript.net/10_modules.html#h_zWTXAU93DC outil de build] est l'approche recommandée pour la plupart des utilisateurs — plus votre projet a de dépendances, plus vous êtes susceptible de rencontrer des problèmes que l'hébergement statique ne peut pas facilement résoudre. Avec un outil de build, l'importation de fichiers JavaScript locaux et de packages npm devrait fonctionner directement, sans cartes d'importation. -

- - -
    -
  1. - Installez [link:https://nodejs.org/ Node.js]. Nous en aurons besoin pour gérer les dépendances et exécuter notre outil de build. -
  2. -
  3. -

    - Installez three.js et un outil de build, [link:https://vitejs.dev/ Vite], en utilisant un [link:https://www.joshwcomeau.com/javascript/terminal-for-js-devs/ terminal] dans le dossier de votre projet. Vite sera utilisé pendant le développement, mais ne fait pas partie de la page web finale. Si vous préférez utiliser un autre outil de build, c'est bien — nous supportons les outils de build modernes qui peuvent importer les [link:https://eloquentjavascript.net/10_modules.html#h_zWTXAU93DC Modules ES]. -

    -
    -# three.js
    -npm install --save three
    -
    -# vite
    -npm install --save-dev vite
    -
    - -
  4. -
  5. - Depuis votre terminal, exécutez : -
    npx vite 
    - -
  6. -
  7. - Si tout s'est bien passé, vous verrez une URL comme http://localhost:5173 apparaître dans votre terminal, et vous pourrez ouvrir cette URL pour voir votre application web. -
  8. -
- -

- La page sera vide — vous êtes prêt à créer une scène. -

- -

- Si vous voulez en savoir plus sur ces outils avant de continuer, consultez : -

- -
    -
  • - [link:https://threejs-journey.com/lessons/local-server three.js journey : Serveur local] -
  • -
  • - [link:https://vitejs.dev/guide/cli.html Vite : Interface en ligne de commande] -
  • -
  • - [link:https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management MDN : Principes de base de la gestion des packages] -
  • -
- -

Production

- -

- Plus tard, lorsque vous serez prêt à déployer votre application web, il vous suffira d'indiquer à Vite d'exécuter une build de production — npx vite build. Tout ce qui est utilisé par l'application sera compilé, optimisé et copié dans le dossier dist/. Le contenu de ce dossier est prêt à être hébergé sur votre site web. -

- -

Option 2 : Importation depuis un CDN

- -

Développement

- -

L'installation sans outils de build nécessitera quelques modifications de la structure du projet donnée ci-dessus.

- -
    -
  1. -

    - Nous avons importé du code depuis 'three' (un package npm) dans main.js, et les navigateurs web ne savent pas ce que cela signifie. Dans index.html, nous devrons ajouter une [link:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap carte d'importation] définissant où obtenir le package. Placez le code ci-dessous à l'intérieur de la balise <head></head>, après les styles. -

    -
    -<script type="importmap">
    -{
    -  "imports": {
    -    "three": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.module.js",
    -    "three/addons/": "https://cdn.jsdelivr.net/npm/three@<version>/examples/jsm/"
    -  }
    -}
    -</script>
    -
    -

    - N'oubliez pas de remplacer <version> par une version réelle de three.js, comme "v0.149.0". La version la plus récente peut être trouvée sur la [link:https://www.npmjs.com/package/three?activeTab=versions liste des versions npm]. -

    -
  2. -
  3. -

    - Nous aurons également besoin d'exécuter un serveur local pour héberger ces fichiers à une URL accessible par le navigateur web. Bien qu'il soit techniquement possible de double-cliquer sur un fichier HTML et de l'ouvrir dans votre navigateur, des fonctionnalités importantes que nous implémenterons plus tard ne fonctionnent pas lorsque la page est ouverte de cette manière, pour des raisons de sécurité. -

    -

    - Installez [link:https://nodejs.org/ Node.js], puis exécutez [link:https://www.npmjs.com/package/serve serve] pour démarrer un serveur local dans le répertoire du projet : -

    -
    npx serve .
    -
  4. -
  5. - Si tout s'est bien passé, vous verrez une URL comme http://localhost:3000 apparaître dans votre terminal, et vous pourrez ouvrir cette URL pour voir votre application web. -
  6. -
- -

- La page sera vide — vous êtes prêt à [link:#manual/introduction/Creating-a-scene créer une scène]. -

- -

- De nombreux autres serveurs statiques locaux sont disponibles — certains utilisent des langages différents au lieu de Node.js, et d'autres sont des applications de bureau. Ils fonctionnent tous fondamentalement de la même manière, et nous avons fourni quelques alternatives ci-dessous. -

- -
- Plus de serveurs locaux - -

Ligne de commande

- -

Les serveurs locaux en ligne de commande s'exécutent depuis une fenêtre de terminal. Le langage de programmation associé peut devoir être installé au préalable.

- -
    -
  • npx http-server (Node.js)
  • -
  • npx five-server (Node.js)
  • -
  • python -m SimpleHTTPServer (Python 2.x)
  • -
  • python -m http.server (Python 3.x)
  • -
  • php -S localhost:8000 (PHP 5.4+)
  • -
- - -

GUI

- -

Les serveurs locaux GUI s'exécutent sous forme de fenêtre d'application sur votre ordinateur, et peuvent avoir une interface utilisateur.

- -
    -
  • [link:https://greggman.github.io/servez Servez]
  • -
- -

Plugins d'éditeur de code

- -

Certains éditeurs de code disposent de plugins qui lancent un simple serveur à la demande.

- -
    -
  • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] pour Visual Studio Code
  • -
  • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] pour Visual Studio Code
  • -
  • [link:https://atom.io/packages/atom-live-server Live Server] pour Atom
  • -
- - -
- -

Production

- -

- Lorsque vous êtes prêt à déployer votre application web, poussez les fichiers source chez votre hébergeur web — pas besoin de build ou de compiler quoi que ce soit. L'inconvénient de ce compromis est que vous devrez veiller à maintenir la carte d'importation à jour avec toutes les dépendances (et les dépendances des dépendances !) dont votre application a besoin. Si le CDN hébergeant vos dépendances tombe temporairement, votre site web cessera également de fonctionner. -

- -

- IMPORTANT : Importez toutes les dépendances depuis la même version de three.js et depuis le même CDN. Mélanger des fichiers de différentes sources peut entraîner l'inclusion de code dupliqué, ou même casser l'application de manière inattendue. -

- -

Addons

- -

- Par défaut, three.js inclut les fondamentaux d'un moteur 3D. Les autres composants de three.js — tels que les contrôles, les chargeurs et les effets de post-traitement — font partie du répertoire [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm addons/]. Les Addons n'ont pas besoin d'être installés séparément, mais doivent être importés séparément. -

- -

- L'exemple ci-dessous montre comment importer three.js avec les addons `OrbitControls` et `GLTFLoader`. Si nécessaire, cela sera également mentionné dans la documentation ou les exemples de chaque addon. -

- -
-import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
-
-const controls = new OrbitControls( camera, renderer.domElement );
-const loader = new GLTFLoader();
-
- -

- D'excellents projets tiers sont également disponibles pour three.js. Ceux-ci doivent être installés séparément — voir Bibliothèques et Plugins. -

- -

Étapes suivantes

- -

- Vous êtes maintenant prêt à créer une scène. -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/libraries-and-plugins.html b/manual/fr/libraries-and-plugins.html deleted file mode 100644 index 0935775a11093d..00000000000000 --- a/manual/fr/libraries-and-plugins.html +++ /dev/null @@ -1,146 +0,0 @@ - - - Bibliothèques et Plugins - - - - - - - - - - - - - -
-
-

Bibliothèques et Plugins

-
-
-
- -

- Voici une liste de bibliothèques et plugins compatibles développés en externe pour three.js. Cette - liste et les paquets associés sont maintenus par la communauté et ne sont pas garantis - d'être à jour. Si vous souhaitez mettre à jour cette liste, faites une Pull Request ! -

- -

Physique

- -
    -
  • [link:https://github.com/lo-th/Oimo.js/ Oimo.js]
  • -
  • [link:https://enable3d.io/ enable3d]
  • -
  • [link:https://github.com/kripken/ammo.js/ ammo.js]
  • -
  • [link:https://github.com/pmndrs/cannon-es cannon-es]
  • -
  • [link:https://rapier.rs/ rapier]
  • -
  • [link:https://github.com/jrouwe/JoltPhysics.js Jolt]
  • - -
- -

Post-traitement

- -

- En plus des [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/postprocessing effets de post-traitement officiels de three.js], - la prise en charge d'effets et de frameworks supplémentaires est disponible via des bibliothèques externes. -

- -
    -
  • [link:https://github.com/vanruesc/postprocessing postprocessing]
  • -
- -

Performance d'Intersection et de Raycast

- -
    -
  • [link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]
  • -
- -

Tracé de chemin

- -
    -
  • [link:https://github.com/gkjohnson/three-gpu-pathtracer three-gpu-pathtracer]
  • -
- -

Formats de fichier

- -

- En plus des [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/loaders chargeurs officiels de three.js], - la prise en charge de formats supplémentaires est disponible via des bibliothèques externes. -

- -
    -
  • [link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]
  • -
  • [link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]
  • -
  • [link:https://github.com/kaisalmen/WWOBJLoader Chargeur OBJ WebWorker]
  • -
  • [link:https://github.com/IFCjs/web-ifc-three IFC.js]
  • -
- -

Géométrie

- -
    -
  • [link:https://github.com/spite/THREE.MeshLine THREE.MeshLine]
  • -
- -

Texte et Mise en page 3D

- -
    -
  • [link:https://github.com/protectwise/troika/tree/master/packages/troika-three-text troika-three-text]
  • -
  • [link:https://github.com/felixmariotto/three-mesh-ui three-mesh-ui]
  • -
- -

Systèmes de particules

- -
    -
  • [link:https://github.com/Alchemist0823/three.quarks three.quarks]
  • -
  • [link:https://github.com/creativelifeform/three-nebula three-nebula]
  • -
- -

Cinématique inverse

- -
    -
  • [link:https://github.com/jsantell/THREE.IK THREE.IK]
  • -
  • [link:https://github.com/lo-th/fullik fullik]
  • -
  • [link:https://github.com/gkjohnson/closed-chain-ik-js closed-chain-ik]
  • -
- -

IA de jeu

- -
    -
  • [link:https://mugen87.github.io/yuka/ yuka]
  • -
  • [link:https://github.com/donmccurdy/three-pathfinding three-pathfinding]
  • -
  • [link:https://github.com/isaac-mason/recast-navigation-js recast-navigation-js]
  • -
- -

Wrappers et Frameworks

- -
    -
  • [link:https://aframe.io/ A-Frame]
  • -
  • [link:https://lume.io/ Lume] - Éléments HTML pour graphismes 3D basés sur Three.
  • -
  • [link:https://github.com/pmndrs/react-three-fiber react-three-fiber] - Composants React pour graphismes 3D basés sur Three.
  • -
  • [link:https://threepipe.org/ threepipe] - Un framework de visualisation 3D polyvalent utilisant three.js pour le rendu.
  • -
  • [link:https://ecsyjs/ecsy-three ECSY]
  • -
  • [link:https://threlte.xyz/ Threlte] - Composants Svelte pour graphismes 3D basés sur Three.
  • -
  • [link:https://needle.tools/ Needle Engine]
  • -
  • [link:https://tresjs.org/ tresjs] - Composants Vue pour graphismes 3D basés sur Three.
  • -
  • [link:https://giro3d.org Giro3D] - Framework polyvalent basé sur Three pour visualiser et interagir avec des données géospatiales 2D, 2.5D et 3D.
  • -
  • [link:https://zap.works/mattercraft/ Mattercraft] - Éditeur visuel basé sur navigateur pour le contenu web AR, WebXR et 3D, construit sur three.js avec aperçu en temps réel et moteur physique.
  • -
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/lights.html b/manual/fr/lights.html deleted file mode 100644 index 304887f22f22b1..00000000000000 --- a/manual/fr/lights.html +++ /dev/null @@ -1,490 +0,0 @@ - - - Lumières - - - - - - - - - - - - - -
-
-

Lumières

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le -premier article est les bases de three.js. Si -vous ne l'avez pas encore lu et que vous débutez avec three.js, vous pourriez envisager de -commencer par là, ainsi que l'article sur la configuration de votre environnement. Le -l'article précédent portait sur les textures.

-

Voyons comment utiliser les différents types de lumières dans three.js.

-

En partant d'un de nos exemples précédents, mettons à jour la caméra. -Nous définirons le champ de vision à 45 degrés, le plan lointain à 100 unités, -et nous déplacerons la caméra de 10 unités vers le haut et de 20 unités vers l'arrière par rapport à l'origine

-
*const fov = 45;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-*const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-+camera.position.set(0, 10, 20);
-
-

Ajoutons ensuite OrbitControls. Les OrbitControls -permettent à l'utilisateur de faire tourner ou d'orbiter la caméra autour d'un point. Les OrbitControls -sont une fonctionnalité optionnelle de three.js, nous devons donc d'abord les inclure -dans notre page

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-

Ensuite, nous pouvons les utiliser. Nous passons aux OrbitControls une caméra à -contrôler et l'élément DOM à utiliser pour obtenir les événements d'entrée

-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 5, 0);
-controls.update();
-
-

Nous définissons également la cible d'orbite à 5 unités au-dessus de l'origine -et appelons ensuite controls.update pour que les contrôles utilisent la nouvelle -cible.

-

Voyons ensuite comment créer des éléments à éclairer. D'abord, nous allons créer un -plan au sol. Nous appliquerons une petite texture en damier de 2x2 pixels qui -ressemble à ceci :

-
- -
- -

Nous chargeons d'abord la texture, la définissons en mode répétition, définissons le filtrage au -plus proche, et définissons le nombre de fois que nous voulons qu'elle se répète. Étant donné que la -texture est un damier de 2x2 pixels, en la répétant et en définissant la -répétition à la moitié de la taille du plan, chaque case du damier -aura exactement 1 unité de taille ;

-
const planeSize = 40;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
-texture.colorSpace = THREE.SRGBColorSpace;
-const repeats = planeSize / 2;
-texture.repeat.set(repeats, repeats);
-
-

Nous créons ensuite une géométrie de plan, un matériau pour le plan et un maillage -pour l'insérer dans la scène. Les plans sont par défaut dans le plan XY, -mais le sol est dans le plan XZ, nous le faisons donc pivoter.

-
const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planeMat = new THREE.MeshPhongMaterial({
-  map: texture,
-  side: THREE.DoubleSide,
-});
-const mesh = new THREE.Mesh(planeGeo, planeMat);
-mesh.rotation.x = Math.PI * -.5;
-scene.add(mesh);
-
-

Ajoutons un cube et une sphère pour avoir 3 éléments à éclairer, y compris le plan.

-
{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-  const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

Maintenant que nous avons une scène à éclairer, ajoutons des lumières !

-

AmbientLight

-

Commençons par créer une Lumière Ambiante

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.AmbientLight(color, intensity);
-scene.add(light);
-
-

Faisons en sorte de pouvoir également ajuster les paramètres de la lumière. -Nous utiliserons de nouveau lil-gui. -Pour pouvoir ajuster la couleur via lil-gui, nous avons besoin d'un petit assistant -qui présente une propriété à lil-gui qui ressemble à une chaîne de couleur hexadécimale CSS -(par ex. : #FF8844). Notre assistant obtiendra la couleur d'une propriété nommée, -la convertira en chaîne hexadécimale pour l'offrir à lil-gui. -Lorsque lil-gui essaiera de définir la propriété de l'assistant, nous assignerons le résultat à la -couleur de la lumière.

-

Voici l'assistant :

-
class ColorGUIHelper {
-  constructor(object, prop) {
-    this.object = object;
-    this.prop = prop;
-  }
-  get value() {
-    return '#' + this.object[this.prop].getHexString();
-  }
-  set value(hexString) {
-    this.object[this.prop].set(hexString);
-  }
-}
-
-

Et voici notre code de configuration de lil-gui

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

Et voici le résultat

-

- -

-

Cliquez et faites glisser dans la scène pour faire orbiter la caméra.

-

Remarquez qu'il n'y a pas de définition. Les formes sont plates. La Lumière Ambiante -multiplie simplement la couleur du matériau par la couleur de la lumière multipliée par l' -intensité.

-
color = materialColor * light.color * light.intensity;
-

C'est tout. Elle n'a pas de direction. -Ce style d'éclairage ambiant n'est pas très utile en tant qu'éclairage car il est -uniformément réparti, donc à part changer la couleur -de tout dans la scène, il ne ressemble pas beaucoup à un éclairage. -Ce qui aide, c'est qu'il rend les zones sombres moins sombres.

-

HemisphereLight

-

Passons au code pour une Lumière Hémisphérique. Une Lumière Hémisphérique -prend une couleur de ciel et une couleur de sol et multiplie simplement la -couleur du matériau entre ces 2 couleurs — la couleur du ciel si la -surface de l'objet pointe vers le haut et la couleur du sol si -la surface de l'objet pointe vers le bas.

-

Voici le nouveau code

-
-const color = 0xFFFFFF;
-+const skyColor = 0xB1E1FF;  // light blue
-+const groundColor = 0xB97A20;  // brownish orange
-const intensity = 1;
--const light = new THREE.AmbientLight(color, intensity);
-+const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
-scene.add(light);
-
-

Mettons également à jour le code lil-gui pour éditer les deux couleurs

-
const gui = new GUI();
--gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-+gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur du ciel');
-+gui.addColor(new ColorGUIHelper(light, 'groundColor'), 'value').name('couleur du sol');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

Le résultat :

-

- -

-

Remarquez de nouveau qu'il n'y a presque pas de définition, tout semble un peu -plat. La Lumière Hémisphérique utilisée en combinaison avec une autre lumière -peut aider à donner une belle influence de la couleur du -ciel et du sol. De cette façon, elle est mieux utilisée en combinaison avec une -autre lumière ou en substitut d'une Lumière Ambiante.

-

DirectionalLight

-

Passons au code pour une Lumière Directionnelle. -Une Lumière Directionnelle est souvent utilisée pour représenter le soleil.

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.DirectionalLight(color, intensity);
-light.position.set(0, 10, 0);
-light.target.position.set(-5, 0, 0);
-scene.add(light);
-scene.add(light.target);
-
-

Remarquez que nous avons dû ajouter la light et la light.target -à la scène. Une Lumière Directionnelle three.js -brillera dans la direction de sa cible.

-

Faisons en sorte de pouvoir déplacer la cible en l'ajoutant à -notre interface GUI.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur');
-gui.add(light, 'intensity', 0, 5, 0.01);
-gui.add(light.target.position, 'x', -10, 10);
-gui.add(light.target.position, 'z', -10, 10);
-gui.add(light.target.position, 'y', 0, 10);
-
-

- -

-

Il est un peu difficile de voir ce qui se passe. Three.js dispose d'un ensemble -d'objets d'aide que nous pouvons ajouter à notre scène pour aider à visualiser -les parties invisibles d'une scène. Dans ce cas, nous utiliserons le -Helper de Lumière Directionnelle qui dessinera un plan, pour représenter -la lumière, et une ligne de la lumière à la cible. Nous lui -passons simplement la lumière et l'ajoutons à la scène.

-
const helper = new THREE.DirectionalLightHelper(light);
-scene.add(helper);
-
-

Pendant que nous y sommes, faisons en sorte de pouvoir définir à la fois la position -de la lumière et la cible. Pour ce faire, nous allons créer une fonction -qui, étant donné un Vector3, ajustera ses propriétés x, y, et z -en utilisant lil-gui.

-
function makeXYZGUI(gui, vector3, name, onChangeFn) {
-  const folder = gui.addFolder(name);
-  folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
-  folder.add(vector3, 'y', 0, 10).onChange(onChangeFn);
-  folder.add(vector3, 'z', -10, 10).onChange(onChangeFn);
-  folder.open();
-}
-
-

Notez que nous devons appeler la fonction update de l'assistant -chaque fois que nous changeons quelque chose afin que l'assistant sache qu'il doit se mettre à -jour. Ainsi, nous passons une fonction onChangeFn qui sera -appelée chaque fois que lil-gui met à jour une valeur.

-

Ensuite, nous pouvons l'utiliser à la fois pour la position de la lumière -et pour la position de la cible, comme ceci

-
+function updateLight() {
-+  light.target.updateMatrixWorld();
-+  helper.update();
-+}
-+updateLight();
-
-const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-+makeXYZGUI(gui, light.position, 'position', updateLight);
-+makeXYZGUI(gui, light.target.position, 'cible', updateLight);
-
-

Nous pouvons maintenant déplacer la lumière, et sa cible

-

- -

-

Faites orbiter la caméra et il devient plus facile de voir. Le plan -représente une Lumière Directionnelle car une lumière directionnelle -calcule la lumière venant dans une seule direction. Il n'y a pas de -point d'où la lumière provient, c'est un plan infini de lumière -émettant des rayons parallèles.

-

PointLight

-

Une Lumière Ponctuelle est une lumière qui se situe à un point et projette de la lumière -dans toutes les directions à partir de ce point. Modifions le code.

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.PointLight(color, intensity);
-light.position.set(0, 10, 0);
--light.target.position.set(-5, 0, 0);
-scene.add(light);
--scene.add(light.target);
-
-

Passons également à un Helper de Lumière Ponctuelle

-
-const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.PointLightHelper(light);
-scene.add(helper);
-
-

et comme il n'y a pas de cible, la fonction onChange peut être plus simple.

-
function updateLight() {
--  light.target.updateMatrixWorld();
-  helper.update();
-}
--updateLight();
-
-

Notez qu'à un certain niveau, un Helper de Lumière Ponctuelle n'a pas de... point. -Il dessine simplement un petit losange en fil de fer. Cela pourrait tout aussi facilement -être n'importe quelle forme que vous souhaitez, il suffit d'ajouter un maillage à la lumière elle-même.

-

Une Lumière Ponctuelle a la propriété supplémentaire de distance. -Si la distance est 0, alors la Lumière Ponctuelle brille à -l'infini. Si la distance est supérieure à 0, alors la lumière brille -à pleine intensité au niveau de la lumière et s'estompe jusqu'à ne plus avoir d'influence à -distance unités de distance de la lumière.

-

Configurons l'interface GUI pour que nous puissions ajuster la distance.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur');
-gui.add(light, 'intensity', 0, 250, 1);
-+gui.add(light, 'distance', 0, 40).onChange(updateLight);
-
-makeXYZGUI(gui, light.position, 'position', updateLight);
--makeXYZGUI(gui, light.target.position, 'target', updateLight);
-
-

Et maintenant, essayez.

-

- -

-

Remarquez quand distance est > 0 comment la lumière s'estompe.

-

SpotLight

-

Les projecteurs sont effectivement une lumière ponctuelle avec un cône -attaché où la lumière ne brille qu'à l'intérieur du cône. -Il y a en fait 2 cônes. Un cône extérieur et un cône intérieur. -Entre le cône intérieur et le cône extérieur, la -lumière s'estompe de la pleine intensité à zéro.

-

Pour utiliser une Projecteur, nous avons besoin d'une cible, tout comme -pour la lumière directionnelle. Le cône de la lumière s'ouvrira -vers la cible.

-

En modifiant notre Lumière Directionnelle avec l'assistant d'en haut

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.SpotLight(color, intensity);
-scene.add(light);
-scene.add(light.target);
-
--const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.SpotLightHelper(light);
-scene.add(helper);
-
-

L'angle du cône du projecteur est défini avec la propriété angle -en radians. Nous utiliserons notre DegRadHelper de l'article sur les textures -pour présenter une interface utilisateur en -degrés.

-
gui.add(new DegRadHelper(light, 'angle'), 'value', 0, 90).name('angle').onChange(updateLight);
-
-

Le cône intérieur est défini en réglant la propriété pénombre -comme un pourcentage à partir du cône extérieur. En d'autres termes, quand penumbra est 0, alors le -cône intérieur a la même taille (0 = aucune différence) que le cône extérieur. Quand la -penumbra est 1, alors la lumière s'estompe en partant du centre du cône jusqu'au -cône extérieur. Quand penumbra est 0,5, alors la lumière s'estompe en partant de 50 % entre -le centre du cône extérieur.

-
gui.add(light, 'penumbra', 0, 1, 0.01);
-
-

- -

-

Remarquez qu'avec la penumbra par défaut de 0, le projecteur a un bord très net, -tandis que lorsque vous ajustez la penumbra vers 1, le bord devient flou.

-

Il peut être difficile de voir le cône du projecteur. La raison est qu'il est -en dessous du sol. Raccourcissez la distance à environ 5 et vous verrez l'extrémité ouverte -du cône.

-

RectAreaLight

-

Il existe un autre type de lumière, la Lumière Rectangulaire, qui représente -exactement ce à quoi cela ressemble : une zone rectangulaire de lumière, comme un long -néon fluorescent ou peut-être une lucarne dépolie dans un plafond.

-

La Lumière Rectangulaire ne fonctionne qu'avec les matériaux MeshStandardMaterial et -MeshPhysicalMaterial, nous allons donc changer tous nos matériaux en MeshStandardMaterial

-
  ...
-
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
--  const planeMat = new THREE.MeshPhongMaterial({
-+  const planeMat = new THREE.MeshStandardMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  mesh.rotation.x = Math.PI * -.5;
-  scene.add(mesh);
-}
-{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-- const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-+ const cubeMat = new THREE.MeshStandardMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
--  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-+ const sphereMat = new THREE.MeshStandardMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

Pour utiliser la Lumière Rectangulaire, nous devons inclure des données optionnelles supplémentaires de three.js et nous inclurons le -Helper de Lumière Rectangulaire pour nous aider à visualiser la lumière

-
import * as THREE from 'three';
-+import {RectAreaLightUniformsLib} from 'three/addons/lights/RectAreaLightUniformsLib.js';
-+import {RectAreaLightHelper} from 'three/addons/helpers/RectAreaLightHelper.js';
-
-

et nous devons appeler RectAreaLightUniformsLib.init

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  RectAreaLightUniformsLib.init();
-
-

Si vous oubliez les données, la lumière fonctionnera toujours mais elle aura un aspect étrange, alors -n'oubliez pas d'inclure les données supplémentaires.

-

Nous pouvons maintenant créer la lumière

-
const color = 0xFFFFFF;
-*const intensity = 5;
-+const width = 12;
-+const height = 4;
-*const light = new THREE.RectAreaLight(color, intensity, width, height);
-light.position.set(0, 10, 0);
-+light.rotation.x = THREE.MathUtils.degToRad(-90);
-scene.add(light);
-
-*const helper = new RectAreaLightHelper(light);
-*light.add(helper);
-
-

Une chose à noter est que, contrairement à la Lumière Directionnelle et au Projecteur, la -Lumière Rectangulaire n'utilise pas de cible. Elle utilise simplement sa rotation. Une autre chose -à noter est que l'assistant doit être un enfant de la lumière. Il n'est pas un enfant de la -scène comme les autres assistants.

-

Ajustons également l'interface GUI. Nous allons faire en sorte de pouvoir faire pivoter la lumière et ajuster -sa width et sa height

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('couleur');
-gui.add(light, 'intensity', 0, 10, 0.01);
-gui.add(light, 'width', 0, 20);
-gui.add(light, 'height', 0, 20);
-gui.add(new DegRadHelper(light.rotation, 'x'), 'value', -180, 180).name('rotation x');
-gui.add(new DegRadHelper(light.rotation, 'y'), 'value', -180, 180).name('rotation y');
-gui.add(new DegRadHelper(light.rotation, 'z'), 'value', -180, 180).name('rotation z');
-
-makeXYZGUI(gui, light.position, 'position');
-
-

Et voici cela.

-

- -

-

Il est important de noter que chaque lumière que vous ajoutez à la scène ralentit la vitesse -de rendu de la scène par three.js, vous devriez donc toujours essayer d'en -utiliser le moins possible pour atteindre vos objectifs.

-

Ensuite, passons à la gestion des caméras.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/load-gltf.html b/manual/fr/load-gltf.html deleted file mode 100644 index fc6661e871e17e..00000000000000 --- a/manual/fr/load-gltf.html +++ /dev/null @@ -1,588 +0,0 @@ - - - Chargement d'un fichier .GLTF - - - - - - - - - - - - - -
-
-

Chargement d'un fichier .GLTF

-
-
-
-

Dans une leçon précédente, nous avons chargé un fichier .OBJ. Si vous ne l'avez pas lue, vous pourriez vouloir la consulter d'abord.

-

Comme indiqué là-bas, le format de fichier .OBJ est très ancien et assez simple. Il ne fournit aucun graphe de scène, donc tout ce qui est chargé est un seul grand maillage. Il a été conçu principalement comme un moyen simple de passer des données entre des éditeurs 3D.

-

Le format gLTF est en réalité un format conçu dès le départ pour être utilisé pour afficher des graphiques. Les formats 3D peuvent être divisés en 3 ou 4 types de base.

-
    -
  • Formats d'éditeurs 3D

    -

    Ce sont des formats spécifiques à une seule application. .blend (Blender), .max (3d Studio Max), .mb et .ma (Maya), etc...

    -
  • -
  • Formats d'échange

    -

    Ce sont des formats comme .OBJ, .DAE (Collada), .FBX. Ils sont conçus pour aider à échanger des informations entre les éditeurs 3D. En tant que tels, ils sont généralement beaucoup plus volumineux que nécessaire avec des informations supplémentaires utilisées uniquement à l'intérieur des éditeurs 3D.

    -
  • -
  • Formats d'application

    -

    Ceux-ci sont généralement spécifiques à certaines applications, généralement des jeux.

    -
  • -
  • Formats de transmission

    -

    gLTF pourrait être le premier véritable format de transmission. Je suppose que VRML pourrait être considéré comme tel, mais VRML était en réalité un très mauvais format.

    -

    gLTF est conçu pour bien faire certaines choses que tous ces autres formats ne font pas

    -
      -
    1. Être petit pour la transmission

      -

      Par exemple, cela signifie qu'une grande partie de leurs données volumineuses, comme les sommets, est stockée en binaire. Lorsque vous téléchargez un fichier .gLTF, ces données peuvent être téléchargées sur le GPU sans aucun traitement. Elles sont prêtes telles quelles. C'est en contraste avec, par exemple, VRML, .OBJ ou .DAE où les sommets sont stockés sous forme de texte et doivent être analysés. Les positions de sommets en texte peuvent facilement être 3 à 5 fois plus volumineuses qu'en binaire.

      -
    2. -
    3. Être prêt à être rendu

      -

      C'est encore différent des autres formats, sauf peut-être les formats d'application. Les données d'un fichier glTF sont destinées à être rendues, pas éditées. Les données qui ne sont pas importantes pour le rendu ont généralement été supprimées. Les polygones ont été convertis en triangles. Les matériaux ont des valeurs connues qui sont censées fonctionner partout.

      -
    4. -
    -
  • -
-

gLTF a été spécifiquement conçu pour que vous puissiez télécharger un fichier glTF et l'afficher avec un minimum de problèmes. Croisons les doigts pour que ce soit vraiment le cas, car aucun autre format n'a été capable de faire cela.

-

Je n'étais pas vraiment sûr de ce que je devais montrer. À un certain niveau, le chargement et l'affichage d'un fichier gLTF sont plus simples qu'un fichier .OBJ. Contrairement à un fichier .OBJ, les matériaux font directement partie du format. Cela dit, j'ai pensé que je devais au moins en charger un et je pense qu'examiner les problèmes que j'ai rencontrés pourrait fournir de bonnes informations.

-

En cherchant sur le net, j'ai trouvé cette ville low-poly par antonmoek qui semblait, si nous avons de la chance, faire un bon exemple.

-
- -

En partant d'un exemple de l'article sur les fichiers .OBJ, j'ai supprimé le code de chargement de .OBJ et je l'ai remplacé par le code de chargement de .GLTF.

-

L'ancien code .OBJ était

-
const mtlLoader = new MTLLoader();
-mtlLoader.loadMtl('resources/models/windmill/windmill-fixed.mtl', (mtl) => {
-  mtl.preload();
-  mtl.materials.Material.side = THREE.DoubleSide;
-  objLoader.setMaterials(mtl);
-  objLoader.load('resources/models/windmill/windmill.obj', (event) => {
-    const root = event.detail.loaderRootNode;
-    scene.add(root);
-    ...
-  });
-});
-
-

Le nouveau code .GLTF est

-
{
-  const gltfLoader = new GLTFLoader();
-  const url = 'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf';
-  gltfLoader.load(url, (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-    ...
-  });
-
-

J'ai gardé le code de cadrage automatique comme auparavant.

-

Nous devons également inclure le GLTFLoader et nous pouvons nous débarrasser du OBJLoader.

-
-import {LoaderSupport} from 'three/addons/loaders/LoaderSupport.js';
--import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
--import {MTLLoader} from 'three/addons/loaders/MTLLoader.js';
-+import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
-
-

Et en exécutant cela, nous obtenons

-

- -

-

Magie ! Ça fonctionne tout seul, textures comprises.

-

Ensuite, je voulais voir si je pouvais animer les voitures qui circulent, j'ai donc eu besoin de vérifier si la scène avait les voitures comme entités séparées et si elles étaient configurées d'une manière que je pouvais utiliser.

-

J'ai écrit du code pour afficher le graphe de scène dans la console JavaScript.

-

Voici le code pour imprimer le graphe de scène.

-
function dumpObject(obj, lines = [], isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

Et je l'ai appelée juste après avoir chargé la scène.

-
const gltfLoader = new GLTFLoader();
-gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-  const root = gltf.scene;
-  scene.add(root);
-  console.log(dumpObject(root).join('\n'));
-
-

En exécutant cela, j'ai obtenu cette liste

-
OSG_Scene [Scene]
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    └─RootNode_(model_correction_matrix) [Object3D]
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        └─RootNode [Object3D]
-          │ ...
-          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-          │ ├─CAR_03_2 [Object3D]
-          │ │ └─CAR_03_2_World_ap_0 [Mesh]
-          │ ├─Car_04_1 [Object3D]
-          │ │ └─Car_04_1_World_ap_0 [Mesh]
-          │ ├─Car_04_2 [Object3D]
-          │ │ └─Car_04_2_World_ap_0 [Mesh]
-          │ ├─Car_04_3 [Object3D]
-          │ │ └─Car_04_3_World_ap_0 [Mesh]
-          │ ├─Car_04_4 [Object3D]
-          │ │ └─Car_04_4_World_ap_0 [Mesh]
-          │ ├─Car_08_4 [Object3D]
-          │ │ └─Car_08_4_World_ap8_0 [Mesh]
-          │ ├─Car_08_3 [Object3D]
-          │ │ └─Car_08_3_World_ap9_0 [Mesh]
-          │ ├─Car_04_1_2 [Object3D]
-          │ │ └─Car_04_1_2_World_ap_0 [Mesh]
-          │ ├─Car_08_2 [Object3D]
-          │ │ └─Car_08_2_World_ap11_0 [Mesh]
-          │ ├─CAR_03_1_2 [Object3D]
-          │ │ └─CAR_03_1_2_World_ap_0 [Mesh]
-          │ ├─CAR_03_2_2 [Object3D]
-          │ │ └─CAR_03_2_2_World_ap_0 [Mesh]
-          │ ├─Car_04_2_2 [Object3D]
-          │ │ └─Car_04_2_2_World_ap_0 [Mesh]
-          ...
-
-

À partir de cela, nous pouvons voir que toutes les voitures se trouvent sous un parent appelé "Cars".

-
*          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-
-

Donc, comme test simple, j'ai pensé que j'essaierais juste de faire tourner tous les enfants du nœud "Cars" autour de leur axe Y.

-

J'ai cherché le nœud "Cars" après avoir chargé la scène et j'ai sauvegardé le résultat.

-
+let cars;
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-+    cars = root.getObjectByName('Cars');
-
-

Ensuite, dans la fonction render, nous pouvons simplement définir la rotation de chaque enfant de cars.

-
+function render(time) {
-+  time *= 0.001;  // convertir en secondes
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (cars) {
-+    for (const car of cars.children) {
-+      car.rotation.y = time;
-+    }
-+  }
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

Et nous obtenons

-

- -

-

Hmmm, il semble que malheureusement cette scène n'a pas été conçue pour animer les voitures, car leurs origines ne sont pas configurées à cette fin. Les camions tournent dans la mauvaise direction.

-

Cela soulève un point important : si vous allez faire quelque chose en 3D, vous devez planifier à l'avance et concevoir vos éléments de manière à ce que leurs origines soient aux bons endroits, qu'ils aient la bonne échelle, etc.

-

Comme je ne suis pas un artiste et que je ne connais pas très bien Blender, je vais bricoler cet exemple. Nous allons prendre chaque voiture et la faire appartenir à un autre Object3D. Nous allons ensuite déplacer ces objets Object3D pour déplacer les voitures, mais séparément, nous pouvons définir l'Object3D d'origine de la voiture pour la réorienter afin qu'elle soit à peu près là où nous en avons vraiment besoin.

-

En regardant à nouveau la liste du graphe de scène, il semble qu'il n'y ait en réalité que 3 types de voitures : "Car_08", "CAR_03" et "Car_04". Espérons que chaque type de voiture fonctionnera avec les mêmes ajustements.

-

J'ai écrit ce code pour passer en revue chaque voiture, la faire appartenir à un nouvel Object3D, faire appartenir ce nouvel Object3D à la scène, appliquer des paramètres par *type* de voiture pour corriger son orientation, et ajouter le nouvel Object3D à un tableau cars.

-
-let cars;
-+const cars = [];
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
--    cars = root.getObjectByName('Cars');
-+    const loadedCars = root.getObjectByName('Cars');
-+    const fixes = [
-+      { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
-+      { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
-+      { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+    ];
-+
-+    root.updateMatrixWorld();
-+    for (const car of loadedCars.children.slice()) {
-+      const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-+      const obj = new THREE.Object3D();
-+      car.getWorldPosition(obj.position);
-+      car.position.set(0, 0, 0);
-+      car.rotation.set(...fix.rot);
-+      obj.add(car);
-+      scene.add(obj);
-+      cars.push(obj);
-+    }
-     ...
-
-

Cela corrige l'orientation des voitures.

-

- -

-

Maintenant, faisons-les rouler.

-

Faire même un simple système de conduite est trop pour ce post, mais il semble qu'au lieu de cela, nous pourrions simplement créer un chemin alambiqué qui parcourt toutes les routes, puis placer les voitures sur ce chemin. Voici une image de Blender à mi-chemin de la construction du chemin.

-
- -

J'avais besoin d'un moyen d'obtenir les données de ce chemin depuis Blender. Heureusement, j'ai pu sélectionner juste mon chemin et exporter en .OBJ en cochant "write nurbs".

-
- -

En ouvrant le fichier .OBJ, j'ai pu obtenir une liste de points que j'ai formatée ainsi

-
const controlPoints = [
-  [1.118281, 5.115846, -3.681386],
-  [3.948875, 5.115846, -3.641834],
-  [3.960072, 5.115846, -0.240352],
-  [3.985447, 5.115846, 4.585005],
-  [-3.793631, 5.115846, 4.585006],
-  [-3.826839, 5.115846, -14.736200],
-  [-14.542292, 5.115846, -14.765865],
-  [-14.520929, 5.115846, -3.627002],
-  [-5.452815, 5.115846, -3.634418],
-  [-5.467251, 5.115846, 4.549161],
-  [-13.266233, 5.115846, 4.567083],
-  [-13.250067, 5.115846, -13.499271],
-  [4.081842, 5.115846, -13.435463],
-  [4.125436, 5.115846, -5.334928],
-  [-14.521364, 5.115846, -5.239871],
-  [-14.510466, 5.115846, 5.486727],
-  [5.745666, 5.115846, 5.510492],
-  [5.787942, 5.115846, -14.728308],
-  [-5.423720, 5.115846, -14.761919],
-  [-5.373599, 5.115846, -3.704133],
-  [1.004861, 5.115846, -3.641834],
-];
-
-

THREE.js possède des classes de courbes. La CatmullRomCurve3 semblait pouvoir fonctionner. L'intérêt de ce type de courbe est qu'elle essaie de créer une courbe lisse passant par les points.

-

En fait, l'insertion directe de ces points générera une courbe comme celle-ci

-
- -

mais nous voulons des coins plus marqués. Il semblait que si nous calculions des points supplémentaires, nous pourrions obtenir ce que nous voulons. Pour chaque paire de points, nous allons calculer un point à 10 % du chemin entre les 2 points et un autre à 90 % du chemin entre les 2 points, et passer le résultat à CatmullRomCurve3.

-

Cela nous donnera une courbe comme celle-ci

-
- -

Voici le code pour créer la courbe

-
let curve;
-let curveObject;
-{
-  const controlPoints = [
-    [1.118281, 5.115846, -3.681386],
-    [3.948875, 5.115846, -3.641834],
-    [3.960072, 5.115846, -0.240352],
-    [3.985447, 5.115846, 4.585005],
-    [-3.793631, 5.115846, 4.585006],
-    [-3.826839, 5.115846, -14.736200],
-    [-14.542292, 5.115846, -14.765865],
-    [-14.520929, 5.115846, -3.627002],
-    [-5.452815, 5.115846, -3.634418],
-    [-5.467251, 5.115846, 4.549161],
-    [-13.266233, 5.115846, 4.567083],
-    [-13.250067, 5.115846, -13.499271],
-    [4.081842, 5.115846, -13.435463],
-    [4.125436, 5.115846, -5.334928],
-    [-14.521364, 5.115846, -5.239871],
-    [-14.510466, 5.115846, 5.486727],
-    [5.745666, 5.115846, 5.510492],
-    [5.787942, 5.115846, -14.728308],
-    [-5.423720, 5.115846, -14.761919],
-    [-5.373599, 5.115846, -3.704133],
-    [1.004861, 5.115846, -3.641834],
-  ];
-  const p0 = new THREE.Vector3();
-  const p1 = new THREE.Vector3();
-  curve = new THREE.CatmullRomCurve3(
-    controlPoints.map((p, ndx) => {
-      p0.set(...p);
-      p1.set(...controlPoints[(ndx + 1) % controlPoints.length]);
-      return [
-        (new THREE.Vector3()).copy(p0),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.1),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.9),
-      ];
-    }).flat(),
-    true,
-  );
-  {
-    const points = curve.getPoints(250);
-    const geometry = new THREE.BufferGeometry().setFromPoints(points);
-    const material = new THREE.LineBasicMaterial({color: 0xff0000});
-    curveObject = new THREE.Line(geometry, material);
-    scene.add(curveObject);
-  }
-}
-
-

La première partie de ce code crée une courbe. La deuxième partie de ce code génère 250 points à partir de la courbe, puis crée un objet pour afficher les lignes formées en connectant ces 250 points.

-

En exécutant l'exemple, je n'ai pas vu la courbe. Pour la rendre visible, je l'ai fait ignorer le test de profondeur et la rendre en dernier.

-
    curveObject = new THREE.Line(geometry, material);
-+    material.depthTest = false;
-+    curveObject.renderOrder = 1;
-
-

Et c'est là que j'ai découvert qu'elle était beaucoup trop petite.

-
- -

En vérifiant la hiérarchie dans Blender, j'ai découvert que l'artiste avait mis à l'échelle le nœud parent de toutes les voitures.

-
- -

La mise à l'échelle est mauvaise pour les applications 3D en temps réel. Elle cause toutes sortes de problèmes et finit par être une source de frustration infinie lors de la création d'applications 3D en temps réel. Les artistes ne le savent souvent pas car il est si facile de mettre à l'échelle une scène entière dans un programme d'édition 3D, mais si vous décidez de créer une application 3D en temps réel, je vous suggère de demander à vos artistes de ne jamais rien mettre à l'échelle. S'ils modifient l'échelle, ils devraient trouver un moyen d'appliquer cette échelle aux sommets afin que, lorsqu'elle arrive dans votre application, vous puissiez ignorer l'échelle.

-

Et, pas seulement l'échelle, dans ce cas, les voitures sont tournées et décalées par leur parent, le nœud Cars. Cela rendra difficile au moment de l'exécution de déplacer les voitures dans l'espace mondial. Pour être clair, dans ce cas, nous voulons que les voitures circulent dans l'espace mondial, c'est pourquoi ces problèmes se posent. Si quelque chose est destiné à être manipulé dans un espace local, comme la lune tournant autour de la terre, c'est moins problématique.

-

Pour en revenir à la fonction que nous avons écrite ci-dessus pour afficher le graphe de scène, affichons la position, la rotation et l'échelle de chaque nœud.

-
+function dumpVec3(v3, precision = 3) {
-+  return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
-+}
-
-function dumpObject(obj, lines, isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-+  const dataPrefix = obj.children.length
-+     ? (isLast ? '  │ ' : '│ │ ')
-+     : (isLast ? '    ' : '│   ');
-+  lines.push(`${prefix}${dataPrefix}  pos: ${dumpVec3(obj.position)}`);
-+  lines.push(`${prefix}${dataPrefix}  rot: ${dumpVec3(obj.rotation)}`);
-+  lines.push(`${prefix}${dataPrefix}  scl: ${dumpVec3(obj.scale)}`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

Et le résultat de l'exécution

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-        └─RootNode [Object3D]
-          │   pos: 0.000, 0.000, 0.000
-          │   rot: 0.000, 0.000, 0.000
-          │   scl: 1.000, 1.000, 1.000
-          ├─Cars [Object3D]
-*          │ │   pos: -369.069, -90.704, -920.159
-*          │ │   rot: 0.000, 0.000, 0.000
-*          │ │   scl: 1.000, 1.000, 1.000
-          │ ├─CAR_03_1 [Object3D]
-          │ │ │   pos: 22.131, 14.663, -475.071
-          │ │ │   rot: -3.142, 0.732, 3.142
-          │ │ │   scl: 1.500, 1.500, 1.500
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ │       pos: 0.000, 0.000, 0.000
-          │ │       rot: 0.000, 0.000, 0.000
-          │ │       scl: 1.000, 1.000, 1.000
-
-

Cela nous montre que l'Cars dans la scène originale a vu sa rotation et son échelle supprimées et appliquées à ses enfants. Cela suggère que soit l'exportateur utilisé pour créer le fichier .GLTF a fait un travail spécial ici, soit plus probablement l'artiste a exporté une version différente du fichier que le fichier .blend correspondant, ce qui explique pourquoi les choses ne correspondent pas.

-

La morale de l'histoire est que j'aurais probablement dû télécharger le fichier .blend et exporter moi-même. Avant d'exporter, j'aurais dû inspecter tous les nœuds principaux et supprimer toute transformation.

-

Tous ces nœuds en haut

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-
-

sont également un gaspillage.

-

Idéalement, la scène devrait se composer d'un seul nœud "racine" sans position, rotation ou échelle. Au moment de l'exécution, je pourrais alors retirer tous les enfants de cette racine et les faire appartenir à la scène elle-même. Il pourrait y avoir des enfants de la racine comme "Cars" qui m'aideraient à trouver toutes les voitures, mais idéalement, il n'aurait pas non plus de translation, rotation ou échelle afin que je puisse rattacher les voitures à la scène avec un minimum de travail.

-

En tout cas, la solution la plus rapide, même si ce n'est peut-être pas la meilleure, est de simplement ajuster l'objet que nous utilisons pour visualiser la courbe.

-

Voici ce que j'ai obtenu au final.

-

D'abord, j'ai ajusté la position de la courbe et trouvé des valeurs qui semblaient fonctionner. Je l'ai ensuite cachée.

-
{
-  const points = curve.getPoints(250);
-  const geometry = new THREE.BufferGeometry().setFromPoints(points);
-  const material = new THREE.LineBasicMaterial({color: 0xff0000});
-  curveObject = new THREE.Line(geometry, material);
-+  curveObject.scale.set(100, 100, 100);
-+  curveObject.position.y = -621;
-+  curveObject.visible = false;
-  material.depthTest = false;
-  curveObject.renderOrder = 1;
-  scene.add(curveObject);
-}
-
-

Ensuite, j'ai écrit du code pour déplacer les voitures le long de la courbe. Pour chaque voiture, nous choisissons une position de 0 à 1 le long de la courbe et calculons un point dans l'espace mondial en utilisant l'curveObject pour transformer le point. Nous choisissons ensuite un autre point légèrement plus loin sur la courbe. Nous définissons l'orientation de la voiture en utilisant lookAt et plaçons la voiture au point médian entre les 2 points.

-
// créer 2 Vector3 que nous pouvons utiliser pour les calculs de chemin
-const carPosition = new THREE.Vector3();
-const carTarget = new THREE.Vector3();
-
-function render(time) {
-  ...
-
--  for (const car of cars) {
--    car.rotation.y = time;
--  }
-
-+  {
-+    const pathTime = time * .01;
-+    const targetOffset = 0.01;
-+    cars.forEach((car, ndx) => {
-+      // un nombre entre 0 et 1 pour espacer uniformément les voitures
-+      const u = pathTime + ndx / cars.length;
-+
-+      // obtenir le premier point
-+      curve.getPointAt(u % 1, carPosition);
-+      carPosition.applyMatrix4(curveObject.matrixWorld);
-+
-+      // obtenir un deuxième point légèrement plus loin sur la courbe
-+      curve.getPointAt((u + targetOffset) % 1, carTarget);
-+      carTarget.applyMatrix4(curveObject.matrixWorld);
-+
-+      // placer la voiture au premier point (temporairement)
-+      car.position.copy(carPosition);
-+      // orienter la voiture vers le deuxième point
-+      car.lookAt(carTarget);
-+
-+      // placer la voiture entre les 2 points
-+      car.position.lerpVectors(carPosition, carTarget, 0.5);
-+    });
-+  }
-
-

et quand je l'ai exécuté, j'ai découvert que pour chaque type de voiture, leur hauteur au-dessus de leurs origines n'est pas définie de manière cohérente, et j'ai donc dû décaler chacune un peu.

-
const loadedCars = root.getObjectByName('Cars');
-const fixes = [
--  { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
--  { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
--  { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_08', y: 0,  rot: [Math.PI * .5, 0, Math.PI * .5], },
-+  { prefix: 'CAR_03', y: 33, rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_04', y: 40, rot: [0, Math.PI, 0], },
-];
-
-root.updateMatrixWorld();
-for (const car of loadedCars.children.slice()) {
-  const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-  const obj = new THREE.Object3D();
-  car.getWorldPosition(obj.position);
--  car.position.set(0, 0, 0);
-+  car.position.set(0, fix.y, 0);
-  car.rotation.set(...fix.rot);
-  obj.add(car);
-  scene.add(obj);
-  cars.push(obj);
-}
-
-

Et le résultat.

-

- -

-

Pas mal pour quelques minutes de travail.

-

La dernière chose que je voulais faire est d'activer les ombres.

-

Pour ce faire, j'ai pris tout le code GUI de l'exemple d'ombres DirectionalLight dans l'article sur les ombres et l'ai collé dans notre dernier code.

-

Ensuite, après le chargement, nous devons activer les ombres sur tous les objets.

-
{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
-+    root.traverse((obj) => {
-+      if (obj.castShadow !== undefined) {
-+        obj.castShadow = true;
-+        obj.receiveShadow = true;
-+      }
-+    });
-
-

J'ai ensuite passé près de 4 heures à essayer de comprendre pourquoi les helpers d'ombre ne fonctionnaient pas. C'était parce que j'avais oublié d'activer les ombres avec

-
renderer.shadowMap.enabled = true;
-
-

😭

-

J'ai ensuite ajusté les valeurs jusqu'à ce que la caméra d'ombre de notre DirectionLight ait un frustum qui couvrait toute la scène. Voici les paramètres avec lesquels j'ai fini.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-+  light.castShadow = true;
-*  light.position.set(-250, 800, -850);
-*  light.target.position.set(-550, 40, -450);
-
-+  light.shadow.bias = -0.004;
-+  light.shadow.mapSize.width = 2048;
-+  light.shadow.mapSize.height = 2048;
-
-  scene.add(light);
-  scene.add(light.target);
-+  const cam = light.shadow.camera;
-+  cam.near = 1;
-+  cam.far = 2000;
-+  cam.left = -1500;
-+  cam.right = 1500;
-+  cam.top = 1500;
-+  cam.bottom = -1500;
-...
-
-

et j'ai défini la couleur de fond en bleu clair.

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('black');
-+scene.background = new THREE.Color('#DEFEFF');
-
-

Et ... les ombres

-

- -

-

J'espère que parcourir ce projet a été utile et a montré de bons exemples de résolution de certains des problèmes liés au chargement d'un fichier avec un graphe de scène.

-

Une chose intéressante est qu'en comparant le fichier .blend au fichier .gltf, le fichier .blend a plusieurs lumières mais elles ne sont pas des lumières après avoir été chargées dans la scène. Un fichier .GLTF est juste un fichier JSON, vous pouvez donc facilement regarder à l'intérieur. Il se compose de plusieurs tableaux de choses et chaque élément dans un tableau est référencé par index ailleurs. Bien qu'il y ait des extensions en cours de développement, elles soulignent un problème commun à presque tous les formats 3D. Ils ne peuvent jamais couvrir tous les cas.

-

Il y a toujours un besoin de plus de données. Par exemple, nous avons exporté manuellement un chemin pour les voitures à suivre. Idéalement, cette information aurait pu être dans le fichier .GLTF, mais pour ce faire, nous aurions besoin d'écrire notre propre exportateur et de marquer d'une manière ou d'une autre les nœuds pour la façon dont nous voulons qu'ils soient exportés, ou utiliser un schéma de nommage ou quelque chose de similaire pour obtenir les données de l'outil que nous utilisons pour créer les données dans notre application.

-

Tout cela est laissé comme un exercice pour le lecteur.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/load-obj.html b/manual/fr/load-obj.html deleted file mode 100644 index f068e25dd2aaa7..00000000000000 --- a/manual/fr/load-obj.html +++ /dev/null @@ -1,620 +0,0 @@ - - - Charger un fichier .OBJ - - - - - - - - - - - - - -
-
-

Charger un fichier .OBJ

-
-
-
-

L'une des choses les plus courantes que les gens veulent faire avec three.js -est de charger et d'afficher des modèles 3D. Un format courant est le format 3D -.OBJ, alors essayons d'en charger un.

-

En cherchant sur internet, j'ai trouvé ce modèle 3D de moulin à vent sous licence CC-BY-NC 3.0 par ahedov.

-
- -

J'ai téléchargé le fichier .blend à partir de ce site, je l'ai chargé dans Blender -et l'ai exporté en tant que fichier .OBJ.

-
- -
-

Note : Si vous n'avez jamais utilisé Blender, vous pourriez être surpris -par le fait que Blender fait les choses différemment de presque tous les autres -programmes que vous avez utilisés. Sachez simplement que vous pourriez avoir besoin de -prendre le temps de lire quelques bases sur la navigation dans l'interface utilisateur de Blender.

-

Permettez-moi d'ajouter également que les programmes 3D en général sont d'énormes bêtes avec -des milliers de fonctionnalités. Ce sont parmi les logiciels les plus compliqués qui existent. -Lorsque j'ai appris 3D Studio Max en 1996, j'ai lu 70% du manuel -de 600 pages en y consacrant quelques heures par jour pendant environ 3 semaines. Cela a -porté ses fruits, car lorsque j'ai appris Maya quelques années plus tard, certaines des leçons -apprises auparavant étaient applicables à Maya. Alors, sachez simplement que si vous -voulez vraiment pouvoir utiliser un logiciel 3D pour créer des assets 3D -ou pour modifier des assets existants, inscrivez-le à votre emploi du temps et réservez -du temps pour vraiment suivre quelques leçons.

-
-

Dans tous les cas, j'ai utilisé ces options d'exportation

-
- -

Essayons de l'afficher !

-

Je suis parti de l'exemple d'éclairage directionnel de -l'article sur les lumières et je l'ai combiné avec -l'exemple d'éclairage hémisphérique, j'ai donc fini avec une -HemisphereLight et une DirectionalLight. J'ai également supprimé tout ce qui concerne l'interface utilisateur -pour régler les lumières. J'ai également supprimé le cube et la sphère -qui étaient ajoutés à la scène.

-

À partir de là, la première chose à faire est d'inclure le chargeur OBJLoader -dans notre script.

-
import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
-
-

Ensuite, pour charger le fichier .OBJ, nous créons une instance de OBJLoader, -lui passons l'URL de notre fichier .OBJ, et ajoutons un rappel qui -ajoute le modèle chargé à notre scène.

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-    scene.add(root);
-  });
-}
-
-

Si nous exécutons cela, que se passe-t-il ?

-

- -

-

Eh bien, c'est presque ça, mais nous obtenons des erreurs concernant les matériaux, -car nous n'avons pas donné de matériaux à la scène et les fichiers .OBJ n'ont pas de -paramètres de matériaux.

-

Le chargeur .OBJ peut recevoir un -objet de paires nom / matériau. Lorsqu'il charge le fichier .OBJ, -pour chaque nom de matériau qu'il trouve, il cherchera le matériau correspondant -dans la carte des matériaux définie sur le chargeur. S'il trouve un -matériau correspondant au nom, il utilisera ce matériau. Sinon, -il utilisera le matériau par défaut du chargeur.

-

Parfois, les fichiers .OBJ sont accompagnés d'un fichier .MTL qui définit -les matériaux. Dans notre cas, l'exportateur a également créé un fichier .MTL. -Le format .MTL est du texte brut (ASCII), il est donc facile à examiner. -En le regardant ici

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
-map_Bump windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
-map_Bump windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

Nous pouvons voir qu'il y a 2 matériaux référençant 5 textures jpg, -mais où sont les fichiers de texture ?

-
- -

Tout ce que nous avons obtenu était un fichier .OBJ et un fichier .MTL.

-

Au moins pour ce modèle, il s'avère que les textures sont intégrées -dans le fichier .blend que nous avons téléchargé. Nous pouvons demander à Blender -d'exporter ces fichiers en choisissant Fichier->Données externes->Désintégrer tout en fichiers (File->External Data->Unpack All Into Files)

-
- -

puis en choisissant Écrire les fichiers dans le répertoire actuel (Write Files to Current Directory)

-
- -

Cela finit par écrire les fichiers dans le même dossier que le fichier .blend, -dans un sous-dossier appelé textures.

-
- -

Maintenant que les textures sont disponibles, nous pouvons charger le fichier .MTL.

-

D'abord, nous devons inclure le MTLLoader ;

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
-+import {MTLLoader} from 'three/addons/loaders/MTLLoader.js';
-
-

Ensuite, nous chargeons d'abord le fichier .MTL. Une fois le chargement terminé, -nous ajoutons les matériaux tout juste chargés au OBJLoader lui-même via la méthode setMaterials, -puis nous chargeons le fichier .OBJ.

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
-+    mtl.preload();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      scene.add(root);
-    });
-+  });
-}
-
-

Et si nous essayons cela...

-

- -

-

Notez que si vous faites tourner le modèle, vous verrez le tissu du moulin disparaître

-
- -

Nous devons rendre le matériau des pales double face, -ce que nous avons vu dans l'article sur les matériaux. -Il n'y a pas de moyen facile de corriger cela dans le fichier .MTL. -Spontanément, je peux penser à 3 façons de corriger cela.

-
    -
  1. Parcourir tous les matériaux après les avoir chargés et les rendre tous double face.

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.preload();
    -   for (const material of Object.values(mtl.materials)) {
    -     material.side = THREE.DoubleSide;
    -   }
    -   ...
    -

    Cette solution fonctionne, mais idéalement, nous ne voulons que les matériaux qui ont besoin -d'être double face soient double face, car dessiner en double face -est plus lent qu'en simple face.

    -
  2. -
  3. Définir manuellement un matériau spécifique

    -

    En regardant dans le fichier .MTL, il y a 2 matériaux. L'un s'appelle "windmill" -et l'autre s'appelle "Material". Par essais et erreurs, j'ai découvert -que les pales utilisent le matériau appelé "Material", nous pourrions donc le définir -spécifiquement

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.preload();
    -   mtl.materials.Material.side = THREE.DoubleSide;
    -   ...
    -
  4. -
  5. Réalisant que le fichier .MTL est limité, nous pourrions simplement ne pas l'utiliser -et créer nous-mêmes les matériaux à la place.

    -

    Dans ce cas, nous devrions rechercher l'objet Mesh après -avoir chargé le fichier obj.

    -
     objLoader.load('resources/models/windmill/windmill.obj', (root) => {
    -   const materials = {
    -     Material: new THREE.MeshPhongMaterial({...}),
    -     windmill: new THREE.MeshPhongMaterial({...}),
    -   };
    -   root.traverse(node => {
    -     const material = materials[node.material?.name];
    -     if (material) {
    -       node.material = material;
    -     }
    -   })
    -   scene.add(root);
    - });
    -
  6. -
-

À vous de choisir laquelle vous préférez. 1 est la plus simple. 3 est la plus flexible. -2 est entre les deux. Pour l'instant, je vais choisir la 2.

-

Et avec cette modification, vous devriez toujours voir le tissu sur les pales -en regardant par derrière, mais il y a un autre problème. Si nous zoomons de près, -nous voyons que les choses deviennent pixellisées.

-
- -

Que se passe-t-il ?

-

En regardant les textures, il y a 2 textures étiquetées NOR pour carte NORmale. -Et en les regardant, elles ressemblent à des cartes normales. Les cartes normales sont généralement -violettes, tandis que les cartes de relief sont noires et blanches. Les cartes normales représentent -la direction de la surface, tandis que les cartes de relief représentent la hauteur de -la surface.

-
- -

En regardant le code source du MTLLoader, -il s'attend au mot-clé norm pour les cartes normales, alors éditons le fichier .MTL

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
--map_Bump windmill_001_lopatky_NOR.jpg
-+norm windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
--map_Bump windmill_001_base_NOR.jpg
-+norm windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

et maintenant, lorsque nous le chargerons, il utilisera les cartes normales comme cartes normales -et nous pourrons voir l'arrière des pales.

-

- -

-

Chargeons un fichier différent.

-

En cherchant sur internet, j'ai trouvé ce modèle 3D de moulin à vent sous licence CC-BY-NC réalisé par Roger Gerzner / GERIZ.3D Art.

-
- -

Il avait déjà une version .OBJ disponible. Chargeons-le (notez que j'ai retiré le chargeur .MTL pour l'instant)

-
-  objLoader.load('resources/models/windmill/windmill.obj', ...
-+  objLoader.load('resources/models/windmill-2/windmill.obj', ...
-
-

- -

-

Hmmm, rien n'apparaît. Quel est le problème ? Quelle taille a le modèle ? -Nous pouvons demander à THREE.js quelle taille a le modèle et essayer de régler notre -caméra automatiquement.

-

Tout d'abord, nous pouvons demander à THREE.js de calculer une boîte qui contient la scène -que nous venons de charger et de demander sa taille et son centre

-
objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-  scene.add(root);
-
-+  const box = new THREE.Box3().setFromObject(root);
-+  const boxSize = box.getSize(new THREE.Vector3()).length();
-+  const boxCenter = box.getCenter(new THREE.Vector3());
-+  console.log(boxSize);
-+  console.log(boxCenter);
-
-

En regardant dans la console JavaScript, je vois

-
size 2123.6499788469982
-center p {x: -0.00006103515625, y: 770.0909731090069, z: -3.313507080078125}
-
-

Notre caméra n'affiche actuellement qu'environ 100 unités, avec near à 0.1 et far à 100. -Notre plan de sol ne mesure que 40 unités de large, donc en gros, ce modèle de moulin à vent est si grand, 2000 unités, -qu'il entoure notre caméra et que toutes ses parties sont en dehors de notre frustum.

-
- -

Nous pourrions corriger cela manuellement, mais nous pourrions aussi faire en sorte que la caméra cadre automatiquement notre scène. -Essayons cela. Nous pouvons ensuite utiliser la boîte que nous venons de calculer pour ajuster les paramètres de la caméra afin de -visualiser toute la scène. Notez qu'il n'y a pas de bonne réponse -sur l'endroit où placer la caméra. Nous pourrions être face à la scène depuis n'importe quelle direction et à n'importe quelle -altitude, il faudra donc choisir quelque chose.

-

Comme nous l'avons vu dans l'article sur les caméras, la caméra définit un frustum. -Ce frustum est défini par le champ de vision (fov) et les paramètres near et far. Nous -voulons savoir, étant donné le champ de vision actuel de la caméra, à quelle distance la caméra -doit se trouver pour que la boîte contenant la scène s'inscrive dans le frustum, en supposant que le frustum -s'étende à l'infini. En d'autres termes, supposons que near est 0.00000001 et far est l'infini.

-

Puisque nous connaissons la taille de la boîte et que nous connaissons le champ de vision, nous avons ce triangle

-
- -

Vous pouvez voir à gauche la caméra et le frustum bleu qui se projette devant elle. -Nous venons de calculer la boîte qui contient le moulin à vent. Nous devons -calculer à quelle distance la caméra doit se trouver de la boîte pour que celle-ci -apparaisse à l'intérieur du frustum.

-

En utilisant la trigonométrie de base des triangles rectangles et SOHCAHTOA, -étant donné que nous connaissons le champ de vision pour le frustum et que nous connaissons la taille de la boîte, nous pouvons calculer la distance.

-
- -

Sur la base de ce diagramme, la formule pour calculer la distance est

-
distance = halfSizeToFitOnScreen / tangent(halfFovY)
-
-

Traduisons cela en code. D'abord, créons une fonction qui calculera distance, puis déplacera la -caméra de distance unités à partir du centre de la boîte. Nous dirigerons -ensuite la caméra vers le center de la boîte.

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  // calcule un vecteur unitaire qui pointe dans la direction où se trouve actuellement la caméra par rapport au centre de la boîte
-  const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-
-  // déplace la caméra vers une position située à distance unités du centre,
-  // dans la même direction où se trouvait déjà la caméra par rapport au centre
-  camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
-
-  // choisit des valeurs near et far pour le frustum qui
-  // contiendront la boîte.
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-
-  // oriente la caméra pour qu'elle regarde le centre de la boîte
-  camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
-}
-
-

Nous passons 2 tailles. Le boxSize et le sizeToFitOnScreen. Si nous passions simplement boxSize -et l'utilisions comme sizeToFitOnScreen, alors le calcul ferait en sorte que la boîte s'insère parfaitement dans -le frustum. Nous voulons un peu d'espace supplémentaire au-dessus et en dessous, nous passerons donc une taille -légèrement plus grande.

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-    scene.add(root);
-+    // calcule la boîte qui contient tout ce qui se trouve
-+    // à partir de la racine et en dessous
-+    const box = new THREE.Box3().setFromObject(root);
-+
-+    const boxSize = box.getSize(new THREE.Vector3()).length();
-+    const boxCenter = box.getCenter(new THREE.Vector3());
-+
-+    // positionne la caméra pour encadrer la boîte
-+    frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-+
-+    // met à jour les contrôles OrbitControls pour gérer la nouvelle taille
-+    controls.maxDistance = boxSize * 10;
-+    controls.target.copy(boxCenter);
-+    controls.update();
-  });
-}
-
-

Vous pouvez voir ci-dessus que nous passons boxSize * 1.2 pour nous donner 20% d'espace supplémentaire -au-dessus et en dessous de la boîte lorsque nous essayons de l'insérer dans le frustum. Nous avons également mis à jour les -OrbitControls afin que la caméra orbite autour du centre -de la scène.

-

Maintenant si nous essayons cela, nous obtenons...

-

- -

-

Cela fonctionne presque. Utilisez la souris pour faire pivoter la caméra et vous -devriez voir le moulin à vent. Le problème est que le moulin à vent est grand et que le centre de la boîte se trouve à environ (0, 770, 0). -Ainsi, lorsque nous déplaçons la caméra de sa position de départ (0, 10, 20) à distance unités du centre -dans la direction où se trouve la caméra par rapport au centre, cela déplace la caméra presque droit vers le bas, -sous le moulin à vent.

-
- -

Changeons cela pour nous déplacer latéralement à partir du centre de la boîte, dans la direction -où se trouve la caméra par rapport au centre. Tout ce que nous devons faire pour cela -est de mettre à zéro la composante y du vecteur allant de la boîte à la caméra. -Ensuite, lorsque nous normalisons ce vecteur, il deviendra un vecteur parallèle au plan XZ. -En d'autres termes, parallèle au sol.

-
-// calcule un vecteur unitaire qui pointe dans la direction où se trouve actuellement la caméra par rapport au centre de la boîte
--// from the center of the box
--const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-+// calcule un vecteur unitaire qui pointe dans la direction où se trouve actuellement la caméra
-+// dans le plan xz par rapport au centre de la boîte
-+const direction = (new THREE.Vector3())
-+    .subVectors(camera.position, boxCenter)
-+    .multiply(new THREE.Vector3(1, 0, 1))
-+    .normalize();
-
-

Si vous regardez le bas du moulin à vent, vous verrez un petit carré. -C'est notre plan de sol.

-
- -

Il ne mesure que 40x40 unités et est donc beaucoup trop petit par rapport au moulin à vent. -Étant donné que le moulin à vent mesure plus de 2000 unités, changeons la taille du plan de sol -pour quelque chose de plus approprié. Nous devons également ajuster la répétition, sinon notre damier -sera si fin que nous ne pourrons même pas le voir à moins de zoomer très très près.

-
-const planeSize = 40;
-+const planeSize = 4000;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
--const repeats = planeSize / 2;
-+const repeats = planeSize / 200;
-texture.repeat.set(repeats, repeats);
-
-

et maintenant nous pouvons voir ce moulin à vent

-

- -

-

Ajoutons à nouveau les matériaux. Comme précédemment, il y a un fichier .MTL qui référence -des textures, mais en regardant les fichiers, je constate rapidement un problème.

-
 $ ls -l windmill
- -rw-r--r--@ 1 gregg  staff       299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff    142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_diffuse.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 20  2009 windmill_normal.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_spec.tga
-
-

Il y a des fichiers TARGA (.tga) et ils sont gigantesques !

-

THREE.js a en fait un chargeur TGA, mais il est discutable de l'utiliser pour la plupart des cas d'utilisation. -Si vous créez une visionneuse où vous voulez permettre aux utilisateurs de voir des fichiers 3D aléatoires qu'ils -trouvent sur internet, alors peut-être, juste peut-être, que vous voudrez charger des fichiers TGA. (*)

-

Un problème avec les fichiers TGA est qu'ils ne peuvent pas être bien compressés du tout. -TGA ne prend en charge qu'une compression très simple, et en regardant ci-dessus, nous pouvons voir que les fichiers ne sont pas du tout -compressés, car les chances qu'ils aient tous exactement la même taille sont extrêmement faibles. -De plus, ils font 12 mégaoctets chacun !!!

-

Si nous utilisions ces fichiers, l'utilisateur devrait télécharger 36 Mo -pour voir le moulin à vent.

-

Un autre problème avec TGA est que le navigateur lui-même ne les prend pas en charge, donc le chargement -sera probablement plus lent que le chargement de formats pris en charge comme .JPG et .PNG

-

Je suis presque sûr que pour nos besoins, les convertir en .JPG sera la meilleure option. -En regardant à l'intérieur, je vois qu'ils ont 3 canaux chacun, RGB, il n'y a pas de canal alpha. JPG -ne prend en charge que 3 canaux, c'est donc une bonne correspondance. JPG prend également en charge la compression -avec perte, ce qui nous permet de rendre les fichiers beaucoup plus petits à télécharger

-

En chargeant les fichiers, ils étaient chacun de 2048x2048. Cela m'a semblé un gâchis, -mais bien sûr, cela dépend de votre cas d'utilisation. Je les ai mis chacun en 1024x1024 -et les ai enregistrés avec un réglage de qualité de 50% dans Photoshop. Obtenir une liste de fichiers

-
 $ ls -l ../threejs.org/manual/examples/resources/models/windmill
- -rw-r--r--@ 1 gregg  staff     299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff  142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  259927 Nov  7 18:37 windmill_diffuse.jpg
- -rw-r--r--@ 1 gregg  staff   98013 Nov  7 18:38 windmill_normal.jpg
- -rw-r--r--@ 1 gregg  staff  191864 Nov  7 18:39 windmill_spec.jpg
-
-

Nous sommes passés de 36 Mo à 0,55 Mo ! Bien sûr, l'artiste pourrait ne pas être satisfait -de cette compression, alors assurez-vous de le consulter pour discuter des compromis.

-

Maintenant, pour utiliser le fichier .MTL, nous devons l'éditer pour qu'il référence les fichiers .JPG -au lieu des fichiers .TGA. Heureusement, c'est un simple fichier texte, il est donc facile à éditer

-
newmtl blinn1SG
-Ka 0.10 0.10 0.10
-
-Kd 0.00 0.00 0.00
-Ks 0.00 0.00 0.00
-Ke 0.00 0.00 0.00
-Ns 0.060000
-Ni 1.500000
-d 1.000000
-Tr 0.000000
-Tf 1.000000 1.000000 1.000000
-illum 2
--map_Kd windmill_diffuse.tga
-+map_Kd windmill_diffuse.jpg
-
--map_Ks windmill_spec.tga
-+map_Ks windmill_spec.jpg
-
--map_bump windmill_normal.tga
--bump windmill_normal.tga
-+map_bump windmill_normal.jpg
-+bump windmill_normal.jpg
-
-

Maintenant que le fichier .MTL pointe vers des textures de taille raisonnable, nous devons le charger. -Nous allons donc faire comme nous l'avons fait ci-dessus : charger d'abord les matériaux, -puis les définir sur l'OBJLoader

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill_2/windmill-fixed.mtl', (mtl) => {
-+    mtl.preload();
-+    const objLoader = new OBJLoader();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      root.updateMatrixWorld();
-      scene.add(root);
-      // calcule la boîte qui contient tout ce qui se trouve
-      // à partir de la racine et en dessous
-      const box = new THREE.Box3().setFromObject(root);
-
-      const boxSize = box.getSize(new THREE.Vector3()).length();
-      const boxCenter = box.getCenter(new THREE.Vector3());
-
-      // positionne la caméra pour encadrer la boîte
-      frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-
-      // met à jour les contrôles Trackball pour gérer la nouvelle taille
-      controls.maxDistance = boxSize * 10;
-      controls.target.copy(boxCenter);
-      controls.update();
-    });
-+  });
-}
-
-

Avant d'essayer, j'ai rencontré quelques problèmes que, plutôt que de montrer un échec, -je vais simplement passer en revue.

-

Problème n°1 : Le MTLLoader de three crée des matériaux qui multiplient la couleur diffuse du matériau par la carte de texture diffuse.

-

C'est une fonctionnalité utile, mais en regardant le fichier .MTL ci-dessus, la ligne

-
Kd 0.00 0.00 0.00
-
-

définit la couleur diffuse à 0. Carte de texture * 0 = noir ! Il est possible que l'outil de modélisation -utilisé pour créer le moulin à vent n'ait pas multiplié la carte de texture diffuse par la couleur diffuse. -C'est pourquoi cela a fonctionné pour les artistes qui ont créé ce moulin à vent.

-

Pour corriger cela, nous pouvons changer la ligne en

-
Kd 1.00 1.00 1.00
-
-

car Carte de Texture * 1 = Carte de Texture.

-

Problème n°2 : La couleur spéculaire est également noire

-

La ligne qui commence par Ks spécifie la couleur spéculaire. Il est probable que le logiciel de modélisation -utilisé pour créer le moulin à vent ait fait quelque chose de similaire à ce qu'il a fait avec les cartes diffuses, -c'est-à-dire qu'il a utilisé la couleur de la carte spéculaire pour les reflets spéculaires. -Three.js utilise uniquement le canal rouge d'une carte spéculaire comme entrée pour déterminer la quantité -de couleur spéculaire à refléter, mais three a toujours besoin d'une couleur spéculaire définie.

-

Comme ci-dessus, nous pouvons corriger cela en éditant le fichier .MTL comme ceci.

-
-Ks 0.00 0.00 0.00
-+Ks 1.00 1.00 1.00
-
-

Problème n°3 : Le fichier windmill_normal.jpg est une carte normale et non une carte de relief.

-

Tout comme ci-dessus, il suffit d'éditer le fichier .MTL

-
-map_bump windmill_normal.jpg
--bump windmill_normal.jpg
-+norm windmill_normal.jpg
-
-

Compte tenu de tout cela, si nous l'essayons maintenant, il devrait se charger avec les matériaux.

-

- -

-

Le chargement de modèles rencontre souvent ce genre de problèmes. Les problèmes courants incluent :

-
    -
  • Nécessité de connaître la taille

    -

    Ci-dessus, nous avons fait en sorte que la caméra essaie de cadrer la scène, mais ce n'est pas toujours la chose appropriée à faire. Généralement, la chose la plus appropriée à faire est de créer vos propres modèles ou de télécharger les modèles, de les charger dans un logiciel 3D et d'examiner leur échelle et de l'ajuster si nécessaire.

    -
  • -
  • Orientation incorrecte

    -

    THREE.js utilise généralement Y vers le haut. Certains logiciels de modélisation utilisent par défaut Z vers le haut, d'autres Y vers le haut. Certains sont configurables. -Si vous rencontrez ce cas où vous chargez un modèle et qu'il est sur le côté. Vous pouvez soit modifier votre code pour faire pivoter le modèle après le chargement (non recommandé), soit charger le modèle dans votre logiciel de modélisation préféré ou utiliser des outils en ligne de commande pour faire pivoter l'objet dans l'orientation dont vous avez besoin, tout comme vous éditeriez une image pour votre site web plutôt que de la télécharger et d'appliquer du code pour l'ajuster. Blender a même des options lors de l'exportation pour changer l'orientation.

    -
  • -
  • Pas de fichier .MTL ou matériaux incorrects ou paramètres incompatibles

    -

    Ci-dessus, nous avons utilisé un fichier .MTL qui nous a aidés à charger des matériaux, mais il y a eu des problèmes. Nous avons édité manuellement le fichier .MTL pour les corriger. -Il est également courant de regarder à l'intérieur du fichier .OBJ pour voir quels matériaux il contient, ou de charger le fichier .OBJ dans THREE.js et de parcourir la scène pour afficher tous les matériaux. Ensuite, modifiez le code pour créer des matériaux personnalisés et les attribuer là où cela est approprié, soit en créant un objet paire nom/matériau à passer au chargeur au lieu de charger le fichier .MTL, SOIT, après le chargement de la scène, en parcourant la scène et en corrigeant les choses.

    -
  • -
  • Textures trop grandes

    -

    La plupart des modèles 3D sont créés pour l'architecture, les films et publicités, ou les jeux. Pour l'architecture et les films, personne ne se soucie vraiment de la taille des textures puisque. Pour les jeux, les gens s'en soucient car les jeux ont une mémoire limitée, mais la plupart des jeux s'exécutent localement. Cependant, sur les pages web, vous voulez charger le plus rapidement possible, et vous devez donc regarder les textures et essayer de les rendre aussi petites que possible tout en conservant un bon rendu. En fait, pour le premier moulin à vent, nous aurions probablement dû faire quelque chose concernant les textures. Elles totalisent actuellement 10 Mo !!!

    -

    Rappelez-vous également, -comme nous l'avons mentionné dans l'article sur les textures, que -les textures prennent de la mémoire. Ainsi, un JPG de 50 Ko qui s'étend à 4096x4096 se téléchargera -rapidement mais prendra toujours une énorme quantité de mémoire.

    -
  • -
-

La dernière chose que je voulais montrer est de faire tourner les moulins à vent. Malheureusement, -les fichiers .OBJ n'ont pas de hiérarchie. Cela signifie que toutes les parties de chaque -moulin à vent sont fondamentalement considérées comme un seul maillage. Vous ne pouvez pas faire tourner les -pales du moulin car elles ne sont pas séparées du reste du bâtiment.

-

C'est l'une des principales raisons pour lesquelles le .OBJ n'est pas vraiment un bon format. -Si je devais deviner, la raison pour laquelle il est plus courant que d'autres formats -est qu'il est simple et, comme il ne prend pas en charge de nombreuses fonctionnalités, il fonctionne le plus souvent. -Surtout si vous créez quelque chose de statique comme une image architecturale -et qu'il n'y a pas besoin d'animer quoi que ce soit, ce n'est pas une mauvaise façon d'intégrer des -éléments statiques dans une scène.

-

Ensuite, nous allons essayer le chargement d'une scène gLTF. -Le format gLTF prend en charge beaucoup plus de fonctionnalités.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/loading-3d-models.html b/manual/fr/loading-3d-models.html deleted file mode 100644 index a62e64f272ac94..00000000000000 --- a/manual/fr/loading-3d-models.html +++ /dev/null @@ -1,160 +0,0 @@ - - - Chargement de modèles 3D - - - - - - - - - - - - - -
-
-

Chargement de modèles 3D

-
-
-
- -

- Les modèles 3D sont disponibles dans des centaines de formats de fichiers, chacun ayant des objectifs différents, des fonctionnalités variées et une complexité variable. Bien que - - three.js propose de nombreux chargeurs, choisir le bon format et le bon flux de travail vous fera gagner du temps et vous évitera des frustrations plus tard. Certains formats sont difficiles à manipuler, inefficaces pour les expériences en temps réel, ou simplement pas entièrement pris en charge à l'heure actuelle. -

- -

- Ce guide propose un flux de travail recommandé pour la plupart des utilisateurs, ainsi que des suggestions sur ce qu'il faut essayer si les choses ne se passent pas comme prévu. -

- -

Avant de commencer

- -

- Si vous débutez avec l'exécution d'un serveur local, commencez par - Installation - d'abord. De nombreuses erreurs courantes lors de la visualisation de modèles 3D peuvent être évitées en hébergeant correctement les fichiers. -

- -

Flux de travail recommandé

- -

- Dans la mesure du possible, nous recommandons l'utilisation de glTF (GL Transmission Format). Les versions - .GLB et .GLTF du format sont bien prises en charge. Étant donné que glTF est axé sur la diffusion d'assets en temps réel, il est compact à transmettre et rapide à charger. Les fonctionnalités incluent les maillages, les matériaux, les textures, les peaux, les squelettes, les cibles de déformation (morph targets), les animations, les lumières et les caméras. -

- -

- Des fichiers glTF du domaine public sont disponibles sur des sites comme - - Sketchfab, ou divers outils incluent l'exportation glTF : -

- - - -

- Si vos outils préférés ne prennent pas en charge glTF, envisagez de demander l'exportation glTF aux auteurs, ou de poster sur - le fil de discussion de la feuille de route glTF. -

- -

- Lorsque glTF n'est pas une option, des formats populaires tels que FBX, OBJ ou COLLADA sont également disponibles et régulièrement mis à jour. -

- -

Chargement

- -

- Seuls quelques chargeurs (par exemple `ObjectLoader`) sont inclus par défaut avec three.js — les autres doivent être ajoutés individuellement à votre application. -

- -
-import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
-
- -

- Une fois qu'un chargeur a été importé, vous êtes prêt à ajouter un modèle à votre scène. La syntaxe varie selon les différents chargeurs — lorsque vous utilisez un autre format, consultez les exemples et la documentation de ce chargeur. Pour glTF, l'utilisation avec des scripts globaux serait : -

- -
-const loader = new GLTFLoader();
-
-loader.load( 'path/to/model.glb', function ( gltf ) {
-
-  scene.add( gltf.scene );
-
-}, undefined, function ( error ) {
-
-  console.error( error );
-
-} );
-
- -

Dépannage

- -

- Vous avez passé des heures à modéliser un chef-d'œuvre artisanal, vous le chargez dans la page web, et — oh non ! 😭 Il est déformé, mal coloré, ou manque entièrement. Commencez par ces étapes de dépannage : -

- -
    -
  1. - Vérifiez la console JavaScript pour les erreurs, et assurez-vous d'avoir utilisé une fonction de rappel `onError` lors de l'appel à `.load()` pour journaliser le résultat. -
  2. -
  3. - Visualisez le modèle dans une autre application. Pour glTF, des visionneuses par glisser-déposer sont disponibles pour - three.js et - babylon.js. Si le modèle - apparaît correctement dans une ou plusieurs applications, - signalez un bug à three.js. - Si le modèle ne peut être affiché dans aucune application, nous vous encourageons fortement à signaler un bug à l'application utilisée pour créer le modèle. -
  4. -
  5. - Essayez de mettre à l'échelle le modèle vers le haut ou vers le bas par un facteur de 1000. De nombreux modèles sont mis à l'échelle différemment, et les grands modèles peuvent ne pas apparaître si la caméra est à l'intérieur du modèle. -
  6. -
  7. - Essayez d'ajouter et de positionner une source de lumière. Le modèle peut être caché dans l'obscurité. -
  8. -
  9. - Recherchez les demandes de texture échouées dans l'onglet réseau, comme - `"C:\\Path\To\Model\texture.jpg"`. Utilisez plutôt des chemins relatifs à votre - modèle, tels que `images/texture.jpg` — cela peut nécessiter d'éditer le fichier modèle dans un éditeur de texte. -
  10. -
- -

Demander de l'aide

- -

- Si vous avez suivi le processus de dépannage ci-dessus et que votre modèle ne fonctionne toujours pas, la bonne approche pour demander de l'aide vous permettra d'obtenir une solution plus rapidement. Posez une question sur le - forum three.js et, dans la mesure du possible, - incluez votre modèle (ou un modèle plus simple présentant le même problème) dans tous les formats dont vous disposez. Incluez suffisamment d'informations pour que quelqu'un d'autre puisse reproduire le problème rapidement — idéalement, une démo en direct. -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/material-table.html b/manual/fr/material-table.html deleted file mode 100644 index 9287f8ca14a743..00000000000000 --- a/manual/fr/material-table.html +++ /dev/null @@ -1,47 +0,0 @@ - - - Tableau des fonctionnalités des matériaux - - - - - - - - - - - - - -
-
-

Tableau des fonctionnalités des matériaux

-
-
-
-

Les matériaux les plus courants dans three.js sont les matériaux Mesh. Voici un tableau montrant quels matériaux prennent en charge quelles fonctionnalités.

-
-
- - -
- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/materials.html b/manual/fr/materials.html deleted file mode 100644 index 770216a9b6258a..00000000000000 --- a/manual/fr/materials.html +++ /dev/null @@ -1,314 +0,0 @@ - - - Matériaux - - - - - - - - - - - - - -
-
-

Matériaux

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le -premier article est les bases de three.js. Si -vous ne l'avez pas encore lu et que vous débutez avec three.js, vous pourriez -vouloir commencer par là.

-

Three.js propose plusieurs types de matériaux. -Ils définissent comment les objets apparaîtront dans la scène. -Les matériaux que vous utilisez dépendent vraiment de ce que vous essayez -d'accomplir.

-

Il existe 2 manières de définir la plupart des propriétés des matériaux. L'une -au moment de la création, ce que nous avons déjà vu.

-
const material = new THREE.MeshPhongMaterial({
-  color: 0xFF0000,    // rouge (peut aussi utiliser une chaîne de couleur CSS ici)
-  flatShading: true,
-});
-
-

L'autre est après la création

-
const material = new THREE.MeshPhongMaterial();
-material.color.setHSL(0, 1, .5);  // rouge
-material.flatShading = true;
-
-

notez que les propriétés de type THREE.Color peuvent être définies de plusieurs manières.

-
material.color.set(0x00FFFF);    // comme le style #RRGGBB de CSS
-material.color.set(cssString);   // n'importe quelle couleur CSS, par exemple 'purple', '#F32',
-                                 // 'rgb(255, 127, 64)',
-                                 // 'hsl(180, 50%, 25%)'
-material.color.set(someColor)    // une autre THREE.Color
-material.color.setHSL(h, s, l)   // où h, s et l sont de 0 à 1
-material.color.setRGB(r, g, b)   // où r, g et b sont de 0 à 1
-
-

Et au moment de la création, vous pouvez passer soit un nombre hexadécimal, soit une chaîne CSS

-
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000});         // rouge
-const m2 = new THREE.MeshBasicMaterial({color: 'red'});            // rouge
-const m3 = new THREE.MeshBasicMaterial({color: '#F00'});           // rouge
-const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'});   // rouge
-const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'}); // rouge
-
-

Passons donc en revue l'ensemble des matériaux de three.js.

-

Le MeshBasicMaterial n'est pas affecté par les lumières.

-

Le MeshLambertMaterial calcule l'éclairage uniquement aux sommets, contrairement au MeshPhongMaterial qui calcule l'éclairage à chaque pixel. Le MeshPhongMaterial -prend également en charge les reflets spéculaires.

-
-
-
-
Basique
-
-
-
-
Lambert
-
-
-
-
Phong
-
-
-
-
-
-
-
-
-
-
-
-
-
-
modèles low-poly avec les mêmes matériaux
- -

Le paramètre shininess du MeshPhongMaterial détermine la brillance du reflet spéculaire. Par défaut, il est de 30.

-
-
-
-
shininess: 0
-
-
-
-
shininess: 30
-
-
-
-
shininess: 150
-
-
- -

Notez que définir la propriété emissive sur une couleur pour un -MeshLambertMaterial ou un MeshPhongMaterial et définir la color en noir -(et shininess à 0 pour phong) finit par ressembler exactement au MeshBasicMaterial.

-
-
-
-
-
Basique
-
color: 'purple'
-
-
-
-
-
-
Lambert
-
color: 'black'
-
emissive: 'purple'
-
-
-
-
-
-
Phong
-
color: 'black'
-
emissive: 'purple'
-
shininess: 0
-
-
-
- -

Pourquoi avoir les 3 alors que MeshPhongMaterial peut faire les mêmes choses que MeshBasicMaterial -et MeshLambertMaterial ? La raison est que le matériau le plus sophistiqué -nécessite plus de puissance GPU pour être dessiné. Sur un GPU plus lent, -comme celui d'un téléphone portable, vous pourriez vouloir réduire la -puissance GPU nécessaire pour dessiner votre scène en utilisant l'un des -matériaux moins complexes. Il s'ensuit également que si vous n'avez pas -besoin des fonctionnalités supplémentaires, utilisez le matériau le plus simple. -Si vous n'avez pas besoin de l'éclairage et des reflets spéculaires, -utilisez le MeshBasicMaterial.

-

Le MeshToonMaterial est similaire au MeshPhongMaterial -avec une grande différence. Au lieu d'ombrer en douceur, il utilise une -carte de dégradé (une texture de taille X sur 1) pour décider comment ombrer. -Par défaut, il utilise une carte de dégradé dont la luminosité est de 70% -pour les premiers 70% et de 100% ensuite, mais vous pouvez fournir votre -propre carte de dégradé. Cela donne finalement un aspect bicolore qui -ressemble à un dessin animé.

-
-
-
- -

Ensuite, il y a 2 matériaux basés sur le rendu physique. Le Rendu Basé sur -le Physique est souvent abrégé PBR.

-

Les matériaux ci-dessus utilisent des calculs simples pour créer des matériaux -qui semblent en 3D, mais ils ne correspondent pas à ce qui se passe réellement -dans le monde réel. Les 2 matériaux PBR utilisent des calculs beaucoup plus -complexes pour se rapprocher de ce qui se passe réellement dans le monde réel.

-

Le premier est MeshStandardMaterial. La plus grande différence entre -MeshPhongMaterial et MeshStandardMaterial est qu'il utilise différents paramètres. -MeshPhongMaterial avait un paramètre shininess. MeshStandardMaterial a 2 -paramètres : roughness et metalness.

-

À un niveau basique, roughness est l'opposé -de shininess. Quelque chose qui a une rugosité élevée, comme une balle de baseball, n'a pas -de reflets durs, tandis que quelque chose qui n'est pas rugueux, comme une boule de billard, -est très brillant. La rugosité va de 0 à 1.

-

L'autre paramètre, metalness, indique -à quel point le matériau est métallique. Les métaux se comportent différemment des non-métaux. 0 -pour non-métal et 1 pour métal.

-

Voici un échantillon rapide de MeshStandardMaterial avec une roughness de 0 à 1 -horizontalement et une metalness de 0 à 1 verticalement.

-
- -

Le MeshPhysicalMaterial est le même que le MeshStandardMaterial mais il -ajoute un paramètre clearcoat qui va de 0 à 1 pour déterminer la -quantité de couche de vernis brillant à appliquer, et un paramètre -clearCoatRoughness qui spécifie la rugosité de la couche brillante.

-

Voici la même grille de roughness par metalness que ci-dessus, mais avec -les paramètres clearcoat et clearCoatRoughness.

-
- -

Les différents matériaux standard progressent du plus rapide au plus lent : -MeshBasicMaterialMeshLambertMaterialMeshPhongMaterial ➡ -MeshStandardMaterialMeshPhysicalMaterial. Les matériaux plus lents -peuvent créer des scènes plus réalistes, mais vous pourriez avoir besoin de -concevoir votre code pour utiliser les matériaux plus rapides sur les machines -à faible puissance ou les appareils mobiles.

-

Il existe 3 matériaux qui ont des utilisations spéciales. ShadowMaterial -est utilisé pour obtenir les données créées par les ombres. Nous n'avons pas -encore abordé les ombres. Lorsque ce sera le cas, nous utiliserons ce matériau -pour jeter un coup d'œil à ce qui se passe en coulisse.

-

Le MeshDepthMaterial affiche la profondeur de chaque pixel où -les pixels au near négatif de la caméra sont 0 et au far négatif sont 1. -Certains effets spéciaux peuvent utiliser ces données, que nous aborderons -ultérieurement.

-
-
-
-
-
- -

Le MeshNormalMaterial vous montrera les normales de la géométrie. -Les normales sont la direction vers laquelle pointe un triangle ou un pixel particulier. -MeshNormalMaterial dessine les normales de l'espace de vue (les normales relatives à la caméra). -x est rouge, -y est vert, et -z est bleu donc les choses orientées -vers la droite seront roses, -vers la gauche seront aqua, -vers le haut seront vert clair, -vers le bas seront violettes, -et vers l'écran seront lavande.

-
-
-
-
-
- -

ShaderMaterial sert à créer des matériaux personnalisés à l'aide du système de shaders de three.js. -RawShaderMaterial sert à créer des shaders entièrement personnalisés sans aide de three.js. -Ces deux sujets sont vastes et seront abordés plus tard.

-

La plupart des matériaux partagent un ensemble de paramètres tous définis par Material. -Consultez la documentation -pour les voir tous, mais passons en revue deux des propriétés les plus couramment utilisées.

-

flatShading : -si l'objet semble facetté ou lisse. défaut = false.

-
-
-
-
flatShading: false
-
-
-
-
flatShading: true
-
-
- -

side : quels côtés des triangles afficher. La valeur par défaut est THREE.FrontSide. -Les autres options sont THREE.BackSide et THREE.DoubleSide (les deux côtés). -La plupart des objets 3D dessinés dans three.js sont probablement des solides opaques, donc les faces arrière -(les faces tournées vers l'intérieur du solide) n'ont pas besoin d'être dessinées. La raison la plus courante -de définir side est pour les plans ou d'autres objets non solides où il est -courant de voir les faces arrière des triangles.

-

Voici 6 plans dessinés avec THREE.FrontSide et THREE.DoubleSide.

-
-
-
-
side: THREE.FrontSide
-
-
-
-
side: THREE.DoubleSide
-
-
- -

Il y a vraiment beaucoup de choses à considérer avec les matériaux et nous en avons encore beaucoup -à voir. En particulier, nous avons largement ignoré les textures qui ouvrent tout un éventail -d'options. Cependant, avant d'aborder les textures, nous devons faire une pause et -configurer votre environnement de développement.

-
-

material.needsUpdate

-

-Ce sujet affecte rarement la plupart des applications three.js, mais juste pour information... -Three.js applique les paramètres des matériaux lorsqu'un matériau est utilisé, où "utilisé" -signifie "quelque chose qui est rendu utilise le matériau". Certains paramètres de matériau ne sont -appliqués qu'une seule fois, car leur modification nécessite beaucoup de travail de la part de three.js. -Dans ces cas, vous devez définir material.needsUpdate = true pour indiquer à -three.js d'appliquer vos modifications de matériau. Les paramètres les plus courants -qui nécessitent de définir needsUpdate si vous modifiez les paramètres après avoir -utilisé le matériau sont : -

-
    -
  • flatShading
  • -
  • ajout ou suppression d'une texture -

    - Changer une texture est acceptable, mais si vous souhaitez passer de l'absence de texture - à l'utilisation d'une texture, ou de l'utilisation d'une texture à l'absence de texture, - alors vous devez définir needsUpdate = true. -

    -

    Dans le cas où l'on passe d'une texture à l'absence de texture, il est souvent - simplement préférable d'utiliser une texture blanche de 1x1 pixel.

    -
  • -
-

Comme mentionné ci-dessus, la plupart des applications ne rencontrent jamais ces problèmes. La plupart des applications -ne basculent pas entre un ombrage plat et non plat. La plupart des applications -utilisent également des textures ou une couleur unie pour un matériau donné ; elles basculent rarement -de l'utilisation de l'un à l'utilisation de l'autre. -

-
- -

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/matrix-transformations.html b/manual/fr/matrix-transformations.html deleted file mode 100644 index dd964fc69a000f..00000000000000 --- a/manual/fr/matrix-transformations.html +++ /dev/null @@ -1,96 +0,0 @@ - - - Transformations matricielles - - - - - - - - - - - - - -
-
-

Transformations matricielles

-
-
-
- -

- Three.js utilise des `matrices` pour encoder les transformations 3D : translations (position), rotations et mises à l'échelle. Chaque instance d'`Object3D` possède une `matrix` qui stocke la position, la rotation et l'échelle de cet objet. Cette page décrit comment mettre à jour la transformation d'un objet. -

- -

Propriétés de commodité et `matrixAutoUpdate`

- -

- Il existe deux manières de mettre à jour la transformation d'un objet : -

-
    -
  1. - Modifiez les propriétés `position`, `quaternion` et `scale` de l'objet, et laissez three.js recalculer la matrice de l'objet à partir de ces propriétés : -
    -object.position.copy( start_position );
    -object.quaternion.copy( quaternion );
    -
    - Par défaut, la propriété `matrixAutoUpdate` est définie sur true, et la matrice sera automatiquement recalculée. - Si l'objet est statique, ou si vous souhaitez contrôler manuellement le moment où le recalcul se produit, de meilleures performances peuvent être obtenues en définissant la propriété sur false : -
    -object.matrixAutoUpdate = false;
    -
    - Et après avoir modifié une propriété, mettez à jour la matrice manuellement : -
    -object.updateMatrix();
    -
    -
  2. -
  3. - Modifiez la matrice de l'objet directement. La classe `Matrix4` dispose de différentes méthodes pour modifier la matrice : -
    -object.matrix.makeRotationFromQuaternion( quaternion );
    -object.matrix.setPosition( start_position );
    -object.matrixAutoUpdate = false;
    -
    - Notez que `matrixAutoUpdate` doit être défini sur `false` dans ce cas, et vous devez vous assurer de ne pas appeler `updateMatrix`. Appeler `updateMatrix` écrasera les modifications manuelles apportées à la matrice, en recalculant la matrice à partir de `position`, `scale`, etc. -
  4. -
- -

Matrices de l'objet et du monde

-

- La matrice d'un objet stocke la transformation de l'objet par rapport à son parent ; pour obtenir la transformation de l'objet en coordonnées du monde, vous devez accéder à la matrice du monde de l'objet. -

-

- Lorsque la transformation du parent ou de l'enfant change, vous pouvez demander la mise à jour de la matrice du monde de l'objet enfant en appelant `object.updateMatrixWorld()`. -

-

- Un objet peut être transformé via `applyMatrix4()`. Note : En coulisses, cette méthode repose sur `Matrix4.decompose()`, et toutes les matrices ne sont pas décomposables de cette manière. Par exemple, si un objet a un parent avec une mise à l'échelle non uniforme, la matrice du monde de l'objet peut ne pas être décomposable, et cette méthode pourrait ne pas être appropriée. -

- -

Rotation et Quaternion

-

- Three.js propose deux manières de représenter les rotations 3D : les angles d'Euler et les Quaternions, ainsi que des méthodes pour convertir entre les deux. Les angles d'Euler sont sujets à un problème appelé « verrouillage de cardan » (gimbal lock), où certaines configurations peuvent perdre un degré de liberté (empêchant l'objet de tourner autour d'un axe). Pour cette raison, les rotations d'objets sont toujours stockées dans le quaternion de l'objet. -

-

- Les versions précédentes de la librairie incluaient une propriété `useQuaternion` qui, lorsqu'elle était définie sur false, entraînait le calcul de la matrice de l'objet à partir d'un angle d'Euler. Cette pratique est obsolète --- à la place, vous devriez utiliser la méthode `object.setRotationFromEuler()`, qui mettra à jour le quaternion. -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/multiple-scenes.html b/manual/fr/multiple-scenes.html deleted file mode 100644 index 52f0284fde5a46..00000000000000 --- a/manual/fr/multiple-scenes.html +++ /dev/null @@ -1,652 +0,0 @@ - - - Plusieurs Canvases, Plusieurs Scènes - - - - - - - - - - - - - -
-
-

Plusieurs Canvases, Plusieurs Scènes

-
-
-
-

Une question courante est de savoir comment utiliser THREE.js avec plusieurs canvases. -Disons que vous voulez faire un site de commerce électronique ou que vous voulez créer -une page avec beaucoup de diagrammes 3D. À première vue, cela semble facile. -Faites simplement un canvas partout où vous voulez un diagramme. Pour chaque canvas, -créez un Renderer.

-

Vous découvrirez rapidement, cependant, que vous rencontrez des problèmes.

-
    -
  1. Le navigateur limite le nombre de contextes WebGL que vous pouvez avoir.

    -

    Typiquement, cette limite est d'environ 8. Dès que vous créez -le 9ème contexte, le plus ancien sera perdu.

    -
  2. -
  3. Les ressources WebGL ne peuvent pas être partagées entre les contextes

    -

    Cela signifie que si vous voulez charger un modèle de 10 Mo dans 2 canvases -et que ce modèle utilise 20 Mo de textures, votre modèle de 10 Mo devra -être chargé deux fois et vos textures seront également chargées -deux fois. Rien ne peut être partagé entre les contextes. Cela -signifie également que les choses doivent être initialisées deux fois, les shaders compilés deux fois, -etc. Cela empire à mesure qu'il y a plus de canvases.

    -
  4. -
-

Alors, quelle est la solution ?

-

La solution est un canvas qui remplit la zone d'affichage en arrière-plan et un autre élément pour représenter chaque canvas "virtuel". Nous créons un seul Renderer, puis une Scene pour chaque canvas virtuel. Nous vérifierons ensuite les positions des éléments de canvas virtuels et s'ils sont à l'écran, nous demanderons à THREE.js de dessiner leur scène à l'endroit correct.

-

Avec cette solution, il n'y a qu'un seul canvas, nous résolvons donc les problèmes 1 -et 2 ci-dessus. Nous ne rencontrerons pas la limite de contextes WebGL car nous -n'utiliserons qu'un seul contexte. Nous ne rencontrerons pas non plus les problèmes -de partage pour les mêmes raisons.

-

Commençons par un exemple simple avec seulement 2 scènes. D'abord, nous allons -créer le HTML

-
<canvas id="c"></canvas>
-<p>
-  <span id="box" class="diagram left"></span>
-  J'aime les boîtes. Les cadeaux viennent dans des boîtes.
-  Quand je trouve une nouvelle boîte, je suis toujours impatient de découvrir ce qu'il y a dedans.
-</p>
-<p>
-  <span id="pyramid" class="diagram right"></span>
-  Quand j'étais enfant, je rêvais de partir en expédition à l'intérieur d'une pyramide
-  et de trouver un tombeau inconnu rempli de momies et de trésors.
-</p>
-
-

Ensuite, nous pouvons configurer le CSS peut-être comme ceci

-
#c {
-  position: fixed;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: block;
-  z-index: -1;
-}
-.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-  border: 1px solid black;
-}
-.left {
-  float: left;
-  margin-right: .25em;
-}
-.right {
-  float: right;
-  margin-left: .25em;
-}
-
-

Nous configurons le canvas pour qu'il remplisse l'écran et nous définissons son z-index à --1 pour qu'il apparaisse derrière les autres éléments. Nous devons également spécifier une sorte de largeur et de hauteur -pour nos éléments de canvas virtuels puisqu'il n'y a rien à l'intérieur -pour leur donner une taille.

-

Maintenant, nous allons créer 2 scènes, chacune avec une lumière et une caméra. -À une scène, nous ajouterons un cube et à l'autre une sphère.

-
function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  return {scene, camera, elem};
-}
-
-function setupScene1() {
-  const sceneInfo = makeScene(document.querySelector('#box'));
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({color: 'red'});
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-function setupScene2() {
-  const sceneInfo = makeScene(document.querySelector('#pyramid'));
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-const sceneInfo1 = setupScene1();
-const sceneInfo2 = setupScene2();
-
-

Et ensuite, nous allons créer une fonction pour rendre chaque scène -uniquement si l'élément est à l'écran. Nous pouvons indiquer à THREE.js -de ne rendre qu'une partie du canvas en activant le test scissor -avec Renderer.setScissorTest, puis en définissant à la fois le scissor et le viewport avec Renderer.setViewport et Renderer.setScissor.

-
function renderSceneInfo(sceneInfo) {
-  const {scene, camera, elem} = sceneInfo;
-
-  // obtenir la position relative à la zone d'affichage de cet élément
-  const {left, right, top, bottom, width, height} =
-      elem.getBoundingClientRect();
-
-  const isOffscreen =
-      bottom < 0 ||
-      top > renderer.domElement.clientHeight ||
-      right < 0 ||
-      left > renderer.domElement.clientWidth;
-
-  if (isOffscreen) {
-    return;
-  }
-
-  camera.aspect = width / height;
-  camera.updateProjectionMatrix();
-
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  renderer.render(scene, camera);
-}
-
-

Et ensuite, notre fonction de rendu commencera par effacer l'écran, -puis rendra chaque scène.

-
function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  sceneInfo1.mesh.rotation.y = time * .1;
-  sceneInfo2.mesh.rotation.y = time * .1;
-
-  renderSceneInfo(sceneInfo1);
-  renderSceneInfo(sceneInfo2);
-
-  requestAnimationFrame(render);
-}
-
-

Et voici le résultat

-

- -

-

Vous pouvez voir où se trouve le premier <span>, il y a un cube rouge, et où se trouve le deuxième span, il y a une sphère bleue.

-

Synchronisation

-

Le code ci-dessus fonctionne, mais il y a un petit problème. -Si vos scènes sont compliquées ou si, pour une raison quelconque, -le rendu prend trop de temps, la position des scènes -dessinées dans le canvas sera en décalage par rapport au reste de la page.

-

Si nous donnons une bordure à chaque zone

-
.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-+  border: 1px solid black;
-}
-
-

Et nous définissons le fond de chaque scène

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('red');
-
-

Et si nous faisons défiler rapidement de haut en bas, nous verrons le problème. Voici une animation du défilement ralenti par 10.

-
- -

Nous pouvons passer à une méthode différente qui présente un compromis différent. Nous allons changer le CSS du canvas de position: fixed à position: absolute.

-
#c {
--  position: fixed;
-+  position: absolute;
-
-

Ensuite, nous définirons la transformation du canvas pour le déplacer afin -que le haut du canvas soit au niveau du haut de la partie -de la page actuellement défilée.

-
function render(time) {
-  ...
-
-  const transform = `translateY(${window.scrollY}px)`;
-  renderer.domElement.style.transform = transform;
-
-

position: fixed empêchait le canvas de défiler du tout -tandis que le reste de la page défilait par-dessus. position: absolute -permettra au canvas de défiler avec le reste de la page, ce qui signifie -que ce que nous dessinons restera avec la page pendant le défilement, -même si nous sommes trop lents à rendre. Lorsque nous aurons enfin l'occasion de rendre, -nous déplacerons le canvas pour qu'il corresponde à l'endroit où la page -a été défilée, puis nous referons le rendu. Cela signifie que seuls les bords -de la fenêtre montreront des morceaux non rendus pendant un instant, mais le contenu -au milieu de la page devrait correspondre et ne pas glisser. Voici une vue -des résultats de la nouvelle méthode ralentie par 10.

-
- -

Généraliser le code

-

Maintenant que nous avons fait fonctionner plusieurs scènes, rendons cela un peu plus générique.

-

Nous pourrions faire en sorte que la fonction de rendu principale, celle qui gère le canvas, contienne simplement une liste d'éléments et leur fonction de rendu associée. Pour chaque élément, elle vérifierait si l'élément est à l'écran et, si oui, appellerait la fonction de rendu correspondante. De cette manière, nous aurions un système générique où les scènes individuelles ne sont pas vraiment conscientes d'être rendues dans un espace plus petit.

-

Voici la fonction de rendu principale

-
const sceneElements = [];
-function addScene(elem, fn) {
-  sceneElements.push({elem, fn});
-}
-
-function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.setClearColor(clearColor, 0);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  const transform = `translateY(${window.scrollY}px)`;
-  renderer.domElement.style.transform = transform;
-
-  for (const {elem, fn} of sceneElements) {
-    // obtenir la position relative à la zone d'affichage de cet élément
-    const rect = elem.getBoundingClientRect();
-    const {left, right, top, bottom, width, height} = rect;
-
-    const isOffscreen =
-        bottom < 0 ||
-        top > renderer.domElement.clientHeight ||
-        right < 0 ||
-        left > renderer.domElement.clientWidth;
-
-    if (!isOffscreen) {
-      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
-      renderer.setScissor(left, positiveYUpBottom, width, height);
-      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-      fn(time, rect);
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

Vous pouvez voir qu'elle boucle sur sceneElements, qui est censé être un tableau d'objets, chacun ayant une propriété elem et fn.

-

Elle vérifie si l'élément est à l'écran. Si c'est le cas, elle appelle fn et lui passe l'heure actuelle et son rectangle.

-

Maintenant, le code de configuration pour chaque scène s'ajuste simplement pour s'ajouter à la liste des scènes

-
{
-  const elem = document.querySelector('#box');
-  const {scene, camera} = makeScene();
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({color: 'red'});
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-{
-  const elem = document.querySelector('#pyramid');
-  const {scene, camera} = makeScene();
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-

Avec cela, nous n'avons plus besoin de sceneInfo1 et sceneInfo2, et le code qui faisait pivoter les maillages est maintenant spécifique à chaque scène.

-

- -

-

Utilisation de l'attribut dataset HTML

-

Une dernière chose encore plus générique que nous pouvons faire est d'utiliser l'attribut dataset HTML. C'est une façon d'ajouter vos propres données à un élément HTML. Au lieu d'utiliser id="...", nous utiliserons data-diagram="..." comme ceci

-
<canvas id="c"></canvas>
-<p>
--  <span id="box" class="diagram left"></span>
-+  <span data-diagram="box" class="left"></span>
-  J'aime les boîtes. Les cadeaux viennent dans des boîtes.
-  Quand je trouve une nouvelle boîte, je suis toujours impatient de découvrir ce qu'il y a dedans.
-</p>
-<p>
--  <span id="pyramid" class="diagram left"></span>
-+  <span data-diagram="pyramid" class="right"></span>
-  Quand j'étais enfant, je rêvais de partir en expédition à l'intérieur d'une pyramide
-  et de trouver un tombeau inconnu rempli de momies et de trésors.
-</p>
-
-

Nous pouvons ensuite modifier le sélecteur CSS pour sélectionner cela

-
-.diagram
-+*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-
-

Nous allons modifier le code de configuration de la scène pour qu'il soit simplement une correspondance de noms avec des fonctions d'initialisation de scène qui renvoient une fonction de rendu de scène.

-
const sceneInitFunctionsByName = {
-  'box': () => {
-    const {scene, camera} = makeScene();
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-  'pyramid': () => {
-    const {scene, camera} = makeScene();
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

Et pour initialiser, nous pouvons simplement utiliser querySelectorAll pour trouver tous les diagrammes et appeler la fonction d'initialisation correspondante pour ce diagramme.

-
document.querySelectorAll('[data-diagram]').forEach((elem) => {
-  const sceneName = elem.dataset.diagram;
-  const sceneInitFunction = sceneInitFunctionsByName[sceneName];
-  const sceneRenderFunction = sceneInitFunction(elem);
-  addScene(elem, sceneRenderFunction);
-});
-
-

Pas de changement visuel, mais le code est encore plus générique.

-

-

Ajout de Contrôles à chaque élément

-

Ajouter de l'interactivité, par exemple un TrackballControls, est tout aussi simple. Nous ajoutons d'abord le script pour le contrôle.

-
import {TrackballControls} from 'three/addons/controls/TrackballControls.js';
-
-

Et ensuite, nous pouvons ajouter un TrackballControls à chaque scène en passant l'élément associé à cette scène.

-
-function makeScene() {
-+function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-+  scene.add(camera);
-
-+  const controls = new TrackballControls(camera, elem);
-+  controls.noZoom = true;
-+  controls.noPan = true;
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
--    scene.add(light);
-+    camera.add(light);
-  }
-
--  return {scene, camera};
-+ return {scene, camera, controls};
-}
-
-

Vous remarquerez que nous avons ajouté la caméra à la scène et la lumière à la caméra. -Cela rend la lumière relative à la caméra. Comme les TrackballControls -déplacent la caméra, c'est probablement ce que nous voulons. -Cela permet de maintenir la lumière éclairant le côté de l'objet que nous regardons.

-

Nous devons mettre à jour ces contrôles dans nos fonctions de rendu

-
const sceneInitFunctionsByName = {
-- 'box': () => {
--    const {scene, camera} = makeScene();
-+ 'box': (elem) => {
-+    const {scene, camera, controls} = makeScene(elem);
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
--  'pyramid': () => {
--    const {scene, camera} = makeScene();
-+  'pyramid': (elem) => {
-+    const {scene, camera, controls} = makeScene(elem);
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

Et maintenant, si vous faites glisser les objets, ils pivoteront.

-

- -

-

Ces techniques sont utilisées sur ce site même. En particulier, l'article sur les primitives et l'article sur les matériaux utilisent cette technique pour ajouter les différents exemples tout au long de l'article.

-

Une autre solution consisterait à rendre sur un canvas hors écran et à copier le résultat sur un canvas 2D à chaque élément. -L'avantage de cette solution est qu'il n'y a aucune limite à la manière dont vous pouvez composer chaque zone séparée. Avec la solution précédente, -nous avions un seul canvas en arrière-plan. Avec cette solution, nous avons des éléments HTML normaux.

-

L'inconvénient est que c'est plus lent car une copie doit avoir lieu pour chaque zone. La lenteur dépend du navigateur -et du GPU.

-

Les modifications nécessaires sont assez minimes

-

D'abord, nous allons modifier le HTML car nous n'avons plus besoin d'un canvas sur la page

-
<body>
--  <canvas id="c"></canvas>
-  ...
-</body>
-
-

puis nous allons modifier le CSS

-
-#c {
--  position: absolute;
--  left: 0;
--  top: 0;
--  width: 100%;
--  height: 100%;
--  display: block;
--  z-index: -1;
--}
-canvas {
-  width: 100%;
-  height: 100%;
-  display: block;
-}
-*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-

Nous avons fait en sorte que tous les canvases remplissent leur conteneur.

-

Maintenant, changeons le JavaScript. D'abord, nous ne recherchons plus -le canvas. Au lieu de cela, nous en créons un. Nous activons également -simplement le test scissor au début.

-
function main() {
--  const canvas = document.querySelector('#c');
-+  const canvas = document.createElement('canvas');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas, alpha: true});
-+  renderer.setScissorTest(true);
-
-  ...
-
-

Ensuite, pour chaque scène, nous créons un contexte de rendu 2D et -ajoutons son canvas à l'élément pour cette scène

-
const sceneElements = [];
-function addScene(elem, fn) {
-+  // ajouter un canvas à l'élément
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  elem.appendChild(ctx.canvas);
--  sceneElements.push({elem, fn});
-+  sceneElements.push({elem, ctx, fn});
-}
-
-

Ensuite, lors du rendu, si le canvas du renderer n'est pas -assez grand pour rendre cette zone, nous augmentons sa taille. -De même, si le canvas de cette zone n'a pas la bonne taille, nous -changeons sa taille. Enfin, nous définissons le scissor et le viewport, -rendons la scène pour cette zone, puis copions le résultat sur le canvas de la zone.

-
function render(time) {
-  time *= 0.001;
-
--  resizeRendererToDisplaySize(renderer);
--
--  renderer.setScissorTest(false);
--  renderer.setClearColor(clearColor, 0);
--  renderer.clear(true, true);
--  renderer.setScissorTest(true);
--
--  const transform = `translateY(${window.scrollY}px)`;
--  renderer.domElement.style.transform = transform;
-
--  for (const {elem, fn} of sceneElements) {
-+  for (const {elem, fn, ctx} of sceneElements) {
-    // obtenir la position relative à la zone d'affichage de cet élément
-    const rect = elem.getBoundingClientRect();
-    const {left, right, top, bottom, width, height} = rect;
-+    const rendererCanvas = renderer.domElement;
-
-    const isOffscreen =
-        bottom < 0 ||
--        top > renderer.domElement.clientHeight ||
-+        top > window.innerHeight ||
-        right < 0 ||
--        left > renderer.domElement.clientWidth;
-+        left > window.innerWidth;
-
-    if (!isOffscreen) {
--      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
--      renderer.setScissor(left, positiveYUpBottom, width, height);
--      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-+      // s'assurer que le canvas du renderer est assez grand
-+      if (rendererCanvas.width < width || rendererCanvas.height < height) {
-+        renderer.setSize(width, height, false);
-+      }
-+
-+      // s'assurer que le canvas pour cette zone est de la même taille que la zone
-+      if (ctx.canvas.width !== width || ctx.canvas.height !== height) {
-+        ctx.canvas.width = width;
-+        ctx.canvas.height = height;
-+      }
-+
-+      renderer.setScissor(0, 0, width, height);
-+      renderer.setViewport(0, 0, width, height);
-
-      fn(time, rect);
-
-+      // copier la scène rendue sur le canvas de cet élément
-+      ctx.globalCompositeOperation = 'copy';
-+      ctx.drawImage(
-+          rendererCanvas,
-+          0, rendererCanvas.height - height, width, height,  // src rect
-+          0, 0, width, height);                              // dst rect
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

Le résultat est identique

-

- -

-

Un autre avantage de cette solution est que vous pourriez potentiellement utiliser -OffscreenCanvas -pour rendre depuis un web worker et toujours utiliser cette technique. Malheureusement, en juillet 2020, -OffscreenCanvas n'est pris en charge que par Chrome.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/offscreencanvas.html b/manual/fr/offscreencanvas.html deleted file mode 100644 index 51b0eae9d902d3..00000000000000 --- a/manual/fr/offscreencanvas.html +++ /dev/null @@ -1,1089 +0,0 @@ - - - OffscreenCanvas - - - - - - - - - - - - - -
-
-

OffscreenCanvas

-
-
-
-

OffscreenCanvas -est une fonctionnalité de navigateur relativement nouvelle, actuellement disponible uniquement dans Chrome mais apparemment -à venir sur d'autres navigateurs. OffscreenCanvas permet à un web worker de rendre -sur un canevas. C'est une façon de décharger le travail lourd, comme le rendu d'une scène 3D complexe, -sur un web worker afin de ne pas ralentir la réactivité du navigateur. Cela -signifie également que les données sont chargées et analysées dans le worker, ce qui réduit potentiellement les saccades pendant -le chargement de la page.

-

Commencer à l'utiliser est assez simple. Portons l'exemple des 3 cubes en rotation depuis l'article sur la réactivité.

-

En général, les workers ont leur code séparé -dans un autre fichier script, tandis que la plupart des exemples sur ce site ont leurs -scripts intégrés dans le fichier HTML de la page sur laquelle ils se trouvent.

-

Dans notre cas, nous allons créer un fichier appelé offscreencanvas-cubes.js et -y copier tout le JavaScript depuis l'exemple réactif. Nous apporterons ensuite -les modifications nécessaires pour qu'il s'exécute dans un worker.

-

Nous avons encore besoin de JavaScript dans notre fichier HTML. La première chose -à faire est de trouver le canevas, puis de transférer son contrôle -pour qu'il soit offscreen en appelant canvas.transferControlToOffscreen.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-
-  ...
-
-

Nous pouvons ensuite démarrer notre worker avec new Worker(pathToScript, {type: 'module'}). -et lui passer l'objet offscreen.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-cubes.js', {type: 'module'});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-}
-main();
-
-

Il est important de noter que les workers ne peuvent pas accéder au DOM. Ils -ne peuvent pas regarder les éléments HTML ni recevoir les événements de souris ou -de clavier. La seule chose qu'ils peuvent généralement faire est de répondre -aux messages qui leur sont envoyés et de renvoyer des messages à la page.

-

Pour envoyer un message à un worker, nous appelons worker.postMessage et -lui passons 1 ou 2 arguments. Le premier argument est un objet JavaScript -qui sera cloné -et envoyé au worker. Le second argument est un tableau optionnel -d'objets qui font partie du premier objet et que nous voulons transférer -au worker. Ces objets ne seront pas clonés. Au lieu de cela, ils seront transférés -et cesseront d'exister dans la page principale. Cesser d'exister est probablement -la mauvaise description, ils sont plutôt neutralisés. Seuls certains types d'objets -peuvent être transférés au lieu d'être clonés. Ils incluent OffscreenCanvas, -donc une fois transféré, l'objet offscreen dans la page principale devient inutile.

-

Les workers reçoivent les messages via leur gestionnaire onmessage. L'objet -que nous avons passé à postMessage arrive sur event.data passé au gestionnaire onmessage -sur le worker. Le code ci-dessus déclare un type: 'main' dans l'objet qu'il passe -au worker. Cet objet n'a aucune signification pour le navigateur. Il est entièrement destiné -à notre propre usage. Nous allons créer un gestionnaire qui, basé sur le type, appelle -une fonction différente dans le worker. Ensuite, nous pourrons ajouter des fonctions au besoin et -les appeler facilement depuis la page principale.

-
const handlers = {
-  main,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

Vous pouvez voir ci-dessus que nous recherchons simplement le gestionnaire basé sur le type et que nous lui passons les data -qui ont été envoyées depuis la page principale.

-

Il ne nous reste plus qu'à commencer à modifier la fonction main que nous avons collée dans -offscreencanvas-cubes.js depuis l'article sur la réactivité.

-

Au lieu de rechercher le canevas depuis le DOM, nous le recevrons des données d'événement.

-
-function main() {
--  const canvas = document.querySelector('#c');
-+function main(data) {
-+  const {canvas} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  ...
-
-

En gardant à l'esprit que les workers ne peuvent pas voir le DOM du tout, le premier problème -que nous rencontrons est que resizeRendererToDisplaySize ne peut pas lire canvas.clientWidth -et canvas.clientHeight car ce sont des valeurs DOM. Voici le code original

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
-  const width = canvas.clientWidth;
-  const height = canvas.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

Au lieu de cela, nous devrons envoyer les tailles au worker dès qu'elles changent. -Ajoutons donc un état global et conservons la largeur et la hauteur à cet endroit.

-
const state = {
-  width: 300,  // par défaut du canevas
-  height: 150,  // par défaut du canevas
-};
-
-

Ensuite, ajoutons un gestionnaire 'size' pour mettre à jour ces valeurs.

-
+function size(data) {
-+  state.width = data.width;
-+  state.height = data.height;
-+}
-
-const handlers = {
-  main,
-+  size,
-};
-
-

Maintenant, nous pouvons modifier resizeRendererToDisplaySize pour utiliser state.width et state.height

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = canvas.clientWidth;
--  const height = canvas.clientHeight;
-+  const width = state.width;
-+  const height = state.height;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

et là où nous calculons l'aspect, nous avons besoin de changements similaires

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.aspect = state.width / state.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

De retour dans la page principale, nous enverrons un événement size chaque fois que la page change de taille.

-
const worker = new Worker('offscreencanvas-picking.js', {type: 'module'});
-worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-+function sendSize() {
-+  worker.postMessage({
-+    type: 'size',
-+    width: canvas.clientWidth,
-+    height: canvas.clientHeight,
-+  });
-+}
-+
-+window.addEventListener('resize', sendSize);
-+sendSize();
-
-

Nous l'appelons également une fois pour envoyer la taille initiale.

-

Et avec ces quelques modifications seulement, en supposant que votre navigateur prenne entièrement en charge OffscreenCanvas, -cela devrait fonctionner. Avant de l'exécuter, vérifions si le navigateur prend réellement en charge -OffscreenCanvas et, si ce n'est pas le cas, affichons une erreur. Ajoutons d'abord du HTML pour afficher l'erreur.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="noOffscreenCanvas" style="display:none;">
-+    <div>no OffscreenCanvas support</div>
-+  </div>
-</body>
-
-

et un peu de CSS pour cela

-
#noOffscreenCanvas {
-    display: flex;
-    width: 100%;
-    height: 100%;
-    align-items: center;
-    justify-content: center;
-    background: red;
-    color: white;
-}
-
-

et ensuite nous pouvons vérifier l'existence de transferControlToOffscreen pour voir -si le navigateur prend en charge OffscreenCanvas

-
function main() {
-  const canvas = document.querySelector('#c');
-+  if (!canvas.transferControlToOffscreen) {
-+    canvas.style.display = 'none';
-+    document.querySelector('#noOffscreenCanvas').style.display = '';
-+    return;
-+  }
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-picking.js', {type: 'module});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-  ...
-
-

et avec cela, si votre navigateur prend en charge OffscreenCanvas, cet exemple devrait fonctionner

-

- -

-

C'est formidable, mais comme tous les navigateurs ne prennent pas en charge OffscreenCanvas pour le moment, -modifions le code pour qu'il fonctionne à la fois avec OffscreenCanvas et, si ce n'est pas le cas, pour qu'il revienne à l'utilisation -du canevas dans la page principale comme d'habitude.

-
-

En aparté, si vous avez besoin de OffscreenCanvas pour rendre votre page réactive, alors -l'intérêt d'avoir un fallback n'est pas évident. Peut-être que selon si -vous exécutez sur la page principale ou dans un worker, vous pourriez ajuster la quantité -de travail effectué afin que lorsque vous exécutez dans un worker, vous puissiez faire plus que lorsque -vous exécutez dans la page principale. Ce que vous faites dépend entièrement de vous.

-
-

La première chose que nous devrions probablement faire est de séparer le code three.js -du code spécifique au worker. De cette façon, nous pouvons -utiliser le même code sur la page principale et sur le worker. En d'autres termes, -nous aurons maintenant 3 fichiers

-
    -
  1. notre fichier html.

    -

    threejs-offscreencanvas-w-fallback.html

    -
  2. -
  3. un fichier JavaScript qui contient notre code three.js.

    -

    shared-cubes.js

    -
  4. -
  5. notre code de support pour le worker

    -

    offscreencanvas-worker-cubes.js

    -
  6. -
-

shared-cubes.js et offscreencanvas-worker-cubes.js sont essentiellement -la séparation de notre fichier offscreencanvas-cubes.js précédent. Nous -copions d'abord tout le contenu de offscreencanvas-cubes.js dans shared-cube.js. Ensuite, -nous renommons main en init car nous avons déjà une fonction main dans notre -fichier HTML, et nous devons exporter init et state

-
import * as THREE from 'three';
-
--const state = {
-+export const state = {
-  width: 300,   // par défaut du canevas
-  height: 150,  // par défaut du canevas
-};
-
--function main(data) {
-+export function init(data) {
-  const {canvas} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-

et découpons juste les parties non liées à three.js

-
-function size(data) {
--  state.width = data.width;
--  state.height = data.height;
--}
--
--const handlers = {
--  main,
--  size,
--};
--
--self.onmessage = function(e) {
--  const fn = handlers[e.data.type];
--  if (typeof fn !== 'function') {
--    throw new Error('no handler for type: ' + e.data.type);
--  }
--  fn(e.data);
--};
-
-

Ensuite, nous copions les parties que nous venons de supprimer dans offscreencanvas-worker-cubes.js -et importons shared-cubes.js ainsi qu'appelons init au lieu de main.

-
import {init, state} from './shared-cubes.js';
-
-function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-const handlers = {
--  main,
-+  init,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

De même, nous devons inclure shared-cubes.js dans la page principale

-
<script type="module">
-+import {init, state} from './shared-cubes.js';
-
-

Nous pouvons supprimer le HTML et le CSS que nous avons ajoutés précédemment

-
<body>
-  <canvas id="c"></canvas>
--  <div id="noOffscreenCanvas" style="display:none;">
--    <div>no OffscreenCanvas support</div>
--  </div>
-</body>
-
-

et un peu de CSS pour cela

-
-#noOffscreenCanvas {
--    display: flex;
--    width: 100%;
--    height: 100%;
--    align-items: center;
--    justify-content: center;
--    background: red;
--    color: white;
--}
-
-

Ensuite, modifions le code dans la page principale pour appeler une fonction de démarrage ou une autre -selon que le navigateur prend en charge OffscreenCanvas.

-
function main() {
-  const canvas = document.querySelector('#c');
--  if (!canvas.transferControlToOffscreen) {
--    canvas.style.display = 'none';
--    document.querySelector('#noOffscreenCanvas').style.display = '';
--    return;
--  }
--  const offscreen = canvas.transferControlToOffscreen();
--  const worker = new Worker('offscreencanvas-picking.js', {type: 'module'});
--  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-+  if (canvas.transferControlToOffscreen) {
-+    startWorker(canvas);
-+  } else {
-+    startMainPage(canvas);
-+  }
-  ...
-
-

Nous allons déplacer tout le code que nous avions pour configurer le worker à l'intérieur de startWorker

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-cubes.js', {type: 'module'});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');
-}
-
-

et envoyer init au lieu de main

-
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-+  worker.postMessage({type: 'init', canvas: offscreen}, [offscreen]);
-
-

pour démarrer dans la page principale, nous pouvons faire ceci

-
function startMainPage(canvas) {
-  init({canvas});
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');
-}
-
-

et avec cela, notre exemple s'exécutera soit dans un OffscreenCanvas, soit il -reviendra à s'exécuter dans la page principale.

-

- -

-

C'était donc relativement facile. Essayons le picking. Nous allons prendre du code de -l'exemple RayCaster depuis l'article sur le picking -et le faire fonctionner offscreen.

-

Copions le fichier shared-cube.js vers shared-picking.js et ajoutons les parties de picking. Nous copions le PickHelper

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // restore the color if there is a picked object
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // cast a ray through the frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // get the list of objects the ray intersected
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // pick the first object. It's the closest one
-      this.pickedObject = intersectedObjects[0].object;
-      // save its color
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // set its emissive color to flashing red/yellow
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-const pickPosition = {x: 0, y: 0};
-const pickHelper = new PickHelper();
-
-

Nous avons mis à jour pickPosition à partir de la souris comme ceci

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // notez que nous inversons Y
-}
-window.addEventListener('mousemove', setPickPosition);
-
-

Un worker ne peut pas lire la position de la souris directement, donc tout comme le code de taille, -envoyons un message avec la position de la souris. Comme pour le code de taille, nous enverrons -la position de la souris et mettrons à jour pickPosition

-
function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-+function mouse(data) {
-+  pickPosition.x = data.x;
-+  pickPosition.y = data.y;
-+}
-
-const handlers = {
-  init,
-+  mouse,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

De retour dans notre page principale, nous devons ajouter du code pour passer la souris -au worker ou à la page principale.

-
+let sendMouse;
-
-function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-picking.js', {type: 'module'});
-  worker.postMessage({type: 'init', canvas: offscreen}, [offscreen]);
-
-+  sendMouse = (x, y) => {
-+    worker.postMessage({
-+      type: 'mouse',
-+      x,
-+      y,
-+    });
-+  };
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-function startMainPage(canvas) {
-  init({canvas});
-
-+  sendMouse = (x, y) => {
-+    pickPosition.x = x;
-+    pickPosition.y = y;
-+  };
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');  /* eslint-disable-line no-console */
-}
-
-

Ensuite, nous pouvons copier tout le code de gestion de la souris dans la page principale et -apporter juste des modifications mineures pour utiliser sendMouse

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // note we flip Y
-+  sendMouse(
-+      (pos.x / canvas.clientWidth ) *  2 - 1,
-+      (pos.y / canvas.clientHeight) * -2 + 1);  // notez que nous inversons Y
-}
-
-function clearPickPosition() {
-  // Contrairement à la souris qui a toujours une position
-  // si l'utilisateur arrête de toucher l'écran, nous voulons
-  // arrêter le picking. Pour l'instant, nous choisissons juste une valeur
-  // peu susceptible de sélectionner quelque chose
--  pickPosition.x = -100000;
--  pickPosition.y = -100000;
-+  sendMouse(-100000, -100000);
-}
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-window.addEventListener('touchstart', (event) => {
-  // prevent the window from scrolling
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

et avec cela, le picking devrait fonctionner avec OffscreenCanvas.

-

- -

-

Allons un peu plus loin et ajoutons les OrbitControls. -Cela sera un peu plus complexe. Les OrbitControls utilisent -le DOM de manière assez extensive pour vérifier la souris, les événements tactiles, -et le clavier.

-

Contrairement à notre code jusqu'à présent, nous ne pouvons pas vraiment utiliser un objet state global -sans réécrire tout le code des OrbitControls pour qu'il fonctionne avec. -Les OrbitControls prennent un HTMLElement auquel ils attachent la plupart -des événements DOM qu'ils utilisent. Peut-être pourrions-nous passer notre propre -objet qui a la même surface d'API qu'un élément DOM. -Nous n'avons besoin de prendre en charge que les fonctionnalités dont les OrbitControls ont besoin.

-

En fouillant dans le code source des OrbitControls, -il semble que nous devions gérer les événements suivants.

-
    -
  • contextmenu
  • -
  • pointerdown
  • -
  • pointermove
  • -
  • pointerup
  • -
  • touchstart
  • -
  • touchmove
  • -
  • touchend
  • -
  • wheel
  • -
  • keydown
  • -
-

Pour les événements de pointeur, nous avons besoin des propriétés ctrlKey, metaKey, shiftKey, -button, pointerType, clientX, clientY, pageX et pageY.

-

Pour les événements keydown, nous avons besoin des propriétés ctrlKey, metaKey, shiftKey -et keyCode.

-

Pour l'événement wheel, nous n'avons besoin que de la propriété deltaY.

-

Et pour les événements tactiles, nous n'avons besoin que de pageX et pageY de -la propriété touches.

-

Alors, créons une paire d'objets proxy. Une partie s'exécutera dans la page principale, -capturera tous ces événements et transmettra les valeurs de propriété pertinentes -au worker. L'autre partie s'exécutera dans le worker, recevra ces -événements et les transmettra en utilisant des événements qui ont la même structure -que les événements DOM originaux, de sorte que les OrbitControls ne pourront pas -faire la différence.

-

Voici le code pour la partie worker.

-
import {EventDispatcher} from 'three';
-
-class ElementProxyReceiver extends EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-}
-
-

Tout ce qu'il fait est, s'il reçoit un message, de le dispatcher. -Il hérite de EventDispatcher qui fournit des méthodes comme -addEventListener et removeEventListener, tout comme un élément DOM, -donc si nous le passons aux OrbitControls, cela devrait fonctionner.

-

ElementProxyReceiver gère 1 élément. Dans notre cas, nous n'en avons besoin que d'un, -mais il est préférable d'anticiper, alors créons un gestionnaire pour gérer -plus d'un.

-
class ProxyManager {
-  constructor() {
-    this.targets = {};
-    this.handleEvent = this.handleEvent.bind(this);
-  }
-  makeProxy(data) {
-    const {id} = data;
-    const proxy = new ElementProxyReceiver();
-    this.targets[id] = proxy;
-  }
-  getProxy(id) {
-    return this.targets[id];
-  }
-  handleEvent(data) {
-    this.targets[data.id].handleEvent(data.data);
-  }
-}
-
-

Nous pouvons créer une instance de ProxyManager et appeler sa méthode makeProxy -avec un identifiant, ce qui créera un ElementProxyReceiver qui -répondra aux messages avec cet identifiant.

-

Connectons-le au gestionnaire de messages de notre worker.

-
const proxyManager = new ProxyManager();
-
-function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-function makeProxy(data) {
-  proxyManager.makeProxy(data);
-}
-
-...
-
-const handlers = {
--  init,
--  mouse,
-+  start,
-+  makeProxy,
-+  event: proxyManager.handleEvent,
-   size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

Dans notre code three.js partagé, nous devons importer les OrbitControls et les configurer.

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-export function init(data) {
--  const {canvas} = data;
-+  const {canvas, inputElement} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-+  const controls = new OrbitControls(camera, inputElement);
-+  controls.target.set(0, 0, 0);
-+  controls.update();
-
-

Notez que nous passons notre proxy aux OrbitControls via inputElement -au lieu de passer le canevas comme nous le faisons dans d'autres exemples sans OffscreenCanvas.

-

Ensuite, nous pouvons déplacer tout le code des événements de picking du fichier HTML -vers le code three.js partagé également, tout en changeant -canvas en inputElement.

-
function getCanvasRelativePosition(event) {
--  const rect = canvas.getBoundingClientRect();
-+  const rect = inputElement.getBoundingClientRect();
-  return {
-    x: event.clientX - rect.left,
-    y: event.clientY - rect.top,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  sendMouse(
--      (pos.x / canvas.clientWidth ) *  2 - 1,
--      (pos.y / canvas.clientHeight) * -2 + 1);  // note we flip Y
-+  pickPosition.x = (pos.x / inputElement.clientWidth ) *  2 - 1;
-+  pickPosition.y = (pos.y / inputElement.clientHeight) * -2 + 1;  // notez que nous inversons Y
-}
-
-function clearPickPosition() {
-  // Contrairement à la souris qui a toujours une position
-  // si l'utilisateur arrête de toucher l'écran, nous voulons
-  // arrêter le picking. Pour l'instant, nous choisissons juste une valeur
-  // peu susceptible de sélectionner quelque chose
--  sendMouse(-100000, -100000);
-+  pickPosition.x = -100000;
-+  pickPosition.y = -100000;
-}
-
-*inputElement.addEventListener('mousemove', setPickPosition);
-*inputElement.addEventListener('mouseout', clearPickPosition);
-*inputElement.addEventListener('mouseleave', clearPickPosition);
-
-*inputElement.addEventListener('touchstart', (event) => {
-  // prevent the window from scrolling
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-*inputElement.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-*inputElement.addEventListener('touchend', clearPickPosition);
-
-

De retour dans la page principale, nous avons besoin de code pour envoyer des messages pour -tous les événements que nous avons énumérés ci-dessus.

-
let nextProxyId = 0;
-class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // register an id
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-  }
-}
-
-

ElementProxy prend l'élément dont nous voulons proxifier les événements. Il -enregistre ensuite un identifiant auprès du worker en en choisissant un et en l'envoyant -via le message makeProxy que nous avons configuré précédemment. Le worker créera -un ElementProxyReceiver et l'enregistrera avec cet identifiant.

-

Nous avons ensuite un objet de gestionnaires d'événements à enregistrer. De cette façon, -nous pouvons passer des gestionnaires uniquement pour les événements que nous voulons transmettre au -worker.

-

Lorsque nous démarrons le worker, nous créons d'abord un proxy et passons nos gestionnaires d'événements.

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-orbitcontrols.js', {type: 'module'});
-
-+  const eventHandlers = {
-+    contextmenu: preventDefaultHandler,
-+    mousedown: mouseEventHandler,
-+    mousemove: mouseEventHandler,
-+    mouseup: mouseEventHandler,
-+    pointerdown: mouseEventHandler,
-+    pointermove: mouseEventHandler,
-+    pointerup: mouseEventHandler,
-+    touchstart: touchEventHandler,
-+    touchmove: touchEventHandler,
-+    touchend: touchEventHandler,
-+    wheel: wheelEventHandler,
-+    keydown: filteredKeydownEventHandler,
-+  };
-+  const proxy = new ElementProxy(canvas, worker, eventHandlers);
-  worker.postMessage({
-    type: 'start',
-    canvas: offscreen,
-+    canvasId: proxy.id,
-  }, [offscreen]);
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-

Et voici les gestionnaires d'événements. Tout ce qu'ils font est de copier une liste de propriétés -à partir de l'événement qu'ils reçoivent. On leur passe une fonction sendEvent à laquelle ils passent les données -qu'ils créent. Cette fonction ajoutera l'identifiant correct et l'enverra au worker.

-
const mouseEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'button',
-  'pointerType',
-  'clientX',
-  'clientY',
-  'pointerId',
-  'pageX',
-  'pageY',
-]);
-const wheelEventHandlerImpl = makeSendPropertiesHandler([
-  'deltaX',
-  'deltaY',
-]);
-const keydownEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'keyCode',
-]);
-
-function wheelEventHandler(event, sendFn) {
-  event.preventDefault();
-  wheelEventHandlerImpl(event, sendFn);
-}
-
-function preventDefaultHandler(event) {
-  event.preventDefault();
-}
-
-function copyProperties(src, properties, dst) {
-  for (const name of properties) {
-      dst[name] = src[name];
-  }
-}
-
-function makeSendPropertiesHandler(properties) {
-  return function sendProperties(event, sendFn) {
-    const data = {type: event.type};
-    copyProperties(event, properties, data);
-    sendFn(data);
-  };
-}
-
-function touchEventHandler(event, sendFn) {
-  // preventDefault() corrige les événements mousemove, mouseup et mousedown
-  // qui se déclenchent lors d'un simple toucher/relâcher
-  // Cela n'arrive qu'avec OffscreenCanvas
-  event.preventDefault();
-  const touches = [];
-  const data = {type: event.type, touches};
-  for (let i = 0; i < event.touches.length; ++i) {
-    const touch = event.touches[i];
-    touches.push({
-      pageX: touch.pageX,
-      pageY: touch.pageY,
-      clientX: touch.clientX,
-      clientY: touch.clientY,
-    });
-  }
-  sendFn(data);
-}
-
-// Les quatre touches fléchées
-const orbitKeys = {
-  '37': true,  // left
-  '38': true,  // up
-  '39': true,  // right
-  '40': true,  // down
-};
-function filteredKeydownEventHandler(event, sendFn) {
-  const {keyCode} = event;
-  if (orbitKeys[keyCode]) {
-    event.preventDefault();
-    keydownEventHandler(event, sendFn);
-  }
-}
-
-

Cela semble proche de fonctionner, mais si nous l'essayons réellement, nous verrons -que les OrbitControls ont besoin de quelques éléments supplémentaires.

-

L'une d'elles est qu'ils appellent element.focus. Nous n'avons pas besoin que cela se produise -dans le worker, alors ajoutons simplement un stub.

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-+  focus() {
-+    // sans opération
-+  }
-}
-
-

Une autre chose est qu'ils appellent event.preventDefault et event.stopPropagation. -Nous gérons déjà cela dans la page principale, donc ceux-ci peuvent également être un noop (sans opération).

-
+function noop() {
-+}
-
-class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-+    data.preventDefault = noop;
-+    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // sans opération
-  }
-}
-
-

Une autre chose est qu'ils regardent clientWidth et clientHeight. Nous -passions la taille auparavant, mais nous pouvons mettre à jour la paire de proxies -pour passer cela également.

-

Dans le worker...

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-+  get clientWidth() {
-+    return this.width;
-+  }
-+  get clientHeight() {
-+    return this.height;
-+  }
-+  getBoundingClientRect() {
-+    return {
-+      left: this.left,
-+      top: this.top,
-+      width: this.width,
-+      height: this.height,
-+      right: this.left + this.width,
-+      bottom: this.top + this.height,
-+    };
-+  }
-  handleEvent(data) {
-+    if (data.type === 'size') {
-+      this.left = data.left;
-+      this.top = data.top;
-+      this.width = data.width;
-+      this.height = data.height;
-+      return;
-+    }
-    data.preventDefault = noop;
-    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // sans opération
-  }
-}
-
-

de retour dans la page principale, nous devons envoyer la taille ainsi que les positions gauche et haut également. -Notez qu'en l'état, nous ne gérons pas si le canevas se déplace, seulement s'il redimensionne. Si vous vouliez -gérer le déplacement, vous devriez appeler sendSize chaque fois que quelque chose déplace le canevas.

-
class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // register an id
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-+    sendSize();
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-
-+    function sendSize() {
-+      const rect = element.getBoundingClientRect();
-+      sendEvent({
-+        type: 'size',
-+        left: rect.left,
-+        top: rect.top,
-+        width: element.clientWidth,
-+        height: element.clientHeight,
-+      });
-+    }
-+
-+    window.addEventListener('resize', sendSize);
-  }
-}
-
-

et dans notre code three.js partagé, nous n'avons plus besoin de state

-
-export const state = {
--  width: 300,   // par défaut du canevas
--  height: 150,  // par défaut du canevas
--};
-
-...
-
-function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = state.width;
--  const height = state.height;
-+  const width = inputElement.clientWidth;
-+  const height = inputElement.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = state.width / state.height;
-+    camera.aspect = inputElement.clientWidth / inputElement.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

Quelques hacks supplémentaires. Les OrbitControls ajoutent des événements pointermove et pointerup à l'ownerDocument -de l'élément pour gérer la capture de la souris (lorsque la souris sort de la fenêtre).

-

De plus, le code référence le document global, mais il n'y a pas de document global -dans un worker.

-

Nous pouvons résoudre tout cela avec 2 hacks rapides. Dans notre code worker, -nous allons réutiliser notre proxy pour les deux problèmes.

-
function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-+  proxy.ownerDocument = proxy; // HACK!
-+  self.document = {} // HACK!
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-

Cela donnera aux OrbitControls quelque chose à inspecter qui -correspond à leurs attentes.

-

Je sais que c'était un peu difficile à suivre. La version courte est la suivante : -ElementProxy s'exécute sur la page principale et transmet les événements DOM -à ElementProxyReceiver dans le worker, qui se fait passer pour un HTMLElement -que nous pouvons utiliser à la fois avec les OrbitControls et avec notre propre code.

-

La dernière chose est notre fallback lorsque nous n'utilisons pas OffscreenCanvas. -Tout ce que nous avons à faire est de passer le canevas lui-même comme notre inputElement.

-
function startMainPage(canvas) {
--  init({canvas});
-+  init({canvas, inputElement: canvas});
-  console.log('using regular canvas');
-}
-
-

et maintenant nous devrions avoir les OrbitControls fonctionnant avec OffscreenCanvas

-

- -

-

C'est probablement l'exemple le plus compliqué sur ce site. Il est un -peu difficile à suivre car il y a 3 fichiers impliqués pour chaque -exemple. Le fichier HTML, le fichier worker, le code three.js partagé.

-

J'espère que ce n'était pas trop difficile à comprendre et que cela a fourni -des exemples utiles pour travailler avec three.js, OffscreenCanvas et les web workers.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/optimize-lots-of-objects-animated.html b/manual/fr/optimize-lots-of-objects-animated.html deleted file mode 100644 index 1742cb77df7b30..00000000000000 --- a/manual/fr/optimize-lots-of-objects-animated.html +++ /dev/null @@ -1,492 +0,0 @@ - - - Optimiser de nombreux objets animés - - - - - - - - - - - - - -
-
-

Optimiser de nombreux objets animés

-
-
-
-

Cet article est une continuation de un article sur l'optimisation de nombreux objets -. Si vous ne l'avez pas encore lu, -veuillez le lire avant de poursuivre.

-

Dans l'article précédent, nous avons fusionné environ 19000 cubes en une -seule géométrie. Cela a eu l'avantage d'optimiser notre dessin -de 19000 cubes, mais cela a eu l'inconvénient de rendre plus difficile -le déplacement d'un cube individuel.

-

Selon ce que nous essayons d'accomplir, il existe différentes solutions. -Dans ce cas, affichons plusieurs ensembles de données et animons la transition entre les ensembles.

-

La première chose à faire est d'obtenir plusieurs ensembles de données. Idéalement, nous -pré-traiterions probablement les données hors ligne, mais dans ce cas, chargeons 2 ensembles de -données et générons-en 2 autres.

-

Voici notre ancien code de chargement

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(addBoxes)
-  .then(render);
-
-

Changeons-le pour quelque chose comme ceci

-
async function loadData(info) {
-  const text = await loadFile(info.url);
-  info.file = parseData(text);
-}
-
-async function loadAll() {
-  const fileInfos = [
-    {name: 'men',   hueRange: [0.7, 0.3], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc' },
-    {name: 'women', hueRange: [0.9, 1.1], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014ft_2010_cntm_1_deg.asc' },
-  ];
-
-  await Promise.all(fileInfos.map(loadData));
-
-  ...
-}
-loadAll();
-
-

Le code ci-dessus chargera tous les fichiers dans fileInfos et une fois terminé, chaque objet -dans fileInfos aura une propriété file contenant le fichier chargé. name et hueRange -seront utilisés plus tard. name sera pour un champ d'interface utilisateur. hueRange sera utilisé pour -choisir une plage de teintes à appliquer.

-

Les deux fichiers ci-dessus sont apparemment le nombre d'hommes par zone et le nombre de -femmes par zone en 2010. Notez que je n'ai aucune idée si ces données sont correctes, mais -ce n'est pas vraiment important. L'important est de montrer différents ensembles -de données.

-

Générons 2 ensembles de données supplémentaires. L'un représentant les lieux où le nombre -d'hommes est supérieur au nombre de femmes, et inversement, les lieux où -le nombre de femmes est supérieur au nombre d'hommes.

-

La première chose, écrivons une fonction qui, étant donné un tableau bidimensionnel -de tableaux comme nous avions précédemment, va l'appliquer pour générer un nouveau tableau bidimensionnel -de tableaux.

-
function mapValues(data, fn) {
-  return data.map((row, rowNdx) => {
-    return row.map((value, colNdx) => {
-      return fn(value, rowNdx, colNdx);
-    });
-  });
-}
-
-

Comme la fonction normale Array.map, la fonction mapValues appelle une fonction -fn pour chaque valeur dans le tableau de tableaux. Elle lui passe la valeur ainsi que les -indices de ligne et de colonne.

-

Maintenant, écrivons du code pour générer un nouveau fichier qui est une comparaison entre 2 -fichiers.

-
function makeDiffFile(baseFile, otherFile, compareFn) {
-  let min;
-  let max;
-  const baseData = baseFile.data;
-  const otherData = otherFile.data;
-  const data = mapValues(baseData, (base, rowNdx, colNdx) => {
-    const other = otherData[rowNdx][colNdx];
-      if (base === undefined || other === undefined) {
-        return undefined;
-      }
-      const value = compareFn(base, other);
-      min = Math.min(min === undefined ? value : min, value);
-      max = Math.max(max === undefined ? value : max, value);
-      return value;
-  });
-  // make a copy of baseFile and replace min, max, and data
-  // with the new data
-  return {...baseFile, min, max, data};
-}
-
-

Le code ci-dessus utilise mapValues pour générer un nouvel ensemble de données qui est -une comparaison basée sur la fonction compareFn passée en paramètre. Il suit également -les résultats min et max de la comparaison. Enfin, il crée un nouveau fichier avec -toutes les mêmes propriétés que baseFile, sauf avec de nouvelles valeurs pour min, max et data.

-

Ensuite, utilisons cela pour créer 2 nouveaux ensembles de données.

-
{
-  const menInfo = fileInfos[0];
-  const womenInfo = fileInfos[1];
-  const menFile = menInfo.file;
-  const womenFile = womenInfo.file;
-
-  function amountGreaterThan(a, b) {
-    return Math.max(a - b, 0);
-  }
-  fileInfos.push({
-    name: '>50%men',
-    hueRange: [0.6, 1.1],
-    file: makeDiffFile(menFile, womenFile, (men, women) => {
-      return amountGreaterThan(men, women);
-    }),
-  });
-  fileInfos.push({
-    name: '>50% women',
-    hueRange: [0.0, 0.4],
-    file: makeDiffFile(womenFile, menFile, (women, men) => {
-      return amountGreaterThan(women, men);
-    }),
-  });
-}
-
-

Maintenant, générons une interface utilisateur pour sélectionner parmi ces ensembles de données. Nous avons d'abord besoin -d'un peu de HTML pour l'interface utilisateur.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui"></div>
-</body>
-
-

et du CSS pour le faire apparaître en haut à gauche

-
#ui {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-}
-#ui>div {
-  font-size: 20pt;
-  padding: 1em;
-  display: inline-block;
-}
-#ui>div.selected {
-  color: red;
-}
-
-

Ensuite, nous pouvons parcourir chaque fichier et générer un ensemble de boîtes fusionnées par -ensemble de données, ainsi qu'un élément qui, au survol, affichera cet ensemble -et masquera tous les autres.

-
// afficher les données sélectionnées, masquer les autres
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
-    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-  });
-  requestRenderIfNotRequested();
-}
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
-  const boxes = addBoxes(info.file, info.hueRange);
-  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  div.addEventListener('mouseover', () => {
-    showFileInfo(fileInfos, info);
-  });
-});
-// afficher le premier ensemble de données
-showFileInfo(fileInfos, fileInfos[0]);
-
-

Une autre modification dont nous avons besoin par rapport à l'exemple précédent est de faire en sorte -que addBoxes accepte un hueRange.

-
-function addBoxes(file) {
-+function addBoxes(file, hueRange) {
-
-  ...
-
-    // calculer une couleur
--    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const hue = THREE.MathUtils.lerp(...hueRange, amount);
-
-  ...
-
-

et avec cela, nous devrions pouvoir afficher 4 ensembles de données. Survolez les étiquettes -avec la souris ou touchez-les pour changer d'ensemble.

-

- -

-

Notez qu'il y a quelques points de données étranges qui ressortent vraiment. Je me demande ce qui se passe -avec ceux-là !??! Dans tous les cas, comment animer entre ces 4 ensembles de données.

-

Beaucoup d'idées.

-
    -
  • Faites simplement un fondu entre eux en utilisant Material.opacity

    -

    Le problème avec cette solution est que les cubes se superposent parfaitement, ce qui -entraînera des problèmes de z-fighting. Il est possible de résoudre -cela en changeant la fonction de profondeur et en utilisant le blending. Nous devrions -probablement examiner cette option.

    -
  • -
  • Agrandissez l'ensemble que nous voulons voir et réduisez les autres ensembles

    -

    Parce que toutes les boîtes ont leur origine au centre de la planète, -si nous les réduisons en dessous de 1.0, elles s'enfonceront dans la planète. Au début, cela -semble une bonne idée, mais le problème est que toutes les boîtes de faible hauteur -disparaîtront presque immédiatement et ne seront pas remplacées tant que le nouvel -ensemble de données n'aura pas atteint 1.0. Cela rend la transition peu agréable. -On pourrait peut-être résoudre cela avec un shader personnalisé sophistiqué.

    -
  • -
  • Utiliser les Morphtargets

    -

    Les Morphtargets sont un moyen de fournir plusieurs valeurs pour chaque sommet -de la géométrie et de les morpher ou de les interpoler linéairement (lerp). -Les Morphtargets sont le plus souvent utilisés pour l'animation faciale de personnages -3D, mais ce n'est pas leur seule utilisation.

    -
  • -
-

Essayons les morphtargets.

-

Nous créerons toujours une géométrie pour chaque ensemble de données, mais nous extrairons -ensuite l'attribut position de chacun et les utiliserons comme morphtargets.

-

Changeons d'abord addBoxes pour qu'elle crée et retourne simplement la géométrie fusionnée.

-
-function addBoxes(file) {
-+function makeBoxes(file, hueRange) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  ...
-
--  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
--      geometries, false);
--  const material = new THREE.MeshBasicMaterial({
--    vertexColors: true,
--  });
--  const mesh = new THREE.Mesh(mergedGeometry, material);
--  scene.add(mesh);
--  return mesh;
-+  return BufferGeometryUtils.mergeGeometries(
-+     geometries, false);
-}
-
-

Il y a cependant une autre chose que nous devons faire ici. Les morphtargets doivent -tous avoir exactement le même nombre de sommets. Le sommet #123 dans une cible doit -avoir un sommet correspondant #123 dans toutes les autres cibles. Mais, tel que c'est actuellement, -différents ensembles de données pourraient avoir des points de données sans données, donc aucune boîte ne sera -générée pour ce point, ce qui signifierait l'absence de sommets correspondants pour un autre -ensemble. Nous devons donc vérifier tous les ensembles de données et soit toujours générer -quelque chose s'il y a des données dans n'importe quel ensemble, soit ne rien générer s'il -manque des données dans n'importe quel ensemble. Faisons le second cas.

-
+function dataMissingInAnySet(fileInfos, latNdx, lonNdx) {
-+  for (const fileInfo of fileInfos) {
-+    if (fileInfo.file.data[latNdx][lonNdx] === undefined) {
-+      return true;
-+    }
-+  }
-+  return false;
-+}
-
--function makeBoxes(file, hueRange) {
-+function makeBoxes(file, hueRange, fileInfos) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  ...
-
-  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-+      if (dataMissingInAnySet(fileInfos, latNdx, lonNdx)) {
-+        return;
-+      }
-      const amount = (value - min) / range;
-
-  ...
-
-

Maintenant, nous allons changer le code qui appelait addBoxes pour qu'il utilise makeBoxes -et configure les morphtargets.

-
+// créer la géométrie pour chaque ensemble de données
-+const geometries = fileInfos.map((info) => {
-+  return makeBoxes(info.file, info.hueRange, fileInfos);
-+});
-+
-+// utiliser la première géométrie comme base
-+// et ajouter toutes les géométries comme morphtargets
-+const baseGeometry = geometries[0];
-+baseGeometry.morphAttributes.position = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('position');
-+  const name = `target${ndx}`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+baseGeometry.morphAttributes.color = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('color');
-+  const name = `target${ndx}`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-+});
-+const mesh = new THREE.Mesh(baseGeometry, material);
-+scene.add(mesh);
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
--  const boxes = addBoxes(info.file, info.hueRange);
--  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  function show() {
-    showFileInfo(fileInfos, info);
-  }
-  div.addEventListener('mouseover', show);
-  div.addEventListener('touchstart', show);
-});
-// afficher le premier ensemble de données
-showFileInfo(fileInfos, fileInfos[0]);
-
-

Ci-dessus, nous créons une géométrie pour chaque ensemble de données, utilisons la première comme base, -puis obtenons un attribut position de chaque géométrie et l'ajoutons comme -morphtarget à la géométrie de base pour position.

-

Maintenant, nous devons changer la manière dont nous affichons et masquons les différents ensembles de données. -Au lieu d'afficher ou de masquer un maillage, nous devons modifier l'influence des -morphtargets. Pour l'ensemble de données que nous voulons voir, nous devons avoir une influence de 1, -et pour tous ceux que nous ne voulons pas voir, nous devons avoir une influence de 0.

-

Nous pourrions simplement les régler directement à 0 ou 1, mais si nous faisions cela, nous ne verrions aucune -animation, cela se ferait instantanément, ce qui ne serait pas différent de ce que nous avons déjà. -Nous pourrions également écrire du code d'animation personnalisé, ce qui serait facile, -mais comme le globe webgl original utilise -une bibliothèque d'animation, utilisons la même ici.

-

Nous devons inclure la bibliothèque

-
import * as THREE from 'three';
-import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import TWEEN from 'three/addons/libs/tween.module.js';
-
-

Et ensuite, créer un Tween pour animer les influences.

-
// afficher les données sélectionnées, masquer les autres
-function showFileInfo(fileInfos, fileInfo) {
-+  const targets = {};
--  fileInfos.forEach((info) => {
-+  fileInfos.forEach((info, i) => {
-    const visible = fileInfo === info;
--    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-+    targets[i] = visible ? 1 : 0;
-  });
-+  const durationInMs = 1000;
-+  new TWEEN.Tween(mesh.morphTargetInfluences)
-+    .to(targets, durationInMs)
-+    .start();
-  requestRenderIfNotRequested();
-}
-
-

Nous sommes également censés appeler TWEEN.update à chaque image dans notre boucle de rendu, -mais cela soulève un problème. « tween.js » est conçu pour un rendu continu, -mais nous rendons à la demande. Nous pourrions -passer au rendu continu, mais il est parfois agréable de ne rendre qu'à la demande -car cela permet d'économiser l'énergie de l'utilisateur lorsque rien ne se passe, -alors voyons si nous pouvons le faire animer à la demande.

-

Nous allons créer un TweenManager pour nous aider. Nous l'utiliserons pour créer les Tweens -et les suivre. Il aura une méthode update qui retournera true -si nous devons l'appeler à nouveau, et false si toutes les animations sont terminées.

-
class TweenManger {
-  constructor() {
-    this.numTweensRunning = 0;
-  }
-  _handleComplete() {
-    --this.numTweensRunning;
-    console.assert(this.numTweensRunning >= 0);
-  }
-  createTween(targetObject) {
-    const self = this;
-    ++this.numTweensRunning;
-    let userCompleteFn = () => {};
-    // create a new tween and install our own onComplete callback
-    const tween = new TWEEN.Tween(targetObject).onComplete(function(...args) {
-      self._handleComplete();
-      userCompleteFn.call(this, ...args);
-    });
-    // replace the tween's onComplete function with our own
-    // so we can call the user's callback if they supply one.
-    tween.onComplete = (fn) => {
-      userCompleteFn = fn;
-      return tween;
-    };
-    return tween;
-  }
-  update() {
-    TWEEN.update();
-    return this.numTweensRunning > 0;
-  }
-}
-
-

Pour l'utiliser, nous allons en créer un

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const tweenManager = new TweenManger();
-
-  ...
-
-

Nous l'utiliserons pour créer nos Tweens.

-
// afficher les données sélectionnées, masquer les autres
-function showFileInfo(fileInfos, fileInfo) {
-  const targets = {};
-  fileInfos.forEach((info, i) => {
-    const visible = fileInfo === info;
-    info.elem.className = visible ? 'selected' : '';
-    targets[i] = visible ? 1 : 0;
-  });
-  const durationInMs = 1000;
--  new TWEEN.Tween(mesh.morphTargetInfluences)
-+  tweenManager.createTween(mesh.morphTargetInfluences)
-    .to(targets, durationInMs)
-    .start();
-  requestRenderIfNotRequested();
-}
-
-

Ensuite, nous mettrons à jour notre boucle de rendu pour mettre à jour les tweens et continuer à rendre -s'il y a encore des animations en cours.

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (tweenManager.update()) {
-+    requestRenderIfNotRequested();
-+  }
-
-  controls.update();
-  renderer.render(scene, camera);
-}
-render();
-
-

Et avec cela, nous devrions pouvoir animer entre les ensembles de données.

-

- -

-

J'espère que parcourir ceci a été utile. L'utilisation des morphtargets est une technique courante pour -déplacer de nombreux objets. Par exemple, nous pourrions donner à chaque cube un endroit aléatoire -dans une autre cible et morpher de là à leurs premières positions sur le globe. -Cela pourrait être une façon intéressante de présenter le globe.

-

Ensuite, vous pourriez être intéressé par l'ajout d'étiquettes à un globe, ce qui est abordé -dans Aligner les éléments HTML sur la 3D.

-

Note : Nous pourrions essayer de simplement représenter le pourcentage d'hommes ou de femmes, ou la différence -brute, mais compte tenu de la manière dont nous affichons les informations, des cubes qui poussent -depuis la surface de la terre, nous préférerions que la plupart des cubes soient bas. Si nous -utilisions l'une de ces autres comparaisons, la plupart des cubes auraient environ la moitié -de leur hauteur maximale, ce qui ne donnerait pas une bonne visualisation. N'hésitez pas -à changer amountGreaterThan de Math.max(a - b, 0) à quelque chose comme (a - b) -« différence brute » ou a / (a + b) « pourcentage » et vous verrez ce que je veux dire.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/optimize-lots-of-objects.html b/manual/fr/optimize-lots-of-objects.html deleted file mode 100644 index 99a40b4e78bfcd..00000000000000 --- a/manual/fr/optimize-lots-of-objects.html +++ /dev/null @@ -1,511 +0,0 @@ - - - Optimiser Beaucoup d'Objets - - - - - - - - - - - - - -
-
-

Optimiser Beaucoup d'Objets

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le premier article -est les bases de three.js. Si vous ne l'avez pas encore lu -et que vous débutez avec three.js, vous pourriez vouloir commencer par là.

-

Il existe de nombreuses façons d'optimiser les choses pour three.js. Une méthode est souvent appelée -fusion de géométrie. Chaque Mesh que vous créez et que three.js représente est 1 ou -plusieurs requêtes du système pour dessiner quelque chose. Dessiner 2 choses a plus -de surcoût que d'en dessiner 1, même si les résultats sont les mêmes, donc une façon d'optimiser -est de fusionner les maillages (meshes).

-

Voyons un exemple où cela est une bonne solution pour un problème. -Recréons le Globe WebGL.

-

La première chose à faire est d'obtenir des données. Le Globe WebGL a dit que les données -qu'ils utilisent proviennent de SEDAC. En consultant -le site, j'ai vu qu'il y avait des données démographiques au format grille. -J'ai téléchargé les données avec une résolution de 60 minutes. Ensuite, j'ai examiné les données

-

Cela ressemble à ceci

-
 ncols         360
- nrows         145
- xllcorner     -180
- yllcorner     -60
- cellsize      0.99999999999994
- NODATA_value  -9999
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- 9.241768 8.790958 2.095345 -9999 0.05114867 -9999 -9999 -9999 -9999 -999...
- 1.287993 0.4395509 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
-
-

Il y a quelques lignes qui sont comme des paires clé/valeur suivies de lignes avec une valeur -par point de grille, une ligne pour chaque rangée de points de données.

-

Pour nous assurer que nous comprenons les données, essayons de les tracer en 2D.

-

D'abord un peu de code pour charger le fichier texte

-
async function loadFile(url) {
-  const res = await fetch(url);
-  return res.text();
-}
-
-

Le code ci-dessus renvoie une Promise avec le contenu du fichier à l'url ;

-

Ensuite, nous avons besoin de code pour analyser le fichier

-
function parseData(text) {
-  const data = [];
-  const settings = {data};
-  let max;
-  let min;
-  // split into lines
-  text.split('\n').forEach((line) => {
-    // split the line by whitespace
-    const parts = line.trim().split(/\s+/);
-    if (parts.length === 2) {
-      // only 2 parts, must be a key/value pair
-      settings[parts[0]] = parseFloat(parts[1]);
-    } else if (parts.length > 2) {
-      // more than 2 parts, must be data
-      const values = parts.map((v) => {
-        const value = parseFloat(v);
-        if (value === settings.NODATA_value) {
-          return undefined;
-        }
-        max = Math.max(max === undefined ? value : max, value);
-        min = Math.min(min === undefined ? value : min, value);
-        return value;
-      });
-      data.push(values);
-    }
-  });
-  return Object.assign(settings, {min, max});
-}
-
-

Le code ci-dessus renvoie un objet avec toutes les paires clé/valeur du fichier ainsi -qu'une propriété data contenant toutes les données dans un grand tableau et les valeurs min et -max trouvées dans les données.

-

Ensuite, nous avons besoin de code pour dessiner ces données

-
function drawData(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-  const ctx = document.querySelector('canvas').getContext('2d');
-  // make the canvas the same size as the data
-  ctx.canvas.width = ncols;
-  ctx.canvas.height = nrows;
-  // but display it double size so it's not too small
-  ctx.canvas.style.width = px(ncols * 2);
-  ctx.canvas.style.height = px(nrows * 2);
-  // fill the canvas to dark gray
-  ctx.fillStyle = '#444';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-  // draw each data point
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const hue = 1;
-      const saturation = 1;
-      const lightness = amount;
-      ctx.fillStyle = hsl(hue, saturation, lightness);
-      ctx.fillRect(lonNdx, latNdx, 1, 1);
-    });
-  });
-}
-
-function px(v) {
-  return `${v | 0}px`;
-}
-
-function hsl(h, s, l) {
-  return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
-}
-
-

Et enfin, en liant le tout

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(drawData);
-
-

Nous donne ce résultat

-

- -

-

Donc, cela semble fonctionner.

-

Essayons-le en 3D. En partant du code de rendu à la -demande, nous allons créer une boîte par donnée dans -le fichier.

-

Commençons par créer une simple sphère avec une texture du monde. Voici la texture

-
- -

Et le code pour le mettre en place.

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/world.jpg', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

Notez l'appel à render lorsque la texture a fini de charger. Nous en avons besoin -car nous faisons du rendu à la demande au lieu de le faire en -continu, nous devons donc rendre la scène une fois que la texture est chargée.

-

Ensuite, nous devons modifier le code qui dessinait un point par point de donnée ci-dessus pour -créer une boîte par point de donnée à la place.

-
function addBoxes(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  // make one box geometry
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-  // make it so it scales away from the positive Z axis
-  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // these helpers will make it easy to position the boxes
-  // We can rotate the lon helper on its Y axis to the longitude
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // We rotate the latHelper on its X axis to the latitude
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // The position helper moves the object to the edge of the sphere
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const material = new THREE.MeshBasicMaterial();
-      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-      const saturation = 1;
-      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
-      material.color.setHSL(hue, saturation, lightness);
-      const mesh = new THREE.Mesh(geometry, material);
-      scene.add(mesh);
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-      // use the world matrix of the position helper to
-      // position this mesh.
-      positionHelper.updateWorldMatrix(true, false);
-      mesh.applyMatrix4(positionHelper.matrixWorld);
-
-      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    });
-  });
-}
-
-

Le code est principalement direct par rapport à notre code de dessin de test.

-

Nous créons une boîte et ajustons son centre de manière à ce qu'elle s'éloigne de l'axe Z positif. Si nous -ne faisions pas cela, elle s'agrandirait à partir du centre, mais nous voulons qu'elles s'éloignent de l'origine.

-
-
-
-
par défaut
-
-
-
-
ajusté
-
-
- -

Bien sûr, nous pourrions aussi résoudre cela en faisant de la boîte un enfant d'autres objets THREE.Object3D -comme nous l'avons vu dans les graphes de scène, mais plus nous ajoutons de -nœuds à un graphe de scène, plus cela devient lent.

-

Nous avons également mis en place cette petite hiérarchie de nœuds : lonHelper, latHelper, et -positionHelper. Nous utilisons ces objets pour calculer une position autour de la sphère -où placer la boîte.

-
-
-
- -

Ci-dessus, la barre verte représente lonHelper et -est utilisée pour pivoter vers la longitude sur l'équateur. La -barre bleue représente latHelper qui est utilisée pour pivoter vers une -latitude au-dessus ou en dessous de l'équateur. La sphère -rouge représente le décalage que fournit positionHelper.

-

Nous pourrions faire tous les calculs manuellement pour déterminer les positions sur le globe, mais -faire les choses de cette manière laisse la majeure partie des calculs à la librairie elle-même, de sorte que nous -n'avons pas à nous en occuper.

-

Pour chaque point de donnée, nous créons un MeshBasicMaterial et un Mesh et -puis nous demandons la matrice monde du positionHelper et l'appliquons au nouveau Mesh. -Enfin, nous mettons à l'échelle le maillage à sa nouvelle position.

-

Comme ci-dessus, nous aurions pu également créer un latHelper, un lonHelper et un -positionHelper pour chaque nouvelle boîte, mais cela aurait été encore plus lent.

-

Il y a jusqu'à 360x145 boîtes que nous allons créer. Cela représente jusqu'à 52000 boîtes. -Comme certains points de données sont marqués comme "NO_DATA", le nombre réel de boîtes -que nous allons créer est d'environ 19000. Si nous ajoutions 3 objets d'aide supplémentaires par boîte, -cela représenterait près de 80000 nœuds dans le graphe de scène pour lesquels THREE.js devrait -calculer les positions. En utilisant plutôt un seul ensemble d'aides pour positionner -simplement les maillages, nous économisons environ 60000 opérations.

-

Une note sur lonFudge et latFudge. lonFudge est π/2, ce qui correspond à un quart de tour. -Cela a du sens. Cela signifie simplement que la texture ou les coordonnées de texture commencent à un -décalage différent autour du globe. latFudge, d'un autre côté, je n'ai aucune idée -pourquoi il doit être π * -0.135, c'est juste un montant qui a permis aux boîtes de s'aligner -avec la texture.

-

La dernière chose à faire est d'appeler notre chargeur

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
--  .then(drawData)
-+  .then(addBoxes)
-+  .then(render);
-

Une fois que les données ont fini de charger et d'être analysées, nous devons rendre la scène au moins -une fois puisque nous faisons du rendu à la demande.

-

- -

-

Si vous essayez de faire pivoter l'exemple ci-dessus en faisant glisser la souris sur l'échantillon, vous -remarquerez probablement que c'est lent.

-

Nous pouvons vérifier la fréquence d'images en ouvrant les -outils de développement et en activant l'indicateur de fréquence d'images -du navigateur.

-
- -

Sur ma machine, je vois une fréquence d'images inférieure à 20 ips.

-
- -

Cela ne me semble pas très fluide et je suspecte que beaucoup de gens ont des machines -plus lentes, ce qui rendrait la situation encore pire. Nous ferions mieux d'étudier l'optimisation.

-

Pour ce problème particulier, nous pouvons fusionner toutes les boîtes en une seule géométrie. -Nous dessinons actuellement environ 19000 boîtes. En les fusionnant en une seule -géométrie, nous supprimerions 18999 opérations.

-

Voici le nouveau code pour fusionner les boîtes en une seule géométrie.

-
function addBoxes(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-
--  // make one box geometry
--  const boxWidth = 1;
--  const boxHeight = 1;
--  const boxDepth = 1;
--  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
--  // make it so it scales away from the positive Z axis
--  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // these helpers will make it easy to position the boxes
-  // We can rotate the lon helper on its Y axis to the longitude
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // We rotate the latHelper on its X axis to the latitude
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // The position helper moves the object to the edge of the sphere
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-+  // Utilisé pour déplacer le centre de la boîte afin qu'elle s'agrandisse à partir de l'axe Z positif
-+  const originHelper = new THREE.Object3D();
-+  originHelper.position.z = 0.5;
-+  positionHelper.add(originHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-+  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-
--      const material = new THREE.MeshBasicMaterial();
--      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
--      const saturation = 1;
--      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
--      material.color.setHSL(hue, saturation, lightness);
--      const mesh = new THREE.Mesh(geometry, material);
--      scene.add(mesh);
-
-+      const boxWidth = 1;
-+      const boxHeight = 1;
-+      const boxDepth = 1;
-+      const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
--      // use the world matrix of the position helper to
--      // position this mesh.
--      positionHelper.updateWorldMatrix(true, false);
--      mesh.applyMatrix4(positionHelper.matrixWorld);
--
--      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-
-+      // use the world matrix of the origin helper to
-+      // position this geometry
-+      positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-+      originHelper.updateWorldMatrix(true, false);
-+      geometry.applyMatrix4(originHelper.matrixWorld);
-+
-+      geometries.push(geometry);
-    });
-  });
-
-+  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-+      geometries, false);
-+  const material = new THREE.MeshBasicMaterial({color:'red'});
-+  const mesh = new THREE.Mesh(mergedGeometry, material);
-+  scene.add(mesh);
-
-}
-
-

Ci-dessus, nous avons supprimé le code qui modifiait le point central de la géométrie de la boîte -et le faisons à la place en ajoutant un originHelper. Auparavant, nous utilisions la même -géométrie 19000 fois. Cette fois, nous créons une nouvelle géométrie pour chaque boîte et -comme nous allons utiliser applyMatrix pour déplacer les sommets de chaque géométrie de boîte, -autant le faire une fois au lieu de deux.

-

À la fin, nous passons un tableau de toutes les géométries à -BufferGeometryUtils.mergeGeometries, ce qui les combinera toutes -en un seul maillage.

-

Nous devons également inclure le BufferGeometryUtils

-
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
-
-

Et maintenant, du moins sur ma machine, j'obtiens 60 images par seconde

-

- -

-

Cela a donc fonctionné, mais comme il s'agit d'un seul maillage, nous n'obtenons qu'un seul matériau, ce qui -signifie que nous n'avons qu'une seule couleur, alors qu'avant, nous avions une couleur différente sur chaque boîte. Nous pouvons -y remédier en utilisant les couleurs de sommet.

-

Les couleurs de sommet ajoutent une couleur par sommet. En réglant toutes les couleurs de chaque sommet -de chaque boîte sur des couleurs spécifiques, chaque boîte aura une couleur différente.

-
+const color = new THREE.Color();
-
-const lonFudge = Math.PI * .5;
-const latFudge = Math.PI * -0.135;
-const geometries = [];
-data.forEach((row, latNdx) => {
-  row.forEach((value, lonNdx) => {
-    if (value === undefined) {
-      return;
-    }
-    const amount = (value - min) / range;
-
-    const boxWidth = 1;
-    const boxHeight = 1;
-    const boxDepth = 1;
-    const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-    // adjust the helpers to point to the latitude and longitude
-    lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-    latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-    // use the world matrix of the origin helper to
-    // position this geometry
-    positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    originHelper.updateWorldMatrix(true, false);
-    geometry.applyMatrix4(originHelper.matrixWorld);
-
-+    // calculer une couleur
-+    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const saturation = 1;
-+    const lightness = THREE.MathUtils.lerp(0.4, 1.0, amount);
-+    color.setHSL(hue, saturation, lightness);
-+    // obtenir les couleurs sous forme de tableau de valeurs de 0 à 255
-+    const rgb = color.toArray().map(v => v * 255);
-+
-+    // créer un tableau pour stocker les couleurs pour chaque sommet
-+    const numVerts = geometry.getAttribute('position').count;
-+    const itemSize = 3;  // r, g, b
-+    const colors = new Uint8Array(itemSize * numVerts);
-+
-+    // copier la couleur dans le tableau de couleurs pour chaque sommet
-+    colors.forEach((v, ndx) => {
-+      colors[ndx] = rgb[ndx % 3];
-+    });
-+
-+    const normalized = true;
-+    const colorAttrib = new THREE.BufferAttribute(colors, itemSize, normalized);
-+    geometry.setAttribute('color', colorAttrib);
-
-    geometries.push(geometry);
-  });
-});
-
-

Le code ci-dessus recherche le nombre ou les sommets nécessaires en obtenant l'attribut position -de la géométrie. Nous créons ensuite un Uint8Array pour y mettre les couleurs. -Il ajoute ensuite cela comme un attribut en appelant geometry.setAttribute.

-

Enfin, nous devons dire à three.js d'utiliser les couleurs de sommet.

-
const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-    geometries, false);
--const material = new THREE.MeshBasicMaterial({color:'red'});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-+});
-const mesh = new THREE.Mesh(mergedGeometry, material);
-scene.add(mesh);
-
-

Et avec cela, nous retrouvons nos couleurs

-

- -

-

La fusion de géométrie est une technique d'optimisation courante. Par exemple, au lieu de -100 arbres, vous pourriez fusionner les arbres en 1 seule géométrie, un tas de roches individuelles -en une seule géométrie de roches, une clôture de piquets individuels en un seul maillage de clôture. -Un autre exemple dans Minecraft, il ne dessine probablement pas chaque cube individuellement, -mais crée plutôt des groupes de cubes fusionnés et supprime également sélectivement les faces qui ne -sont jamais visibles.

-

Le problème avec le fait de tout transformer en un seul maillage est qu'il n'est plus facile -de déplacer une partie qui était auparavant séparée. Cependant, selon notre cas d'utilisation, -il existe des solutions créatives. Nous en explorerons une dans -un autre article.

-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/picking.html b/manual/fr/picking.html deleted file mode 100644 index eef73d366dc3fc..00000000000000 --- a/manual/fr/picking.html +++ /dev/null @@ -1,395 +0,0 @@ - - - Sélection - - - - - - - - - - - - - -
-
-

Sélection

-
-
-
-

La sélection (picking) désigne le processus qui consiste à déterminer sur quel objet un utilisateur a cliqué ou touché. Il existe de nombreuses façons d'implémenter la sélection, chacune ayant ses avantages et ses inconvénients. Passons en revue les 2 méthodes les plus courantes.

-

La méthode de sélection (picking) probablement la plus courante est le lancé de rayon (raycasting), ce qui signifie lancer un rayon à partir de la souris à travers le frustum (volume de visualisation) de la scène et calculer les objets que ce rayon intersecte. Conceptuellement, c'est très simple.

-

D'abord, nous prendrions la position de la souris. Nous la convertirions en espace monde en appliquant la projection et l'orientation de la caméra. Nous calculerions un rayon allant du plan proche du frustum de la caméra au plan éloigné. Ensuite, pour chaque triangle de chaque objet dans la scène, nous vérifierions si ce rayon intersecte ce triangle. Si votre scène contient 1000 objets et que chaque objet a 1000 triangles, alors 1 million de triangles devront être vérifiés.

-

Quelques optimisations incluraient de vérifier d'abord si le rayon intersecte la sphère englobante (bounding sphere) ou la boîte englobante (bounding box) d'un objet, c'est-à-dire la sphère ou la boîte qui contient l'objet entier. Si le rayon n'intersecte pas l'une d'elles, nous n'avons pas besoin de vérifier les triangles de cet objet.

-

THREE.js fournit une classe RayCaster qui fait exactement cela.

-

Créons une scène avec 100 objets et essayons de les sélectionner. Nous commencerons avec un exemple tiré de l'article sur les pages responsives

-

Quelques changements

-

Nous allons faire de la caméra l'enfant d'un autre objet afin que nous puissions faire tourner cet autre objet et que la caméra se déplace autour de la scène comme un perche à selfie.

-
*const fov = 60;
-const aspect = 2;  // L'aspect par défaut du canvas
-const near = 0.1;
-*const far = 200;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-*camera.position.z = 30;
-
-const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-+// Place la caméra sur un poteau (la rend enfant d'un objet)
-+// afin que nous puissions faire tourner le poteau pour déplacer la caméra autour de la scène
-+const cameraPole = new THREE.Object3D();
-+scene.add(cameraPole);
-+cameraPole.add(camera);
-
-

et dans la fonction render, nous ferons tourner le poteau de la caméra.

-
cameraPole.rotation.y = time * .1;
-
-

Mettons aussi la lumière sur la caméra pour qu'elle bouge avec elle.

-
-scene.add(light);
-+camera.add(light);
-
-

Générons 100 cubes avec des couleurs aléatoires dans des positions, orientations et échelles aléatoires.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return min + (max - min) * Math.random();
-}
-
-function randomColor() {
-  return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`;
-}
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-}
-
-

Et enfin, effectuons la sélection.

-

Créons une classe simple pour gérer la sélection

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // Rétablit la couleur s'il y a un objet sélectionné
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // Lance un rayon à travers le frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // Obtient la liste des objets intersectés par le rayon
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // Sélectionne le premier objet. C'est le plus proche
-      this.pickedObject = intersectedObjects[0].object;
-      // Sauvegarde sa couleur
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // Définit sa couleur émissive sur un rouge/jaune clignotant
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

Vous pouvez voir que nous créons un RayCaster et que nous pouvons ensuite appeler la fonction pick pour lancer un rayon à travers la scène. Si le rayon touche quelque chose, nous changeons la couleur du premier objet qu'il touche.

-

Bien sûr, nous pourrions appeler cette fonction uniquement lorsque l'utilisateur appuie sur le bouton de la souris (mouse down), ce qui est probablement ce que vous voulez généralement, mais pour cet exemple, nous sélectionnerons à chaque image ce qui se trouve sous la souris. Pour ce faire, nous devons d'abord suivre la position de la souris.

-
const pickPosition = {x: 0, y: 0};
-clearPickPosition();
-
-...
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // Note : on inverse Y
-}
-
-function clearPickPosition() {
-  // Contrairement à la souris qui a toujours une position
-  // si l'utilisateur arrête de toucher l'écran, nous voulons
-  // arrêter la sélection. Pour l'instant, nous choisissons simplement une valeur
-  // peu susceptible de sélectionner quelque chose
-  pickPosition.x = -100000;
-  pickPosition.y = -100000;
-}
-
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-

Remarquez que nous enregistrons une position de souris normalisée. Indépendamment de la taille du canvas, nous avons besoin d'une valeur qui va de -1 à gauche à +1 à droite. De même, nous avons besoin d'une valeur qui va de -1 en bas à +1 en haut.

-

Pendant que nous y sommes, prenons également en charge les appareils mobiles.

-
window.addEventListener('touchstart', (event) => {
-  // Empêche le défilement de la fenêtre
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

Et enfin, dans notre fonction render, nous appelons la fonction pick de PickHelper.

-
+const pickHelper = new PickHelper();
-
-function render(time) {
-  time *= 0.001;  // Convertit en secondes ;
-
-  ...
-
-+  pickHelper.pick(pickPosition, scene, camera, time);
-
-  renderer.render(scene, camera);
-
-  ...
-
-

et voici le résultat

-

- -

-

Cela semble fonctionner parfaitement et c'est probablement le cas pour de nombreuses utilisations, mais il y a plusieurs problèmes.

-
    -
  1. C'est basé sur le CPU.

    -

    JavaScript parcourt chaque objet et vérifie si le rayon intersecte la boîte ou la sphère englobante de cet objet. Si c'est le cas, JavaScript doit parcourir chaque triangle de cet objet et vérifier si le rayon intersecte le triangle.

    -

    Le bon côté de cela est que JavaScript peut facilement calculer exactement où le rayon a intersecté le triangle et nous fournir ces données. Par exemple, si vous vouliez placer un marqueur là où l'intersection s'est produite.

    -

    Le mauvais côté est que cela représente beaucoup de travail pour le CPU. Si vous avez des objets avec beaucoup de triangles, cela pourrait être lent.

    -
  2. -
  3. Cela ne gère pas les shaders étranges ou les déplacements.

    -

    Si vous avez un shader qui déforme ou morph le géométrie, JavaScript n'a aucune connaissance de cette déformation et donnera donc la mauvaise réponse. Par exemple, à ma connaissance, vous ne pouvez pas utiliser cette méthode avec des objets skinnés (avec animation par squelette).

    -
  4. -
  5. Cela ne gère pas les trous transparents.

    -
  6. -
-

À titre d'exemple, appliquons cette texture aux cubes.

-
- -

Nous allons juste apporter ces modifications

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load('resources/images/frame.png');
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    +map: texture,
-    +transparent: true,
-    +side: THREE.DoubleSide,
-    +alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  ...
-
-

Et en exécutant cela, vous devriez rapidement voir le problème

-

- -

-

Essayez de sélectionner quelque chose à travers une boîte et vous ne le pouvez pas

-
- -

C'est parce que JavaScript ne peut pas facilement examiner les textures et les matériaux et déterminer si une partie de votre objet est réellement transparente ou non.

-

Une solution à tous ces problèmes est d'utiliser la sélection basée sur le GPU. Malheureusement, bien que conceptuellement simple, elle est plus compliquée à utiliser que la méthode de lancé de rayon ci-dessus.

-

Pour faire de la sélection par GPU, nous rendons chaque objet dans une couleur unique hors écran. Nous consultons ensuite la couleur du pixel correspondant à la position de la souris. La couleur nous indique quel objet a été sélectionné.

-

Cela peut résoudre les problèmes 2 et 3 ci-dessus. Quant au problème 1, la vitesse, cela dépend vraiment. Chaque objet doit être dessiné deux fois. Une fois pour l'affichage normal et encore pour la sélection. Il est possible avec des solutions plus sophistiquées que les deux puissent être faites en même temps, mais nous n'allons pas essayer cela.

-

Une chose que nous pouvons faire, cependant, puisque nous ne lirons qu'un seul pixel, est de configurer la caméra de manière à ce que seul ce pixel soit dessiné. Nous pouvons le faire en utilisant PerspectiveCamera.setViewOffset qui nous permet de dire à THREE.js de calculer une caméra qui rend juste une partie plus petite d'un rectangle plus grand. Cela devrait faire gagner du temps.

-

Pour effectuer ce type de sélection dans THREE.js à l'heure actuelle, il faut créer 2 scènes. L'une que nous remplirons avec nos maillages normaux. L'autre que nous remplirons avec des maillages qui utilisent notre matériau de sélection.

-

Donc, d'abord, créez une deuxième scène et assurez-vous qu'elle se vide en noir.

-
const scene = new THREE.Scene();
-scene.background = new THREE.Color('white');
-const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

Ensuite, pour chaque cube que nous plaçons dans la scène principale, nous créons un "cube de sélection" correspondant à la même position que le cube original, le plaçons dans la pickingScene, et définissons son matériau de manière à dessiner l'identifiant de l'objet comme sa couleur. Nous conservons également une carte des identifiants vers les objets afin que lorsque nous recherchons un identifiant plus tard, nous puissions le mapper à l'objet correspondant.

-
const idToObject = {};
-+const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-+  const id = i + 1;
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    map: texture,
-    transparent: true,
-    side: THREE.DoubleSide,
-    alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-+  idToObject[id] = cube;
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-
-+  const pickingMaterial = new THREE.MeshPhongMaterial({
-+    emissive: new THREE.Color().setHex(id, THREE.NoColorSpace),
-+    color: new THREE.Color(0, 0, 0),
-+    specular: new THREE.Color(0, 0, 0),
-+    map: texture,
-+    transparent: true,
-+    side: THREE.DoubleSide,
-+    alphaTest: 0.5,
-+    blending: THREE.NoBlending,
-+  });
-+  const pickingCube = new THREE.Mesh(geometry, pickingMaterial);
-+  pickingScene.add(pickingCube);
-+  pickingCube.position.copy(cube.position);
-+  pickingCube.rotation.copy(cube.rotation);
-+  pickingCube.scale.copy(cube.scale);
-}
-
-

Notez que nous faisons un usage "abusif" du MeshPhongMaterial ici. En définissant son emissive sur notre identifiant et les attributs color et specular à 0, cela finira par rendre l'identifiant uniquement là où l'alpha de la texture est supérieur à alphaTest. Nous devons également définir blending à NoBlending afin que l'identifiant ne soit pas multiplié par l'alpha.

-

Notez que l'abus du MeshPhongMaterial pourrait ne pas être la meilleure solution car il calculera toujours toutes nos lumières lors du dessin de la scène de sélection, même si nous n'avons pas besoin de ces calculs. Une solution plus optimisée créerait un shader personnalisé qui écrit simplement l'identifiant là où l'alpha de la texture est supérieur à alphaTest.

-

Comme nous sélectionnons à partir de pixels au lieu de lancer des rayons, nous pouvons modifier le code qui définit la position de sélection pour utiliser simplement des pixels.

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // Note : on inverse Y
-+  pickPosition.x = pos.x;
-+  pickPosition.y = pos.y;
-}
-
-

Ensuite, changeons la classe PickHelper en GPUPickHelper. Elle utilisera un WebGLRenderTarget comme nous l'avons vu dans l'article sur les render targets. Notre render target ici ne fait qu'un seul pixel, 1x1.

-
-class PickHelper {
-+class GPUPickHelper {
-  constructor() {
--    this.raycaster = new THREE.Raycaster();
-+    // Crée un render target de 1x1 pixel
-+    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-+    this.pixelBuffer = new Uint8Array(4);
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera, time) {
-+    const {pickingTexture, pixelBuffer} = this;
-
-    // Rétablit la couleur s'il y a un objet sélectionné
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-+    // Définit le décalage de vue pour représenter juste un seul pixel sous la souris
-+    const pixelRatio = renderer.getPixelRatio();
-+    camera.setViewOffset(
-+        renderer.getContext().drawingBufferWidth,   // Largeur totale
-+        renderer.getContext().drawingBufferHeight,  // Hauteur totale
-+        cssPosition.x * pixelRatio | 0,             // rect x
-+        cssPosition.y * pixelRatio | 0,             // rect y
-+        1,                                          // rect largeur
-+        1,                                          // rect hauteur
-+    );
-+    // Rend la scène
-+    renderer.setRenderTarget(pickingTexture)
-+    renderer.render(scene, camera);
-+    renderer.setRenderTarget(null);
-+
-+    // Efface le décalage de vue pour que le rendu redevienne normal
-+    camera.clearViewOffset();
-+    // Lit le pixel
-+    renderer.readRenderTargetPixels(
-+        pickingTexture,
-+        0,   // x
-+        0,   // y
-+        1,   // largeur
-+        1,   // hauteur
-+        pixelBuffer);
-+
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2]      );
-
--    // Lance un rayon à travers le frustum
--    this.raycaster.setFromCamera(normalizedPosition, camera);
--    // Obtient la liste des objets intersectés par le rayon
--    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
--    if (intersectedObjects.length) {
--      // Sélectionne le premier objet. C'est le plus proche
--      this.pickedObject = intersectedObjects[0].object;
-
-+    const intersectedObject = idToObject[id];
-+    if (intersectedObject) {
-+      // Sélectionne le premier objet. C'est le plus proche
-+      this.pickedObject = intersectedObject;
-      // Sauvegarde sa couleur
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // Définit sa couleur émissive sur un rouge/jaune clignotant
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

Et ensuite, nous devons juste l'utiliser

-
-const pickHelper = new PickHelper();
-+const pickHelper = new GPUPickHelper();
-
-

et lui passer la pickScene au lieu de la scene.

-
-  pickHelper.pick(pickPosition, scene, camera, time);
-+  pickHelper.pick(pickPosition, pickScene, camera, time);
-
-

Et maintenant, cela devrait vous permettre de sélectionner à travers les parties transparentes.

-

- -

-

J'espère que cela vous donne une idée de la manière d'implémenter la sélection. Dans un futur article, nous pourrons peut-être aborder la manière de manipuler des objets avec la souris.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/post-processing.html b/manual/fr/post-processing.html deleted file mode 100644 index c422e49e085578..00000000000000 --- a/manual/fr/post-processing.html +++ /dev/null @@ -1,221 +0,0 @@ - - - Post-traitement - - - - - - - - - - - - - -
-
-

Post-traitement

-
-
-
-

Le post-traitement fait généralement référence à l'application d'une sorte d'effet ou de filtre à une image 2D. Dans le cas de THREE.js, nous avons une scène avec un ensemble de maillages. Nous rendons cette scène en une image 2D. Normalement, cette image est rendue directement dans le canvas et affichée dans le navigateur, mais nous pouvons au lieu de cela la rendre sur une cible de rendu (render target) et ensuite appliquer des effets de post-traitement au résultat avant de le dessiner sur le canvas. On appelle cela post-traitement parce que cela se produit après (post) le traitement principal de la scène.

-

Des exemples de post-traitement sont les filtres de type Instagram, les filtres Photoshop, etc...

-

THREE.js propose des classes d'exemple pour aider à mettre en place un pipeline de post-traitement. La manière dont cela fonctionne est de créer un EffectComposer et d'y ajouter plusieurs objets Pass. Ensuite, vous appelez EffectComposer.render et cela rend votre scène sur une cible de rendu puis applique chaque Pass.

-

Chaque Pass peut être un effet de post-traitement comme l'ajout d'une vignette, le flou, l'application d'un effet de lumière (bloom), l'application d'un grain de film, le réglage de la teinte, de la saturation, du contraste, etc... et enfin le rendu du résultat sur le canvas.

-

Il est un peu important de comprendre comment fonctionne EffectComposer. Il crée deux cibles de rendu. Appelons-les rtA et rtB.

-

Ensuite, vous appelez EffectComposer.addPass pour ajouter chaque pass dans l'ordre où vous voulez les appliquer. Les passes sont ensuite appliquées à peu près comme ceci.

-
- -

D'abord, la scène que vous avez passée à RenderPass est rendue sur rtA, puis rtA est passée à la passe suivante, quelle qu'elle soit. Cette passe utilise rtA comme entrée pour faire ce qu'elle a à faire et écrit les résultats sur rtB. rtB est ensuite passé à la passe suivante qui utilise rtB comme entrée et écrit de nouveau sur rtA. Cela continue à travers toutes les passes.

-

Chaque Pass a 4 options de base

-

enabled

-

Indique si cette passe doit être utilisée ou non

-

needsSwap

-

Indique s'il faut échanger rtA et rtB après avoir terminé cette passe

-

clear

-

Indique s'il faut effacer avant de rendre cette passe

-

renderToScreen

-

Indique s'il faut rendre sur le canvas au lieu de la cible de rendu de destination actuelle. Dans la plupart des cas d'utilisation, vous ne définissez pas explicitement ce drapeau car la dernière passe de la chaîne est automatiquement rendue sur l'écran.

-

Mettons en place un exemple de base. Nous allons commencer avec l'exemple de l'article sur la réactivité.

-

Pour cela, nous créons d'abord un EffectComposer.

-
const composer = new EffectComposer(renderer);
-
-

Ensuite, comme première passe, nous ajoutons un RenderPass qui rendra notre scène avec notre caméra dans la première cible de rendu.

-
composer.addPass(new RenderPass(scene, camera));
-
-

Ensuite, nous ajoutons un BloomPass. Un BloomPass rend son entrée sur une cible de rendu généralement plus petite et floute le résultat. Il ajoute ensuite ce résultat flouté par-dessus l'entrée originale. Cela fait fleurir (bloom) la scène.

-
const bloomPass = new BloomPass(
-    1,    // strength
-    25,   // kernel size
-    4,    // sigma ?
-    256,  // blur render target resolution
-);
-composer.addPass(bloomPass);
-
-

Ensuite, nous ajoutons un FilmPass qui dessine du bruit et des lignes de balayage par-dessus son entrée.

-
const filmPass = new FilmPass(
-    0.5,   // intensity
-    false,  // grayscale
-);
-composer.addPass(filmPass);
-
-

Enfin, nous ajoutons un OutputPass qui effectue la conversion de l'espace couleur en sRGB et un mappage tonal (tone mapping) optionnel. Cette passe est généralement la dernière de la chaîne.

-
const outputPass = new OutputPass();
-composer.addPass(outputPass);
-
-

Pour utiliser ces classes, nous devons importer un certain nombre de scripts.

-
import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js';
-import {RenderPass} from 'three/addons/postprocessing/RenderPass.js';
-import {BloomPass} from 'three/addons/postprocessing/BloomPass.js';
-import {FilmPass} from 'three/addons/postprocessing/FilmPass.js';
-import {OutputPass} from 'three/addons/postprocessing/OutputPass.js';
-
-

Pour pratiquement n'importe quel post-traitement, EffectComposer.js, RenderPass.js et OutputPass.js sont requis.

-

Les dernières choses que nous devons faire sont d'utiliser EffectComposer.render au lieu de WebGLRenderer.render et de dire à l'EffectComposer de correspondre à la taille du canvas.

-
-function render(now) {
--  time *= 0.001;
-+let then = 0;
-+function render(now) {
-+  now *= 0.001;  // convertir en secondes
-+  const deltaTime = now - then;
-+  then = now;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-+    composer.setSize(canvas.width, canvas.height);
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
--    const rot = time * speed;
-+    const rot = now * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
--  renderer.render(scene, camera);
-+  composer.render(deltaTime);
-
-  requestAnimationFrame(render);
-}
-
-

EffectComposer.render prend un deltaTime qui est le temps en secondes depuis le rendu de la dernière frame. Il passe cela aux différents effets au cas où certains d'entre eux seraient animés. Dans ce cas, le FilmPass est animé.

-

- -

-

Pour changer les paramètres d'effet à l'exécution, il faut généralement définir des valeurs d'uniformes. Ajoutons une interface graphique (GUI) pour ajuster certains paramètres. Déterminer quelles valeurs vous pouvez facilement ajuster et comment les ajuster nécessite de fouiller dans le code de cet effet.

-

En regardant à l'intérieur de BloomPass.js, j'ai trouvé cette ligne :

-
this.combineUniforms[ 'strength' ].value = strength;
-
-

Nous pouvons donc définir la force (strength) en définissant

-
bloomPass.combineUniforms.strength.value = someValue;
-
-

De même, en regardant dans FilmPass.js, j'ai trouvé ces lignes :

-
this.uniforms.intensity.value = intensity;
-this.uniforms.grayscale.value = grayscale;
-
-

Ce qui indique assez clairement comment les définir.

-

Faisons une petite interface graphique rapide pour définir ces valeurs

-
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

et

-
const gui = new GUI();
-{
-  const folder = gui.addFolder('BloomPass');
-  folder.add(bloomPass.combineUniforms.strength, 'value', 0, 2).name('strength');
-  folder.open();
-}
-{
-  const folder = gui.addFolder('FilmPass');
-  folder.add(filmPass.uniforms.grayscale, 'value').name('grayscale');
-  folder.add(filmPass.uniforms.intensity, 'value', 0, 1).name('intensity');
-  folder.open();
-}
-
-

et maintenant nous pouvons ajuster ces paramètres

-

- -

-

Ce fut une petite étape pour créer notre propre effet.

-

Les effets de post-traitement utilisent des shaders. Les shaders sont écrits dans un langage appelé GLSL (Graphics Library Shading Language). Passer en revue l'intégralité du langage est un sujet beaucoup trop vaste pour ces articles. Quelques ressources pour commencer seraient peut-être cet article et peut-être le Livre des Shaders.

-

Je pense qu'un exemple pour vous aider à démarrer serait utile, alors créons un simple shader de post-traitement GLSL. Nous en créerons un qui nous permette de multiplier l'image par une couleur.

-

Pour le post-traitement, THREE.js fournit un outil utile appelé ShaderPass. Il prend un objet avec des informations définissant un shader de vertex, un shader de fragment, et les entrées par défaut. Il gérera la configuration de la texture à lire pour obtenir les résultats de la passe précédente et l'endroit où rendre, soit sur une des cibles de rendu de l'EffectComposer, soit sur le canvas.

-

Voici un simple shader de post-traitement qui multiplie le résultat de la passe précédente par une couleur.

-
const colorShader = {
-  uniforms: {
-    tDiffuse: { value: null },
-    color:    { value: new THREE.Color(0x88CCFF) },
-  },
-  vertexShader: `
-    varying vec2 vUv;
-    void main() {
-      vUv = uv;
-      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
-    }
-  `,
-  fragmentShader: `
-    varying vec2 vUv;
-    uniform sampler2D tDiffuse;
-    uniform vec3 color;
-    void main() {
-      vec4 previousPassColor = texture2D(tDiffuse, vUv);
-      gl_FragColor = vec4(
-          previousPassColor.rgb * color,
-          previousPassColor.a);
-    }
-  `,
-};
-
-

Ci-dessus, tDiffuse est le nom que ShaderPass utilise pour passer la texture résultat de la passe précédente, donc nous en avons pratiquement toujours besoin. Nous déclarons ensuite color comme une Color de THREE.js.

-

Ensuite, nous avons besoin d'un shader de vertex. Pour le post-traitement, le shader de vertex montré ici est à peu près standard et n'a que rarement besoin d'être modifié. Sans entrer dans trop de détails (voir les articles liés ci-dessus), les variables uv, projectionMatrix, modelViewMatrix et position sont toutes ajoutées comme par magie par THREE.js.

-

Enfin, nous créons un shader de fragment. Dans celui-ci, nous obtenons une couleur de pixel de la passe précédente avec cette ligne

-
vec4 previousPassColor = texture2D(tDiffuse, vUv);
-
-

nous la multiplions par notre couleur et définissons gl_FragColor au résultat

-
gl_FragColor = vec4(
-    previousPassColor.rgb * color,
-    previousPassColor.a);
-
-

Ajoutons une simple interface graphique (GUI) pour définir les 3 valeurs de la couleur

-
const gui = new GUI();
-gui.add(colorPass.uniforms.color.value, 'r', 0, 4).name('red');
-gui.add(colorPass.uniforms.color.value, 'g', 0, 4).name('green');
-gui.add(colorPass.uniforms.color.value, 'b', 0, 4).name('blue');
-
-

Ce qui nous donne un simple effet de post-traitement qui multiplie par une couleur.

-

- -

-

Comme mentionné précédemment, tous les détails sur la manière d'écrire du GLSL et des shaders personnalisés sont trop complexes pour ces articles. Si vous voulez vraiment savoir comment fonctionne WebGL lui-même, consultez ces articles. Une autre excellente ressource est simplement de lire les shaders de post-traitement existants dans le dépôt THREE.js. Certains sont plus compliqués que d'autres, mais si vous commencez par les plus petits, vous pourrez, je l'espère, vous faire une idée de leur fonctionnement.

-

La plupart des effets de post-traitement dans le dépôt THREE.js ne sont malheureusement pas documentés, donc pour les utiliser, vous devrez lire les exemples ou le code des effets eux-mêmes. J'espère que ces simples exemples et l'article sur les cibles de rendu vous fourniront suffisamment de contexte pour commencer.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/prerequisites.html b/manual/fr/prerequisites.html deleted file mode 100644 index 6a8911cdcfaf8e..00000000000000 --- a/manual/fr/prerequisites.html +++ /dev/null @@ -1,332 +0,0 @@ - - - Conditions préalables - - - - - - - - - - - - - -
-
-

Conditions préalables

-
-
-
-

Ces articles sont destinés à vous aider à apprendre à utiliser three.js. -Ils supposent que vous savez programmer en JavaScript. Ils supposent -que vous savez ce qu'est le DOM, comment écrire du code HTML et comment créer des éléments DOM -en JavaScript. Ils supposent que vous savez utiliser -les modules es6 -via import et via les balises <script type="module">. Ils supposent que vous savez utiliser les import maps. -Ils supposent que vous connaissez un peu de CSS et que vous savez ce que -sont les sélecteurs CSS. -Ils supposent également que vous connaissez ES5, ES6 et peut-être un peu ES7. -Ils supposent que vous savez que le navigateur n'exécute du JavaScript que via des événements et des callbacks. -Ils supposent que vous savez ce qu'est une closure.

-

Voici quelques rappels et notes

-

modules es6

-

Les modules es6 peuvent être chargés via le mot-clé import dans un script -ou en ligne via une balise <script type="module">. Voici un exemple

-
-<script type="importmap">
-{
-  "imports": {
-    "three": "./path/to/three.module.js",
-    "three/addons/": "./different/path/to/examples/jsm/"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-...
-
-</script>
-
-

Voir plus de détails au bas de cet article.

-

document.querySelector et document.querySelectorAll

-

Vous pouvez utiliser document.querySelector pour sélectionner le premier élément -qui correspond à un sélecteur CSS. document.querySelectorAll retourne -tous les éléments qui correspondent à un sélecteur CSS.

-

Vous n'avez pas besoin de onload

-

Beaucoup de pages vieilles de 20 ans utilisent du HTML comme ceci

-
<body onload="somefunction()">
-

Ce style est obsolète. Mettez vos scripts -au bas de la page.

-
<html>
-  <head>
-    ...
-  </head>
-  <body>
-     ...
-  </body>
-  <script>
-    // javascript inline
-  </script>
-</html>
-
-

ou utilisez la propriété defer.

-

Savoir comment fonctionnent les closures

-
function a(v) {
-  const foo = v;
-  return function() {
-     return foo;
-  };
-}
-
-const f = a(123);
-const g = a(456);
-console.log(f());  // imprime 123
-console.log(g());  // imprime 456
-
-

Dans le code ci-dessus, la fonction a crée une nouvelle fonction à chaque fois qu'elle est appelée. Cette -fonction englobe la variable foo. Voici plus d'informations.

-

Comprendre comment fonctionne this

-

this n'est pas magique. C'est effectivement une variable qui est automatiquement passée aux fonctions, tout comme -un argument est passé à une fonction. L'explication simple est que lorsque vous appelez une fonction directement -comme ceci

-
somefunction(a, b, c);
-

this sera null (en mode strict ou dans un module), alors que lorsque vous appelez une fonction via l'opérateur point . comme ceci

-
someobject.somefunction(a, b, c);
-

this sera défini sur someobject.

-

Là où les gens se perdent, c'est avec les callbacks.

-
 const callback = someobject.somefunction;
- loader.load(callback);
-

ne fonctionne pas comme une personne inexpérimentée pourrait s'attendre, car lorsque -loader.load appelle le callback, il ne l'appelle pas avec l'opérateur point . -donc par défaut this sera null (sauf si le loader le définit explicitement sur autre chose). -Si vous voulez que this soit someobject lorsque le callback a lieu, vous devez -le dire à JavaScript en le liant à la fonction.

-
 const callback = someobject.somefunction.bind(someobject);
- loader.load(callback);
-

Cet article pourrait aider à expliquer this.

-

Éléments ES5/ES6/ES7

-

var est obsolète. Utilisez const et/ou let

-

Il n'y a aucune raison d'utiliser var JAMAIS et à ce stade, il est considéré comme une mauvaise pratique -de l'utiliser du tout. Utilisez const si la variable ne sera jamais réassignée, ce qui est la plupart du temps. -Utilisez let dans les cas où la valeur change. Cela aidera à éviter des tonnes de bugs.

-

Utilisez for(elem of collection) jamais for(elem in collection)

-

for of est nouveau, for in est ancien. for in avait des problèmes qui sont résolus par for of

-

Par exemple, vous pouvez itérer sur toutes les paires clé/valeur d'un objet avec

-
for (const [key, value] of Object.entries(someObject)) {
-  console.log(key, value);
-}
-
-

Utilisez forEach, map et filter là où c'est utile

-

Les tableaux ont ajouté les fonctions forEach, -map et -filter et -sont assez largement utilisés dans le JavaScript moderne.

-

Utilisez la déstructuration

-

Supposons un objet const dims = {width: 300, height: 150}

-

ancien code

-
const width = dims.width;
-const height = dims.height;
-
-

nouveau code

-
const {width, height} = dims;
-
-

La déstructuration fonctionne aussi avec les tableaux. Supposons un tableau const position = [5, 6, 7, 1];

-

ancien code

-
const y = position[1];
-const z = position[2];
-
-

nouveau code

-
const [, y, z] = position;
-
-

La déstructuration fonctionne également dans les arguments de fonction

-
const dims = {width: 300, height: 150};
-const vector = [3, 4];
-
-function lengthOfVector([x, y]) {
-  return Math.sqrt(x * x + y * y);
-}
-
-const dist = lengthOfVector(vector);  // dist = 5
-
-function area({width, height}) {
-  return width * height;
-}
-const a = area(dims);  // a = 45000
-
-

Utilisez les raccourcis de déclaration d'objet

-

ancien code

-
 const width = 300;
- const height = 150;
- const obj = {
-   width: width,
-   height: height,
-   area: function() {
-     return this.width * this.height
-   },
- };
-
-

nouveau code

-
 const width = 300;
- const height = 150;
- const obj = {
-   width,
-   height,
-   area() {
-     return this.width * this.height;
-   },
- };
-
-

Utilisez le paramètre rest et l'opérateur spread ...

-

Le paramètre rest peut être utilisé pour consommer un nombre quelconque de paramètres. Exemple

-
 function log(className, ...args) {
-   const elem = document.createElement('div');
-   elem.className = className;
-   elem.textContent = args.join(' ');
-   document.body.appendChild(elem);
- }
-
-

L'opérateur spread peut être utilisé pour étendre un itérable en arguments

-
const position = [1, 2, 3];
-someMesh.position.set(...position);
-
-

ou copier un tableau

-
const copiedPositionArray = [...position];
-copiedPositionArray.push(4); // [1,2,3,4]
-console.log(position); // [1,2,3] position n'est pas affectée
-
-

ou pour fusionner des objets

-
const a = {abc: 123};
-const b = {def: 456};
-const c = {...a, ...b};  // c est maintenant {abc: 123, def: 456}
-

Utilisez class

-

La syntaxe pour créer des objets de type classe avant ES5 était peu familière à la plupart -des programmeurs. À partir d'ES5, vous pouvez maintenant utiliser le mot-clé class -qui est plus proche du style C++/C#/Java.

-

Comprendre les getters et setters

-

Les getters et -setters sont -courants dans la plupart des langages modernes. La syntaxe class -d'ES5 les rend beaucoup plus faciles qu'avant ES5.

-

Utilisez les fonctions fléchées (arrow functions) là où c'est approprié

-

C'est particulièrement utile avec les callbacks et les promises.

-
loader.load((texture) => {
-  // utiliser la texture
-});
-
-

Les fonctions fléchées lient this au contexte dans lequel vous créez la fonction fléchée.

-
const foo = (args) => {/* code */};
-
-

est un raccourci pour

-
const foo = (function(args) {/* code */}).bind(this));
-
-

Voir le lien ci-dessus pour plus d'informations sur this.

-

Promises ainsi que async/await

-

Les Promises aident avec le code asynchrone. Async/await aident à -utiliser les promises.

-

C'est un sujet trop vaste pour être abordé ici, mais vous pouvez lire sur -les promises ici -et sur async/await ici.

-

Utilisez les littéraux de gabarit (Template Literals)

-

Les littéraux de gabarit sont des chaînes utilisant des accents graves (backticks) au lieu de guillemets.

-
const foo = `this is a template literal`;
-

Les littéraux de gabarit ont fondamentalement 2 fonctionnalités. La première est qu'ils peuvent être multi-lignes

-
const foo = `this
-is
-a
-template
-literal`;
-const bar = "this\nis\na\ntemplate\nliteral";
-
-

foo et bar ci-dessus sont identiques.

-

L'autre est que vous pouvez sortir du mode chaîne et insérer des fragments de -JavaScript en utilisant ${javascript-expression}. C'est la partie gabarit. Exemple :

-
const r = 192;
-const g = 255;
-const b = 64;
-const rgbCSSColor = `rgb(${r},${g},${b})`;
-
-

ou

-
const color = [192, 255, 64];
-const rgbCSSColor = `rgb(${color.join(',')})`;
-
-

ou

-
const aWidth = 10;
-const bWidth = 20;
-someElement.style.width = `${aWidth + bWidth}px`;
-
-

Apprenez les conventions de codage JavaScript.

-

Bien que vous soyez libre de formater votre code comme bon vous semble, il existe au moins une -convention dont vous devriez être conscient. Les variables, noms de fonctions, noms de méthodes, en -JavaScript sont tous en lowerCasedCamelCase. Les constructeurs, les noms de classes sont -en CapitalizedCamelCase. Si vous suivez cette règle, votre code correspondra à la plupart des autres -codes JavaScript. Beaucoup de linters, des programmes qui vérifient les erreurs évidentes dans votre code, -vous signaleront des erreurs si vous utilisez la mauvaise casse, car en suivant la convention -ci-dessus, ils peuvent savoir quand vous utilisez quelque chose de manière incorrecte.

-
const v = new vector(); // clairement une erreur si toutes les classes commencent par une majuscule
-const v = Vector();     // clairement une erreur si toutes les fonctions commencent par une minuscule.
-
-

Envisagez d'utiliser Visual Studio Code

-

Bien sûr, utilisez l'éditeur que vous voulez, mais si vous ne l'avez pas essayé, envisagez -d'utiliser Visual Studio Code pour JavaScript et -après l'avoir installé, configurez -eslint. -Cela pourrait prendre quelques minutes à configurer, mais cela vous aidera énormément à trouver -les bugs dans votre JavaScript.

-

Quelques exemples

-

Si vous activez la règle no-undef alors -VSCode via ESLint vous avertira de nombreuses variables non définies.

-
- -

Ci-dessus, vous pouvez voir que j'ai mal orthographié doTheThing en doThing. Il y a un trait ondulé rouge -sous doThing et en survolant, il me dit qu'il n'est pas défini. Une erreur -évitée.

-

Si vous utilisez des balises <script> pour inclure three.js, vous recevrez des avertissements en utilisant THREE, alors ajoutez /* global THREE */ en haut de vos -fichiers JavaScript pour dire à eslint que THREE existe. (ou mieux, utilisez import 😉)

-
- -

Ci-dessus, vous pouvez voir qu'eslint connaît la règle selon laquelle les UpperCaseNames sont des constructeurs -et que vous devriez donc utiliser new. Une autre erreur détectée et évitée. C'est la -règle new-cap.

-

Il existe des centaines de règles que vous pouvez activer ou désactiver ou -personnaliser. Par exemple, j'ai mentionné ci-dessus que vous -devriez utiliser const et let plutôt que var.

-

Ici, j'ai utilisé var et il m'a averti que je devrais utiliser let ou const

-
- -

Ici, j'ai utilisé let, mais il a vu que je ne changeais jamais la valeur, alors il a suggéré que j'utilise const.

-
- -

Bien sûr, si vous préférez continuer à utiliser var, vous pouvez simplement désactiver cette règle. -Comme je l'ai dit ci-dessus, je préfère utiliser const et let plutôt que var car ils -fonctionnent mieux et préviennent les bugs.

-

Dans les cas où vous avez vraiment besoin de outrepasser une règle, vous pouvez ajouter des commentaires pour les désactiver -pour une seule ligne ou une section de code.

-

Si vous avez vraiment besoin de prendre en charge les anciens navigateurs, utilisez un transpiler

-

La plupart des navigateurs modernes sont mis à jour automatiquement, donc l'utilisation de toutes ces fonctionnalités vous aidera à -être productif et à éviter les bugs. Cela dit, si vous êtes sur un projet qui doit absolument -prendre en charge les anciens navigateurs, il existe des outils qui prendront votre code ES5/ES6/ES7 -et le transpileront vers du JavaScript pré-ES5.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/primitives.html b/manual/fr/primitives.html deleted file mode 100644 index 3b2cbdb179abe6..00000000000000 --- a/manual/fr/primitives.html +++ /dev/null @@ -1,360 +0,0 @@ - - - Primitives - - - - - - - - - - - - - -
-
-

Primitives

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. -Le premier article traitait des notions fondamentales. -Si vous ne l'avez pas encore lu, vous pourriez vouloir commencer par là.

-

Three.js dispose d'un grand nombre de primitives. Les primitives -sont généralement des formes 3D qui sont générées au moment de l'exécution -avec un ensemble de paramètres.

-

Il est courant d'utiliser des primitives pour des choses comme une sphère -pour un globe ou un ensemble de boîtes pour dessiner un graphique 3D. Il est -particulièrement courant d'utiliser des primitives pour expérimenter -et commencer avec la 3D. Pour la majorité des applications 3D, -il est plus courant qu'un artiste crée des modèles 3D -dans un programme de modélisation 3D comme Blender -ou Maya ou Cinema 4D. Plus tard dans cette série, nous aborderons -la création et le chargement de données à partir de plusieurs programmes de modélisation -3D. Pour l'instant, passons en revue quelques-unes des primitives disponibles.

-

Beaucoup des primitives ci-dessous ont des valeurs par défaut pour tout ou partie de leurs -paramètres, de sorte que vous pouvez les utiliser plus ou moins selon vos besoins.

-
Une Boîte
-
Un cercle plat
-
Un Cône
-
Un Cylindre
-
Un dodécaèdre (12 faces)
-
Une forme 2D extrudée avec biseautage optionnel. -Ici, nous extrudons une forme de cœur. Notez que c'est la base -de TextGeometry.
-
Un icosaèdre (20 faces)
-
Une forme générée en faisant tourner une ligne. Exemples : lampes, quilles de bowling, bougies, chandeliers, verres à vin, verres à boire, etc... Vous fournissez la silhouette 2D comme une série de points, puis vous indiquez à three.js combien de subdivisions créer en faisant tourner la silhouette autour d'un axe.
-
Un Octaèdre (8 faces)
-
Une surface générée en fournissant une fonction qui prend un point 2D d'une grille et renvoie le point 3D correspondant.
-
Un plan 2D
-
Prend un ensemble de triangles centrés autour d'un point et les projette sur une sphère
-
Un disque 2D avec un trou au centre
-
Un contour 2D qui est triangulé
-
Une sphère
-
Un tétraèdre (4 faces)
-
Texte 3D généré à partir d'une police 3D et d'une chaîne de caractères
-
Un tore (beignet)
-
Un nœud torique
-
Un cercle tracé le long d'un chemin
-
Un objet d'aide qui prend une autre géométrie en entrée et génère des arêtes seulement si l'angle entre les faces est supérieur à un certain seuil. Par exemple, si vous regardez la boîte en haut, elle montre une ligne traversant chaque face, montrant chaque triangle qui compose la boîte. En utilisant un EdgesGeometry à la place, les lignes du milieu sont supprimées. Ajustez le seuil `thresholdAngle` ci-dessous et vous verrez les arêtes en dessous de ce seuil disparaître.
-
Génère une géométrie qui contient un segment de ligne (2 points) par arête dans la géométrie donnée. Sans cela, il vous manquerait souvent des arêtes ou vous obtiendriez des arêtes supplémentaires car WebGL nécessite généralement 2 points par segment de ligne. Par exemple, si vous n'aviez qu'un seul triangle, il n'y aurait que 3 points. Si vous essayiez de le dessiner en utilisant un matériau avec wireframe: true, vous n'obtiendriez qu'une seule ligne. Passer cette géométrie de triangle à un WireframeGeometry générera une nouvelle géométrie qui a 3 segments de ligne utilisant 6 points.
- -

Nous aborderons la création de géométries personnalisées dans un autre article. Pour l'instant, -faisons un exemple créant chaque type de primitive. Nous commencerons -avec les exemples de l'article précédent.

-

Près du haut, définissons une couleur de fond

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color(0xAAAAAA);
-
-

Cela indique à three.js d'effacer avec un gris clair.

-

La caméra doit changer de position afin que nous puissions voir tous les -objets.

-
-const fov = 75;
-+const fov = 40;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 1000;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 120;
-
-

Ajoutons une fonction, addObject, qui prend une position x, y et un Object3D et ajoute -l'objet à la scène.

-
const objects = [];
-const spread = 15;
-
-function addObject(x, y, obj) {
-  obj.position.x = x * spread;
-  obj.position.y = y * spread;
-
-  scene.add(obj);
-  objects.push(obj);
-}
-
-

Créons également une fonction pour créer un matériau de couleur aléatoire. -Nous utiliserons une fonctionnalité de Color -qui vous permet de définir une couleur -basée sur la teinte, la saturation et la luminance.

-

hue (teinte) va de 0 à 1 autour de la roue chromatique avec -le rouge à 0, le vert à 0.33 et le bleu à 0.66. saturation -va de 0 à 1, 0 n'ayant pas de couleur et 1 étant -la plus saturée. luminance va de 0 à 1 -avec 0 étant le noir, 1 étant le blanc et 0.5 étant -la quantité maximale de couleur. En d'autres termes, -lorsque la luminance passe de 0.0 à 0.5, la couleur -passe du noir à la hue (teinte). De 0.5 à 1.0, -la couleur passe de la hue (teinte) au blanc.

-
function createMaterial() {
-  const material = new THREE.MeshPhongMaterial({
-    side: THREE.DoubleSide,
-  });
-
-  const hue = Math.random();
-  const saturation = 1;
-  const luminance = .5;
-  material.color.setHSL(hue, saturation, luminance);
-
-  return material;
-}
-
-

Nous avons également passé side: THREE.DoubleSide au matériau. -Cela indique à three de dessiner les deux côtés des triangles -qui composent une forme. Pour une forme solide comme une sphère -ou un cube, il n'y a généralement aucune raison de dessiner les -côtés arrière des triangles car ils font tous face à l'intérieur de la -forme. Dans notre cas cependant, nous dessinons quelques éléments -comme le PlaneGeometry et le ShapeGeometry -qui sont bidimensionnels et n'ont donc pas d'intérieur. Sans -définir side: THREE.DoubleSide, ils disparaîtraient -en regardant leurs côtés arrière.

-

Je dois noter qu'il est plus rapide de dessiner lorsque l'on ne définit pas -side: THREE.DoubleSide, donc idéalement nous ne le définirions que sur -les matériaux qui en ont vraiment besoin, mais dans ce cas, nous -ne dessinons pas trop, donc il n'y a pas beaucoup de raison de -s'en soucier.

-

Créons une fonction, addSolidGeometry, à laquelle -nous passons une géométrie, et elle crée un matériau de couleur aléatoire -via createMaterial et l'ajoute à la scène -via addObject.

-
function addSolidGeometry(x, y, geometry) {
-  const mesh = new THREE.Mesh(geometry, createMaterial());
-  addObject(x, y, mesh);
-}
-
-

Maintenant, nous pouvons l'utiliser pour la majorité des primitives que nous créons. -Par exemple, pour créer une boîte

-
{
-  const width = 8;
-  const height = 8;
-  const depth = 8;
-  addSolidGeometry(-2, -2, new THREE.BoxGeometry(width, height, depth));
-}
-
-

Si vous regardez le code ci-dessous, vous verrez une section similaire pour chaque type de géométrie.

-

Voici le résultat :

-

- -

-

Il y a quelques exceptions notables au modèle ci-dessus. -La plus importante est probablement la TextGeometry. Elle nécessite de charger -les données de police 3D avant de pouvoir générer un maillage pour le texte. -Ces données se chargent de manière asynchrone, nous devons donc attendre qu'elles -soient chargées avant d'essayer de créer la géométrie. En "promisifiant" -le chargement de la police, nous pouvons rendre les choses beaucoup plus faciles. -Nous créons un FontLoader, puis une fonction loadFont qui renvoie -une promesse qui, une fois résolue, nous donnera la police. Nous créons ensuite -une fonction async appelée doit et chargeons la police en utilisant await. -Et enfin, nous créons la géométrie et appelons addObject pour l'ajouter à la scène.

-
{
-  const loader = new FontLoader();
-  // promisify font loading
-  function loadFont(url) {
-    return new Promise((resolve, reject) => {
-      loader.load(url, resolve, undefined, reject);
-    });
-  }
-
-  async function doit() {
-    const font = await loadFont('resources/threejs/fonts/helvetiker_regular.typeface.json');  /* threejs.org : URL */
-    const geometry = new TextGeometry('three.js', {
-      font: font,
-      size: 3.0,
-      depth: .2,
-      curveSegments: 12,
-      bevelEnabled: true,
-      bevelThickness: 0.15,
-      bevelSize: .3,
-      bevelSegments: 5,
-    });
-    const mesh = new THREE.Mesh(geometry, createMaterial());
-    geometry.computeBoundingBox();
-    geometry.boundingBox.getCenter(mesh.position).multiplyScalar(-1);
-
-    const parent = new THREE.Object3D();
-    parent.add(mesh);
-
-    addObject(-1, -1, parent);
-  }
-  doit();
-}
-
-

Il y a une autre différence. Nous voulons faire tourner le texte autour de son -centre, mais par défaut, three.js crée le texte de manière à ce que son centre de rotation -soit sur le bord gauche. Pour contourner ce problème, nous pouvons demander à three.js de calculer la -boîte englobante (bounding box) de la géométrie. Nous pouvons ensuite appeler la méthode getCenter -de la boîte englobante et lui passer l'objet position de notre maillage. -getCenter copie le centre de la boîte dans la position. -Elle renvoie également l'objet position afin que nous puissions appeler multiplyScalar(-1) -pour positionner l'objet entier de sorte que son centre de rotation -soit au centre de l'objet.

-

Si nous appelions simplement addSolidGeometry comme avec les exemples précédents, -cela redéfinirait la position, ce qui n'est pas bon. -Donc, dans ce cas, nous créons un Object3D qui -est le nœud standard pour le graphe de scène de three.js. Mesh -est également hérité de Object3D. Nous aborderons le fonctionnement du graphe de scène -dans un autre article. -Pour l'instant, il suffit de savoir que, -comme les nœuds DOM, les enfants sont dessinés par rapport à leur parent. -En créant un Object3D et en faisant de notre maillage un enfant de celui-ci, -nous pouvons positionner l'Object3D où nous voulons tout en -conservant le décalage central que nous avons défini précédemment.

-

Si nous ne faisions pas cela, le texte tournerait de manière décentrée.

-

- -

-

Notez que celui de gauche ne tourne pas autour de son centre -tandis que celui de droite le fait.

-

Les autres exceptions sont les 2 exemples basés sur des lignes pour EdgesGeometry -et WireframeGeometry. Au lieu d'appeler addSolidGeometry, elles appellent -addLineGeometry qui ressemble à ceci

-
function addLineGeometry(x, y, geometry) {
-  const material = new THREE.LineBasicMaterial({color: 0x000000});
-  const mesh = new THREE.LineSegments(geometry, material);
-  addObject(x, y, mesh);
-}
-
-

Elle crée un LineBasicMaterial noir et crée ensuite un objet LineSegments -qui est un wrapper pour Mesh et aide three à savoir que vous rendez -des segments de ligne (2 points par segment).

-

Chacune des primitives possède plusieurs paramètres que vous pouvez passer lors de sa création -et il est préférable de consulter la documentation pour les voir tous plutôt que -de les répéter ici. Vous pouvez également cliquer sur les liens ci-dessus à côté de chaque forme -pour accéder directement à la documentation de cette forme.

-

Il existe une autre paire de classes qui ne correspondent pas vraiment aux modèles ci-dessus. Ce sont -les classes PointsMaterial et Points. Points est similaire à LineSegments ci-dessus en ce sens qu'elle prend une -BufferGeometry mais dessine des points à chaque sommet au lieu de lignes. -Pour l'utiliser, vous devez également lui passer un PointsMaterial qui -prend un paramètre size pour définir la taille des points.

-
const radius = 7;
-const widthSegments = 12;
-const heightSegments = 8;
-const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-const material = new THREE.PointsMaterial({
-    color: 'red',
-    size: 0.2,     // in world units
-});
-const points = new THREE.Points(geometry, material);
-scene.add(points);
-
-
-
-
- -

Vous pouvez désactiver sizeAttenuation en le définissant à false si vous souhaitez que les points -aient la même taille quelle que soit leur distance par rapport à la caméra.

-
const material = new THREE.PointsMaterial({
-    color: 'red',
-+    sizeAttenuation: false,
-+    size: 3,       // in pixels
--    size: 0.2,     // in world units
-});
-...
-
-
-
-
- -

Une autre chose importante à aborder est que presque toutes les formes -ont divers paramètres pour déterminer combien les subdiviser. Un bon exemple -pourrait être les géométries de sphères. Les sphères prennent des paramètres pour -le nombre de divisions à faire autour et de haut en bas. Par exemple

-
-
-
-
-
- -

La première sphère a 5 segments autour et 3 en hauteur, soit 15 segments -ou 30 triangles. La deuxième sphère a 24 segments sur 10, soit 240 segments -ou 480 triangles. La dernière a 50 sur 50, soit 2500 segments ou 5000 triangles.

-

C'est à vous de décider du nombre de subdivisions dont vous avez besoin. Il peut -sembler que vous ayez besoin d'un grand nombre de segments, mais supprimez les lignes -et l'ombrage plat, et nous obtenons ceci

-
-
-
-
-
- -

Il n'est maintenant plus si clair que celle de droite avec 5000 triangles -soit entièrement meilleure que celle du milieu avec seulement 480.

-

Si vous ne dessinez que quelques sphères, comme par exemple un seul globe pour -une carte de la terre, alors une seule sphère de 10000 triangles n'est pas un mauvais -choix. Si par contre vous essayez de dessiner 1000 sphères, alors -1000 sphères multipliées par 10000 triangles chacune donnent 10 millions de triangles. -Pour animer fluidement, vous avez besoin que le navigateur dessine à 60 images par -seconde, donc vous demanderiez au navigateur de dessiner 600 millions de triangles -par seconde. C'est beaucoup de calcul.

-

Parfois, il est facile de choisir. Par exemple, vous pouvez également choisir -de subdiviser un plan.

-
-
-
-
- -

Le plan de gauche est composé de 2 triangles. Le plan de droite -est composé de 200 triangles. Contrairement à la sphère, il n'y a vraiment aucun compromis sur la qualité pour la plupart -des cas d'utilisation d'un plan. Vous ne subdiviseriez très probablement un plan -que si vous vous attendiez à vouloir le modifier ou le déformer d'une manière ou d'une autre. Une boîte -est similaire.

-

Alors, choisissez ce qui convient le mieux à votre situation. Moins -vous choisissez de subdivisions, plus il est probable que les choses fonctionneront fluidement et moins -elles consommeront de mémoire. Vous devrez décider vous-même quel est le bon -compromis pour votre situation particulière.

-

Si aucune des formes ci-dessus ne correspond à votre cas d'utilisation, vous pouvez charger -une géométrie, par exemple à partir d'un fichier .obj -ou d'un fichier .gltf. -Vous pouvez également créer votre propre BufferGeometry personnalisée.

-

Ensuite, passons en revue le fonctionnement du graphe de scène de three et comment -l'utiliser.

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/rendering-on-demand.html b/manual/fr/rendering-on-demand.html deleted file mode 100644 index 72bfd38777e967..00000000000000 --- a/manual/fr/rendering-on-demand.html +++ /dev/null @@ -1,196 +0,0 @@ - - - Rendu à la demande - - - - - - - - - - - - - -
-
-

Rendu à la demande

-
-
-
-

Le sujet peut sembler évident pour beaucoup, mais au cas où... la plupart des exemples Three.js rendent en continu. En d'autres termes, ils mettent en place une boucle requestAnimationFrame ou "boucle rAF" comme ceci

-
function render() {
-  ...
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

Pour quelque chose qui s'anime, cela a du sens, mais qu'en est-il de quelque chose qui ne s'anime pas ? Dans ce cas, rendre en continu est un gaspillage de la puissance de l'appareil et si l'utilisateur est sur un appareil portable, cela gaspille la batterie de l'utilisateur.

-

La façon la plus évidente de résoudre ce problème est de rendre une fois au début, puis de ne rendre que lorsque quelque chose change. Les changements incluent le chargement final des textures ou des modèles, l'arrivée de données depuis une source externe, l'ajustement d'un paramètre par l'utilisateur, le changement de caméra ou d'autres entrées pertinentes.

-

Prenons un exemple de l'article sur la réactivité et modifions-le pour qu'il rende à la demande.

-

D'abord, nous allons ajouter les OrbitControls afin qu'il y ait quelque chose qui puisse changer et auquel nous puissions réagir en rendant.

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-

et les configurer

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-camera.position.z = 2;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

Puisque nous n'animerons plus les cubes, nous n'avons plus besoin de les suivre

-
-const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
--];
-+makeInstance(geometry, 0x44aa88,  0);
-+makeInstance(geometry, 0x8844aa, -2);
-+makeInstance(geometry, 0xaa8844,  2);
-
-

Nous pouvons supprimer le code d'animation des cubes et les appels à requestAnimationFrame

-
-function render(time) {
--  time *= 0.001;
-+function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
--  cubes.forEach((cube, ndx) => {
--    const speed = 1 + ndx * .1;
--    const rot = time * speed;
--    cube.rotation.x = rot;
--    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
--requestAnimationFrame(render);
-
-

puis nous devons rendre une fois

-
render();
-
-

Nous devons rendre chaque fois que les OrbitControls modifient les paramètres de la caméra. Heureusement, les OrbitControls déclenchent un événement change chaque fois que quelque chose change.

-
controls.addEventListener('change', render);
-
-

Nous devons également gérer le cas où l'utilisateur redimensionne la fenêtre. C'était géré automatiquement auparavant puisque nous rendions en continu, mais maintenant que nous ne le faisons plus, nous devons rendre lorsque la taille de la fenêtre change.

-
window.addEventListener('resize', render);
-
-

Et avec cela, nous obtenons quelque chose qui rend à la demande.

-

- -

-

Les OrbitControls ont des options pour ajouter une sorte d'inertie afin de les rendre moins rigides. Nous pouvons l'activer en définissant la propriété enableDamping sur true.

-
controls.enableDamping = true;
-
-

Avec enableDamping activé, nous devons appeler controls.update dans notre fonction de rendu afin que les OrbitControls puissent continuer à nous fournir de nouveaux paramètres de caméra pendant qu'ils lissent le mouvement. Mais cela signifie que nous ne pouvons pas appeler render directement depuis l'événement change car nous nous retrouverions dans une boucle infinie. Les contrôles nous enverraient un événement change et appelleraient render, render appellerait controls.update. controls.update enverrait un autre événement change.

-

Nous pouvons résoudre cela en utilisant requestAnimationFrame pour appeler render, mais nous devons nous assurer de ne demander une nouvelle image que si une n'a pas déjà été demandée, ce que nous pouvons faire en conservant une variable qui suit si nous avons déjà demandé une image.

-
+let renderRequested = false;
-
-function render() {
-+  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  renderer.render(scene, camera);
-}
-render();
-
-+function requestRenderIfNotRequested() {
-+  if (!renderRequested) {
-+    renderRequested = true;
-+    requestAnimationFrame(render);
-+  }
-+}
-
--controls.addEventListener('change', render);
-+controls.addEventListener('change', requestRenderIfNotRequested);
-
-

Nous devrions probablement aussi utiliser requestRenderIfNotRequested pour le redimensionnement également

-
-window.addEventListener('resize', render);
-+window.addEventListener('resize', requestRenderIfNotRequested);
-
-

Il peut être difficile de voir la différence. Essayez de cliquer sur l'exemple ci-dessous et utilisez les touches fléchées pour vous déplacer ou faites glisser pour faire tourner. Ensuite, essayez de cliquer sur l'exemple ci-dessus et faites la même chose, et vous devriez pouvoir faire la différence. Celui d'en haut s'accroche lorsque vous appuyez sur une touche fléchée ou faites glisser, celui d'en bas glisse.

-

- -

-

Ajoutons également une simple GUI lil-gui et faisons en sorte que ses modifications rendent à la demande.

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

Permettons de définir la couleur et l'échelle x de chaque cube. Pour pouvoir définir la couleur, nous utiliserons le ColorGUIHelper que nous avons créé dans l'article sur les lumières.

-

Tout d'abord, nous devons créer une GUI

-
const gui = new GUI();
-
-

puis pour chaque cube, nous créerons un dossier et ajouterons 2 contrôles, un pour material.color et un autre pour cube.scale.x.

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const folder = gui.addFolder(`Cube${x}`);
-+  folder.addColor(new ColorGUIHelper(material, 'color'), 'value')
-+      .name('color')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.add(cube.scale, 'x', .1, 1.5)
-+      .name('scale x')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.open();
-
-  return cube;
-}
-
-

Vous pouvez voir ci-dessus que les contrôles lil-gui ont une méthode onChange à laquelle vous pouvez passer une fonction de rappel à appeler lorsque la GUI modifie une valeur. Dans notre cas, nous avons juste besoin qu'elle appelle requestRenderIfNotRequested. L'appel à folder.open fait que le dossier s'ouvre dès le départ.

-

- -

-

J'espère que cela vous donne une idée de la façon de faire en sorte que three.js rende à la demande plutôt qu'en continu. Les applications/pages qui rendent three.js à la demande ne sont pas aussi courantes que la plupart des pages utilisant three.js qui sont soit des jeux, soit de l'art animé en 3D, mais des exemples de pages qui pourraient mieux rendre à la demande seraient, par exemple, une visionneuse de carte, un éditeur 3D, un générateur de graphiques 3D, un catalogue de produits, etc...

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/rendertargets.html b/manual/fr/rendertargets.html deleted file mode 100644 index dc8fde818ee9c4..00000000000000 --- a/manual/fr/rendertargets.html +++ /dev/null @@ -1,168 +0,0 @@ - - - Cibles de rendu - - - - - - - - - - - - - -
-
-

Cibles de rendu

-
-
-
-

Une cible de rendu dans three.js est essentiellement une texture sur laquelle vous pouvez effectuer un rendu. -Une fois le rendu effectué, vous pouvez utiliser cette texture comme n'importe quelle autre texture.

-

Faisons un exemple simple. Nous allons commencer par un exemple tiré de l'article sur la responsivité.

-

Rendre sur une cible de rendu est presque exactement la même chose qu'un rendu normal. D'abord, nous créons un WebGLRenderTarget.

-
const rtWidth = 512;
-const rtHeight = 512;
-const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
-
-

Ensuite, nous avons besoin d'une Camera et d'une Scene

-
const rtFov = 75;
-const rtAspect = rtWidth / rtHeight;
-const rtNear = 0.1;
-const rtFar = 5;
-const rtCamera = new THREE.PerspectiveCamera(rtFov, rtAspect, rtNear, rtFar);
-rtCamera.position.z = 2;
-
-const rtScene = new THREE.Scene();
-rtScene.background = new THREE.Color('red');
-
-

Notez que nous avons défini l'aspect sur celui de la cible de rendu, et non sur celui du canvas. -Le bon aspect à utiliser dépend de ce pour quoi nous rendons. Dans ce cas, -nous utiliserons la texture de la cible de rendu sur la face d'un cube. Puisque les faces de -du cube sont carrées, nous voulons un aspect de 1.0.

-

Nous remplissons la scène. Dans ce cas, nous utilisons la lumière et les 3 cubes de l'article précédent.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(-1, 2, 4);
-*  rtScene.add(light);
-}
-
-const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-*  rtScene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-*const rtCubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

La Scene et la Camera de l'article précédent sont toujours là. Nous les utiliserons pour rendre sur le canvas. -Il nous suffit d'ajouter des éléments à rendre.

-

Ajoutons un cube qui utilise la texture de la cible de rendu.

-
const material = new THREE.MeshPhongMaterial({
-  map: renderTarget.texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-
-

Maintenant, au moment du rendu, nous rendons d'abord la scène de la cible de rendu sur la cible de rendu.

-
function render(time) {
-  time *= 0.001;
-
-  ...
-
-  // faire tourner tous les cubes dans la scène de la cible de rendu
-  rtCubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  // dessiner la scène de la cible de rendu sur la cible de rendu
-  renderer.setRenderTarget(renderTarget);
-  renderer.render(rtScene, rtCamera);
-  renderer.setRenderTarget(null);
-
-

Ensuite, nous rendons la scène avec le cube unique qui utilise la texture de la cible de rendu sur le canvas.

-
  // faire tourner le cube dans la scène
-  cube.rotation.x = time;
-  cube.rotation.y = time * 1.1;
-
-  // rendre la scène sur le canvas
-  renderer.render(scene, camera);
-
-

And voilà

-

- -

-

Le cube est rouge car nous avons défini le background de la rtScene sur rouge, de sorte que la -texture de la cible de rendu est effacée en rouge.

-

Les cibles de rendu sont utilisées pour toutes sortes de choses. Les ombres utilisent des cibles de rendu. -La sélection (picking) peut utiliser une cible de rendu. Divers types d'effets de post-traitement -nécessitent des cibles de rendu. Rendre un rétroviseur dans une voiture ou une vue en direct sur un moniteur à l'intérieur d'une scène 3D -pourrait utiliser une cible de rendu.

-

Quelques notes sur l'utilisation de WebGLRenderTarget.

-
    -
  • Par défaut, WebGLRenderTarget crée 2 textures. Une texture de couleur et une texture de profondeur/stencil. Si vous n'avez pas besoin des textures de profondeur ou de stencil, vous pouvez demander à ne pas les créer en passant des options. Exemple :

    -
      const rt = new THREE.WebGLRenderTarget(width, height, {
    -    depthBuffer: false,
    -    stencilBuffer: false,
    -  });
    -
    -
  • -
  • Vous pourriez avoir besoin de changer la taille d'une cible de rendu

    -

    Dans l'exemple ci-dessus, nous créons une cible de rendu de taille fixe, 512x512. Pour des choses comme le post-traitement, vous devez généralement créer une cible de rendu de la même taille que votre canvas. Dans notre code, cela signifierait que lorsque nous changeons la taille du canvas, nous mettons également à jour la taille de la cible de rendu et la caméra que nous utilisons lors du rendu sur la cible de rendu. Exemple :

    -
    function render(time) {
    -  time *= 0.001;
    -
    -  if (resizeRendererToDisplaySize(renderer)) {
    -    const canvas = renderer.domElement;
    -    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    -    camera.updateProjectionMatrix();
    -
    -+    renderTarget.setSize(canvas.width, canvas.height);
    -+    rtCamera.aspect = camera.aspect;
    -+    rtCamera.updateProjectionMatrix();
    -}
    -
  • -
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/responsive.html b/manual/fr/responsive.html deleted file mode 100644 index 1d76fee24e8432..00000000000000 --- a/manual/fr/responsive.html +++ /dev/null @@ -1,260 +0,0 @@ - - - Conception Réactive - - - - - - - - - - - - - -
-
-

Conception Réactive

-
-
-
-

Ceci est le deuxième article d'une série d'articles sur three.js. -Le premier article traitait des fondamentaux. -Si vous ne l'avez pas encore lu, vous voudrez peut-être commencer par là.

-

Cet article explique comment rendre votre application three.js réactive à toute situation. Rendre une page web réactive fait généralement référence à la capacité de la page à s'afficher correctement sur des écrans de différentes tailles, des ordinateurs de bureau aux tablettes et téléphones.

-

Pour three.js, il y a encore plus de situations à considérer. Par exemple, un éditeur 3D avec des contrôles à gauche, à droite, en haut ou en bas est quelque chose que nous pourrions vouloir gérer. Un diagramme interactif au milieu d'un document est un autre exemple.

-

Le dernier exemple que nous avions utilisait un simple canevas sans CSS et sans taille

-
<canvas id="c"></canvas>
-
-

Ce canevas a par défaut une taille de 300x150 pixels CSS.

-

Dans la plateforme web, la méthode recommandée pour définir la taille d'un élément est d'utiliser CSS.

-

Faisons en sorte que le canevas remplisse la page en ajoutant du CSS

-
<style>
-html, body {
-   margin: 0;
-   height: 100%;
-}
-#c {
-   width: 100%;
-   height: 100%;
-   display: block;
-}
-</style>
-
-

En HTML, le corps (body) a une marge de 5 pixels par défaut, donc définir la marge à 0 supprime cette marge. Définir la hauteur de html et body à 100 % leur permet de remplir la fenêtre. Sinon, ils ne sont que de la taille du contenu qui les remplit.

-

Ensuite, nous disons à l'élément id=c de prendre -100 % de la taille de son conteneur, qui est ici le corps du -document.

-

Enfin, nous définissons son mode display à block. Le mode d'affichage par défaut d'un canevas est inline. Les éléments inline -peuvent finir par ajouter des espaces blancs à l'affichage. En -définissant le canevas à block, ce problème disparaît.

-

Voici le résultat

-

- -

-

Vous pouvez voir que le canevas remplit maintenant la page, mais il y a 2 -problèmes. Premièrement, nos cubes sont étirés. Ce ne sont pas des cubes, -mais plutôt des boîtes. Trop hauts ou trop larges. Ouvrez l'exemple -dans sa propre fenêtre et redimensionnez-le. Vous verrez comment -les cubes s'étirent en largeur et en hauteur.

-

-

Le deuxième problème est qu'ils semblent avoir une faible résolution ou être pixellisés et -flous. Élargissez beaucoup la fenêtre et vous verrez vraiment -le problème.

-

-

Résolvons d'abord le problème de l'étirement. Pour ce faire, nous devons -définir l'aspect de la caméra sur l'aspect de la taille d'affichage du canevas. -Nous pouvons le faire en examinant les propriétés clientWidth -et clientHeight du canevas.

-

Nous allons mettre à jour notre boucle de rendu comme ceci

-
function render(time) {
-  time *= 0.001;
-
-+  const canvas = renderer.domElement;
-+  camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+  camera.updateProjectionMatrix();
-
-  ...
-
-

Maintenant, les cubes ne devraient plus être déformés.

-

- -

-

Ouvrez l'exemple dans une fenêtre séparée et redimensionnez la fenêtre. -Vous devriez voir que les cubes ne sont plus étirés en hauteur ou en largeur. -Ils conservent le bon aspect quelle que soit la taille de la fenêtre.

-

-

Maintenant, résolvons le problème de la pixellisation.

-

Les éléments Canvas ont 2 tailles. Une taille est la taille à laquelle le canevas est affiché -sur la page. C'est ce que nous définissons avec CSS. L'autre taille est le -nombre de pixels dans le canevas lui-même. Ce n'est pas différent d'une image. -Par exemple, nous pourrions avoir une image de 128x64 pixels et -l'afficher en 400x200 pixels en utilisant CSS.

-
<img src="some128x64image.jpg" style="width:400px; height:200px">
-
-

La taille interne d'un canevas, sa résolution, est souvent appelée sa taille de drawingbuffer. -Dans three.js, nous pouvons définir la taille du drawingbuffer du canevas en appelant renderer.setSize. -Quelle taille devrions-nous choisir ? La réponse la plus évidente est « la même taille que celle affichée par le canevas ». -Encore une fois, pour ce faire, nous pouvons examiner les propriétés clientWidth et clientHeight -du canevas.

-

Écrivons une fonction qui vérifie si le canevas du renderer n'a pas -déjà la taille à laquelle il est affiché et, si ce n'est pas le cas, définit sa taille.

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
-  const width = canvas.clientWidth;
-  const height = canvas.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

Notez que nous vérifions si le canevas a réellement besoin d'être redimensionné. Le redimensionnement du canevas -est une partie intéressante de la spécification du canevas, et il est préférable de ne pas définir la même -taille si elle est déjà celle que nous souhaitons.

-

Une fois que nous savons si nous devons redimensionner ou non, nous appelons alors renderer.setSize et -passons la nouvelle largeur et hauteur. Il est important de passer false à la fin. -renderer.setSize définit par défaut la taille CSS du canevas, mais ce n'est pas -ce que nous voulons. Nous voulons que le navigateur continue à fonctionner comme il le fait pour tous les autres -éléments, c'est-à-dire en utilisant CSS pour déterminer la taille d'affichage de l'élément. Nous ne -voulons pas que les canevas utilisés par three soient différents des autres éléments.

-

Notez que notre fonction retourne true si le canevas a été redimensionné. -Nous pouvons l'utiliser pour vérifier s'il y a d'autres éléments que nous devrions mettre à jour. Modifions -notre boucle de rendu pour utiliser la nouvelle fonction

-
function render(time) {
-  time *= 0.001;
-
-+  if (resizeRendererToDisplaySize(renderer)) {
-+    const canvas = renderer.domElement;
-+    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.updateProjectionMatrix();
-+  }
-
-  ...
-
-

Comme l'aspect ne changera que si la taille d'affichage du canevas a changé, -nous ne définissons l'aspect de la caméra que si resizeRendererToDisplaySize -retourne true.

-

- -

-

Il devrait maintenant rendre avec une résolution qui correspond à la taille d'affichage -du canevas.

-

Pour illustrer le fait de laisser CSS gérer le redimensionnement, prenons -notre code et mettons-le dans un fichier .js séparé. -Voici ensuite quelques exemples supplémentaires où nous laissons CSS choisir la taille, et notez -que nous n'avons eu à modifier aucun code pour qu'ils fonctionnent.

-

Mettons nos cubes au milieu d'un paragraphe de texte.

-

- -

-

et voici notre même code utilisé dans une disposition de style éditeur -où la zone de contrôle à droite peut être redimensionnée.

-

- -

-

Le point important à noter est qu'aucun code n'a été modifié. Seuls notre HTML et notre CSS -ont changé.

-

Gestion des écrans HD-DPI

-

HD-DPI signifie écrans à haute densité de points par pouce (high-density dot per inch displays). -C'est le cas de la plupart des Macs actuels et de nombreuses machines Windows, -ainsi que de la quasi-totalité des smartphones.

-

La façon dont cela fonctionne dans le navigateur est qu'ils utilisent -des pixels CSS pour définir les tailles, qui sont censées être les mêmes -quelle que soit la résolution de l'écran. Le navigateur -se contentera de rendre le texte avec plus de détails, mais avec la même -taille physique.

-

Il existe différentes façons de gérer les écrans HD-DPI avec three.js.

-

La première consiste simplement à ne rien faire de spécial. C'est sans doute -la méthode la plus courante. Le rendu graphique 3D nécessite beaucoup de -puissance de traitement GPU. Les GPU mobiles ont moins de puissance que les ordinateurs de bureau, -du moins en 2018, et pourtant les téléphones portables ont souvent des écrans à très -haute résolution. Les téléphones haut de gamme actuels ont un rapport HD-DPI -de 3x, ce qui signifie que pour chaque pixel d'un écran non HD-DPI, -ces téléphones ont 9 pixels. Cela signifie qu'ils doivent effectuer 9 fois -le rendu.

-

Calculer 9 fois les pixels représente beaucoup de travail, donc si nous -laissons le code tel quel, nous calculerons 1x les pixels et le -navigateur se contentera de l'afficher à 3x la taille (3x par 3x = 9x pixels).

-

Pour toute application three.js lourde, c'est probablement ce que vous voudrez, -sinon vous risquez d'avoir une fréquence d'images lente.

-

Cela dit, si vous souhaitez réellement rendre à la résolution -de l'appareil, il existe plusieurs façons de le faire dans three.js.

-

L'une consiste à indiquer à three.js un multiplicateur de résolution en utilisant renderer.setPixelRatio. -Vous demandez au navigateur quel est le multiplicateur entre les pixels CSS et les pixels de l'appareil, -et vous le passez à three.js

-
 renderer.setPixelRatio(window.devicePixelRatio);
-

Après cela, tout appel à renderer.setSize utilisera magiquement -la taille demandée multipliée par le rapport de pixels -que vous avez passé. Ceci est fortement DÉCONSEILLÉ. Voir ci-dessous

-

L'autre méthode consiste à le faire vous-même lorsque vous redimensionnez le canevas.

-
    function resizeRendererToDisplaySize(renderer) {
-      const canvas = renderer.domElement;
-      const pixelRatio = window.devicePixelRatio;
-      const width  = Math.floor( canvas.clientWidth  * pixelRatio );
-      const height = Math.floor( canvas.clientHeight * pixelRatio );
-      const needResize = canvas.width !== width || canvas.height !== height;
-      if (needResize) {
-        renderer.setSize(width, height, false);
-      }
-      return needResize;
-    }
-
-

Cette seconde méthode est objectivement meilleure. Pourquoi ? Parce que cela signifie que j'obtiens ce que je demande. -Il existe de nombreux cas lors de l'utilisation de three.js où nous devons connaître la taille réelle -du drawingBuffer du canevas. Par exemple, lors de la création d'un filtre de post-traitement, -ou si nous créons un shader qui accède à gl_FragCoord, si nous faisons -une capture d'écran, ou lisons des pixels pour la sélection GPU, pour dessiner dans un canevas 2D, -etc... Il existe de nombreux cas où si nous utilisons setPixelRatio, notre taille réelle sera différente -de la taille demandée, et nous devrons deviner quand utiliser la taille -que nous avons demandée et quand utiliser la taille que three.js utilise réellement. -En le faisant nous-mêmes, nous savons toujours que la taille utilisée est la taille que nous avons demandée. -Il n'y a pas de cas particulier où de la magie opère en coulisses.

-

Voici un exemple utilisant le code ci-dessus.

-

- -

-

Il peut être difficile de voir la différence, mais si vous avez un écran HD-DPI -et que vous comparez cet exemple à ceux ci-dessus, vous devriez -remarquer que les bords sont plus nets.

-

Cet article a couvert un sujet très basique mais fondamental. -Ensuite, passons rapidement en revue les primitives de base que three.js fournit.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/scenegraph.html b/manual/fr/scenegraph.html deleted file mode 100644 index 3f169c54201ebb..00000000000000 --- a/manual/fr/scenegraph.html +++ /dev/null @@ -1,475 +0,0 @@ - - - Graphe de scène - - - - - - - - - - - - - -
-
-

Graphe de scène

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le -premier article est les bases de three.js. Si -vous ne l'avez pas encore lu, vous pourriez envisager de commencer par là.

-

Le cœur de Three.js est sans doute son graphe de scène. Un graphe de scène dans un moteur 3D -est une hiérarchie de nœuds dans un graphe où chaque nœud représente -un espace local.

-

-

C'est un peu abstrait, alors essayons de donner quelques exemples.

-

Un exemple pourrait être le système solaire : soleil, terre, lune.

-

-

La Terre tourne autour du Soleil. La Lune tourne autour de la Terre. La Lune -se déplace en cercle autour de la Terre. Du point de -vue de la Lune, elle tourne dans l'« espace local » de la Terre. Même si -son mouvement par rapport au Soleil est une courbe folle ressemblant à un spirographe, du point de vue de la Lune, elle n'a qu'à se soucier de tourner -autour de l'espace local de la Terre.

-

- -
- -

-

Pour le voir autrement, vous qui vivez sur Terre n'avez pas à penser -à la rotation de la Terre sur son axe ni à sa rotation autour du -Soleil. Vous marchez, conduisez, nagez ou courez comme si la Terre -ne bougeait ni ne tournait pas du tout. Vous marchez, conduisez, nagez, courez et vivez -dans l'« espace local » de la Terre, même si, par rapport au Soleil, vous tournez -autour de la Terre à environ 1600 kilomètres par heure et autour -du Soleil à environ 108 000 kilomètres par heure. Votre position dans le système solaire -est similaire à celle de la Lune ci-dessus, mais vous n'avez pas à vous en soucier. -Vous vous préoccupez simplement de votre position par rapport à la Terre dans son -« espace local ».

-

Prenons les choses étape par étape. Imaginez que nous voulions faire -un diagramme du soleil, de la terre et de la lune. Nous commencerons par le soleil en -créant simplement une sphère et en la plaçant à l'origine. Remarque : Nous utilisons -le soleil, la terre, la lune pour illustrer comment utiliser un graphe de scène. Bien sûr, -le vrai soleil, la terre et la lune utilisent la physique, mais pour nos besoins, nous allons -simuler cela avec un graphe de scène.

-
// un tableau d'objets dont la rotation doit être mise à jour
-const objects = [];
-
-// utiliser une seule sphère pour tout
-const radius = 1;
-const widthSegments = 6;
-const heightSegments = 6;
-const sphereGeometry = new THREE.SphereGeometry(
-    radius, widthSegments, heightSegments);
-
-const sunMaterial = new THREE.MeshPhongMaterial({emissive: 0xFFFF00});
-const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
-sunMesh.scale.set(5, 5, 5);  // agrandir le soleil
-scene.add(sunMesh);
-objects.push(sunMesh);
-
-

Nous utilisons une sphère avec très peu de polygones. Seulement 6 subdivisions autour de son équateur. -C'est pour qu'il soit facile de voir la rotation.

-

Nous allons réutiliser la même sphère pour tout, nous allons donc définir une échelle -de 5x pour le maillage du soleil.

-

Nous définissons également la propriété emissive du matériau phong en jaune. La propriété emissive d'un matériau phong est essentiellement la couleur qui sera dessinée sans lumière frappant -la surface. La lumière est ajoutée à cette couleur.

-

Plaçons également une seule lumière ponctuelle au centre de la scène. Nous reviendrons plus tard sur -les détails des lumières ponctuelles, mais pour l'instant, la version simple est qu'une lumière ponctuelle -représente la lumière qui émane d'un point unique.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 500;
-  const light = new THREE.PointLight(color, intensity);
-  scene.add(light);
-}
-
-

Pour faciliter la visualisation, nous allons placer la caméra juste au-dessus de l'origine, -regardant vers le bas. La façon la plus simple de faire cela est d'utiliser la fonction lookAt. La fonction lookAt -orientera la caméra depuis sa position pour « regarder » la position -que nous lui passons. Cependant, avant de faire cela, nous devons indiquer à la caméra -dans quelle direction se trouve le haut de la caméra, ou plutôt quelle direction est le « haut » pour la -caméra. Dans la plupart des situations, Y positif vers le haut est suffisant, mais puisque -nous regardons directement vers le bas, nous devons indiquer à la caméra que Z positif est vers le haut.

-
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-camera.position.set(0, 50, 0);
-camera.up.set(0, 0, 1);
-camera.lookAt(0, 0, 0);
-
-

Dans la boucle de rendu, adaptée des exemples précédents, nous faisons pivoter tous -les objets de notre tableau objects avec ce code.

-
objects.forEach((obj) => {
-  obj.rotation.y = time;
-});
-
-

Comme nous avons ajouté le sunMesh au tableau objects, il va tourner.

-

- -

-

Maintenant, ajoutons la Terre.

-
const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
-earthMesh.position.x = 10;
-scene.add(earthMesh);
-objects.push(earthMesh);
-
-

Nous créons un matériau bleu, mais nous lui donnons une petite quantité de bleu émissif -afin qu'il ressorte sur notre fond noir.

-

Nous utilisons la même sphereGeometry avec notre nouveau earthMaterial bleu pour créer -un earthMesh. Nous le positionnons à 10 unités à gauche du soleil -et l'ajoutons à la scène. Comme nous l'avons ajouté à notre tableau objects, il tournera aussi.

-

- -

-

Vous pouvez voir que le soleil et la terre tournent, mais la terre ne -tourne pas autour du soleil. Faisons de la terre un enfant du soleil

-
-scene.add(earthMesh);
-+sunMesh.add(earthMesh);
-
-

et...

-

- -

-

Que s'est-il passé ? Pourquoi la Terre a-t-elle la même taille que le Soleil et pourquoi est-elle si loin ? -J'ai en fait dû déplacer la caméra de 50 unités au-dessus à 150 unités au-dessus pour voir la Terre.

-

Nous avons fait du earthMesh un enfant du sunMesh. L'échelle du sunMesh est -réglée à 5x avec sunMesh.scale.set(5, 5, 5). Cela signifie que -l'espace local du sunMesh est 5 fois plus grand. Tout ce qui est placé dans cet espace -sera multiplié par 5. Cela signifie que la terre est maintenant 5 fois plus grande et -que sa distance par rapport au soleil (earthMesh.position.x = 10) est également -multipliée par 5.

-

Notre graphe de scène ressemble actuellement à ceci

-

-

Pour corriger cela, ajoutons un nœud de graphe de scène vide. Nous allons rendre le soleil et la terre -enfants de ce nœud.

-
+const solarSystem = new THREE.Object3D();
-+scene.add(solarSystem);
-+objects.push(solarSystem);
-
-const sunMaterial = new THREE.MeshPhongMaterial({emissive: 0xFFFF00});
-const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
-sunMesh.scale.set(5, 5, 5);
--scene.add(sunMesh);
-+solarSystem.add(sunMesh);
-objects.push(sunMesh);
-
-const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
-earthMesh.position.x = 10;
--sunMesh.add(earthMesh);
-+solarSystem.add(earthMesh);
-objects.push(earthMesh);
-
-

Ici, nous avons créé un Object3D. Comme un Mesh, c'est aussi un nœud dans le graphe de scène, -mais contrairement à un Mesh, il n'a ni matériau ni géométrie. Il représente simplement un espace local.

-

Notre nouveau graphe de scène ressemble à ceci

-

-

Le sunMesh et le earthMesh sont tous deux enfants du solarSystem. Les 3 -tournent et maintenant, parce que le earthMesh n'est pas un enfant du sunMesh, -il n'est plus mis à l'échelle par 5x.

-

- -

-

Bien mieux. La Terre est plus petite que le soleil et elle tourne autour du soleil -tout en tournant sur elle-même.

-

En continuant sur ce même schéma, ajoutons une lune.

-
+const earthOrbit = new THREE.Object3D();
-+earthOrbit.position.x = 10;
-+solarSystem.add(earthOrbit);
-+objects.push(earthOrbit);
-
-const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
--earthMesh.position.x = 10; // notez que ce décalage est déjà défini dans l'objet THREE.Object3D parent "earthOrbit"
--solarSystem.add(earthMesh);
-+earthOrbit.add(earthMesh);
-objects.push(earthMesh);
-
-+const moonOrbit = new THREE.Object3D();
-+moonOrbit.position.x = 2;
-+earthOrbit.add(moonOrbit);
-
-+const moonMaterial = new THREE.MeshPhongMaterial({color: 0x888888, emissive: 0x222222});
-+const moonMesh = new THREE.Mesh(sphereGeometry, moonMaterial);
-+moonMesh.scale.set(.5, .5, .5);
-+moonOrbit.add(moonMesh);
-+objects.push(moonMesh);
-
-

Encore une fois, nous avons ajouté d'autres nœuds de graphe de scène invisibles. Le premier, un Object3D appelé earthOrbit -et auquel nous avons ajouté le earthMesh et le moonOrbit, également nouveau. Nous avons ensuite ajouté le moonMesh -au moonOrbit. Le nouveau graphe de scène ressemble à ceci.

-

-

et voici le résultat

-

- -

-

Vous pouvez voir que la lune suit le motif spirographe montré en haut -de cet article, mais nous n'avons pas eu à le calculer manuellement. Nous avons simplement -configuré notre graphe de scène pour qu'il le fasse pour nous.

-

Il est souvent utile de dessiner quelque chose pour visualiser les nœuds dans le graphe de scène. -Three.js dispose de quelques ummmm, helpers utiles pour ummm, ... aider à cela.

-

L'un s'appelle AxesHelper. Il dessine 3 lignes représentant les axes -locaux X, -Y et -Z. Ajoutons-en un à chaque nœud que nous -avons créé.

-
// ajouter un AxesHelper à chaque nœud
-objects.forEach((node) => {
-  const axes = new THREE.AxesHelper();
-  axes.material.depthTest = false;
-  axes.renderOrder = 1;
-  node.add(axes);
-});
-
-

Dans notre cas, nous voulons que les axes apparaissent même s'ils sont à l'intérieur des sphères. -Pour ce faire, nous réglons la propriété depthTest de leur matériau sur false, ce qui signifie qu'ils ne -vérifieront pas s'ils dessinent derrière quelque chose d'autre. Nous réglons également -leur renderOrder à 1 (la valeur par défaut est 0) afin qu'ils soient dessinés après -toutes les sphères. Sinon, une sphère pourrait dessiner par-dessus et les masquer.

-

- -

-

Nous pouvons voir les axes -x (rouge) et -z (bleu). Comme nous regardons -directement vers le bas et que chacun de nos objets ne tourne que autour de son -axe y, nous ne voyons pas beaucoup les axes y (vert).

-

Il peut être difficile d'en voir certains car il y a 2 paires d'axes qui se chevauchent. Le sunMesh -et le solarSystem sont tous deux à la même position. De même, le earthMesh et -le earthOrbit sont à la même position. Ajoutons quelques contrôles simples pour nous permettre -de les activer/désactiver pour chaque nœud. -Tant qu'on y est, ajoutons également un autre helper appelé GridHelper. Il -crée une grille 2D sur le plan XZ. Par défaut, la grille est de 10x10 unités.

-

Nous allons également utiliser lil-gui, une bibliothèque d'interface utilisateur -très populaire dans les projets three.js. lil-gui prend un -objet et le nom d'une propriété sur cet objet et, en fonction du type de la propriété, -crée automatiquement une interface utilisateur pour manipuler cette propriété.

-

Nous voulons créer à la fois un GridHelper et un AxesHelper pour chaque nœud. Nous avons besoin -d'une étiquette pour chaque nœud, nous allons donc nous débarrasser de l'ancienne boucle et passer à l'appel -d'une fonction pour ajouter les helpers pour chaque nœud

-
-// ajouter un AxesHelper à chaque nœud
--objects.forEach((node) => {
--  const axes = new THREE.AxesHelper();
--  axes.material.depthTest = false;
--  axes.renderOrder = 1;
--  node.add(axes);
--});
-
-+function makeAxisGrid(node, label, units) {
-+  const helper = new AxisGridHelper(node, units);
-+  gui.add(helper, 'visible').name(label);
-+}
-+
-+makeAxisGrid(solarSystem, 'solarSystem', 25);
-+makeAxisGrid(sunMesh, 'sunMesh');
-+makeAxisGrid(earthOrbit, 'earthOrbit');
-+makeAxisGrid(earthMesh, 'earthMesh');
-+makeAxisGrid(moonOrbit, 'moonOrbit');
-+makeAxisGrid(moonMesh, 'moonMesh');
-
-

makeAxisGrid crée un AxisGridHelper, une classe que nous allons créer -pour rendre lil-gui heureux. Comme indiqué ci-dessus, lil-gui -créera automatiquement une interface utilisateur qui manipule la propriété nommée -de certains objets. Il créera une interface utilisateur différente en fonction du type -de propriété. Nous voulons qu'il crée une case à cocher, nous devons donc spécifier -une propriété bool. Mais, nous voulons que les axes et la grille -apparaissent/disparaissent en fonction d'une seule propriété, nous allons donc créer une classe -qui a un getter et un setter pour une propriété. De cette façon, nous pouvons laisser lil-gui -penser qu'il manipule une seule propriété, mais en interne, nous pouvons définir -la propriété visible à la fois de l'AxesHelper et du GridHelper pour un nœud.

-
// Active/désactive la visibilité des axes et de la grille
-// lil-gui nécessite une propriété qui renvoie un booléen
-// pour décider de créer une case à cocher, nous créons donc un setter
-// et un getter pour `visible` que nous pouvons dire à lil-gui
-// de regarder.
-class AxisGridHelper {
-  constructor(node, units = 10) {
-    const axes = new THREE.AxesHelper();
-    axes.material.depthTest = false;
-    axes.renderOrder = 2;  // après la grille
-    node.add(axes);
-
-    const grid = new THREE.GridHelper(units, units);
-    grid.material.depthTest = false;
-    grid.renderOrder = 1;
-    node.add(grid);
-
-    this.grid = grid;
-    this.axes = axes;
-    this.visible = false;
-  }
-  get visible() {
-    return this._visible;
-  }
-  set visible(v) {
-    this._visible = v;
-    this.grid.visible = v;
-    this.axes.visible = v;
-  }
-}
-
-

Une chose à noter est que nous avons défini le renderOrder de l'AxesHelper -à 2 et celui du GridHelper à 1 afin que les axes soient dessinés après la grille. -Sinon, la grille pourrait écraser les axes.

-

- -

-

Activez le solarSystem et vous verrez que la terre se trouve exactement à 10 -unités du centre, comme nous l'avons réglé ci-dessus. Vous pouvez voir comment la -terre se trouve dans l'espace local du solarSystem. De même, si vous -activez l'earthOrbit, vous verrez que la lune se trouve exactement à 2 unités -du centre de l'espace local de l'earthOrbit.

-

Quelques autres exemples de graphes de scène. Une automobile dans un monde de jeu simple pourrait avoir un graphe de scène comme celui-ci

-

-

Si vous déplacez la carrosserie de la voiture, toutes les roues bougeront avec elle. Si vous vouliez que la carrosserie -rebondisse séparément des roues, vous pourriez rendre la carrosserie et les roues enfants d'un nœud « châssis » -qui représente le châssis de la voiture.

-

Un autre exemple est un humain dans un monde de jeu.

-

-

Vous pouvez voir que le graphe de scène devient assez complexe pour un humain. En fait, -le graphe de scène ci-dessus est simplifié. Par exemple, vous pourriez l'étendre -pour couvrir chaque doigt (au moins 28 nœuds supplémentaires) et chaque orteil -(encore 28 nœuds) plus ceux pour le visage et la mâchoire, les yeux et peut-être plus.

-

Créons un graphe de scène semi-complexe. Nous allons faire un char. Le char aura -6 roues et une tourelle. Le char suivra un chemin. Il y aura une sphère qui -se déplacera et le char ciblera la sphère.

-

Voici le graphe de scène. Les maillages sont colorés en vert, les Object3D en bleu, -les lumières en or et les caméras en violet. Une caméra n'a pas été ajoutée -au graphe de scène.

-
- -

Regardez le code pour voir la configuration de tous ces nœuds.

-

Pour la cible, la chose que le char vise, il y a un targetOrbit -(Object3D) qui tourne simplement comme l'earthOrbit ci-dessus. Un -targetElevation (Object3D), qui est un enfant du targetOrbit, fournit un -décalage par rapport au targetOrbit et une élévation de base. Un autre -Object3D appelé targetBob est enfant de celui-ci et il monte et descend simplement -par rapport au targetElevation. Enfin, il y a le targetMesh qui est juste un cube que nous -faisons pivoter et dont nous changeons les couleurs

-
// déplacer la cible
-targetOrbit.rotation.y = time * .27;
-targetBob.position.y = Math.sin(time * 2) * 4;
-targetMesh.rotation.x = time * 7;
-targetMesh.rotation.y = time * 13;
-targetMaterial.emissive.setHSL(time * 10 % 1, 1, .25);
-targetMaterial.color.setHSL(time * 10 % 1, 1, .25);
-
-

Pour le char, il y a un Object3D appelé tank qui est utilisé pour déplacer tout ce qui se -trouve en dessous. Le code utilise une SplineCurve à laquelle il peut demander les positions -le long de cette courbe. 0.0 est le début de la courbe. 1.0 est la fin de la courbe. Il -demande la position actuelle où il place le char. Il demande ensuite une -position légèrement plus loin le long de la courbe et l'utilise pour orienter le char dans cette -direction en utilisant Object3D.lookAt.

-
const tankPosition = new THREE.Vector2();
-const tankTarget = new THREE.Vector2();
-
-...
-
-// déplacer le char
-const tankTime = time * .05;
-curve.getPointAt(tankTime % 1, tankPosition);
-curve.getPointAt((tankTime + 0.01) % 1, tankTarget);
-tank.position.set(tankPosition.x, 0, tankPosition.y);
-tank.lookAt(tankTarget.x, 0, tankTarget.y);
-
-

La tourelle sur le dessus du char est déplacée automatiquement en étant un enfant -du char. Pour la pointer vers la cible, nous demandons simplement la position mondiale de la cible -et ensuite utilisons à nouveau Object3D.lookAt.

-
const targetPosition = new THREE.Vector3();
-
-...
-
-// orienter la tourelle vers la cible
-targetMesh.getWorldPosition(targetPosition);
-turretPivot.lookAt(targetPosition);
-
-

Il y a une turretCamera qui est un enfant du turretMesh, donc -elle montera et descendra et tournera avec la tourelle. Nous la faisons -viser la cible.

-
// faire pointer la turretCamera vers la cible
-turretCamera.lookAt(targetPosition);
-
-

Il y a aussi un targetCameraPivot qui est un enfant du targetBob, donc il flotte -autour de la cible. Nous le faisons viser le char. Son but est de permettre à la -targetCamera d'être décalée par rapport à la cible elle-même. Si nous avions fait de la caméra -un enfant du targetBob et l'avions simplement fait pointer, elle serait à l'intérieur de la -cible.

-
// faire pointer le targetCameraPivot vers le char
-tank.getWorldPosition(targetPosition);
-targetCameraPivot.lookAt(targetPosition);
-
-

Enfin, nous faisons tourner toutes les roues

-
wheelMeshes.forEach((obj) => {
-  obj.rotation.x = time * 3;
-});
-
-

Pour les caméras, nous avons configuré un tableau de toutes les 4 caméras au moment de l'initialisation avec des descriptions.

-
const cameras = [
-  { cam: camera, desc: 'caméra détachée', },
-  { cam: turretCamera, desc: 'sur tourelle regardant la cible', },
-  { cam: targetCamera, desc: 'près de la cible regardant le char', },
-  { cam: tankCamera, desc: 'au-dessus de l'arrière du char', },
-];
-
-const infoElem = document.querySelector('#info');
-
-

et passons en revue nos caméras au moment du rendu.

-
const camera = cameras[time * .25 % cameras.length | 0];
-infoElem.textContent = camera.desc;
-
-

- -

-

J'espère que cela vous donne une idée du fonctionnement des graphes de scène et de la manière dont vous pourriez les utiliser. -Créer des nœuds Object3D et les rendre parents d'autres objets est une étape importante pour bien utiliser -un moteur 3D comme three.js. Souvent, il peut sembler qu'il soit nécessaire de faire des calculs mathématiques complexes -pour faire bouger et pivoter quelque chose comme vous le souhaitez. Par exemple, sans graphe de scène, -calculer le mouvement de la lune ou où placer les roues de la voiture par rapport à sa -carrosserie serait très compliqué, mais en utilisant un graphe de scène, cela devient beaucoup plus facile.

-

Ensuite, nous aborderons les matériaux.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/setup.html b/manual/fr/setup.html deleted file mode 100644 index 1d3ce4215fdb8c..00000000000000 --- a/manual/fr/setup.html +++ /dev/null @@ -1,84 +0,0 @@ - - - Configuration - - - - - - - - - - - - - -
-
-

Configuration

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. -Le premier article portait sur les fondamentaux de three.js. -Si vous ne l'avez pas encore lu, vous pourriez vouloir commencer par là.

-

Avant d'aller plus loin, nous devons parler de la configuration de votre -ordinateur en tant qu'environnement de développement. En particulier, pour des raisons de sécurité, -WebGL ne peut pas utiliser directement les images de votre disque dur. Cela signifie -que pour développer, vous devez utiliser un serveur web. Heureusement, -les serveurs web de développement sont très faciles à configurer et à utiliser.

-

Tout d'abord, si vous le souhaitez, vous pouvez télécharger l'intégralité de ce site à partir de ce lien. -Une fois téléchargé, double-cliquez sur le fichier zip pour décompresser les fichiers.

-

Ensuite, téléchargez l'un de ces serveurs web simples.

-

Si vous préférez un serveur web avec une interface utilisateur, il existe -Servez.

-

- -
- -

-

Il suffit de le pointer vers le dossier où vous avez décompressé les fichiers, cliquez sur "Démarrer", puis rendez-vous -dans votre navigateur à l'adresse http://localhost:8080/ ou si vous souhaitez -parcourir les exemples, allez à l'adresse http://localhost:8080/threejs.

-

Pour arrêter le service, cliquez sur stop ou quittez Servez.

-

Si vous préférez la ligne de commande (c'est mon cas), une autre solution est d'utiliser node.js. -Téléchargez-le, installez-le, puis ouvrez une fenêtre d'invite de commandes / console / terminal. Si vous êtes sous Windows, le programme d'installation ajoutera une "Invite de commandes Node" spéciale, utilisez donc celle-ci.

-

Ensuite, installez servez en tapant

-
npm -g install servez
-

Si vous êtes sur OSX, utilisez

-
sudo npm -g install servez
-

Une fois que vous avez fait cela, tapez

-
servez path/to/folder/where/you/unzipped/files
-

Ou si vous êtes comme moi

-
cd path/to/folder/where/you/unzipped/files
-servez
-

Il devrait afficher quelque chose comme

-

- -
- -

-

Puis, dans votre navigateur, allez à l'adresse http://localhost:8080/.

-

Si vous ne spécifiez pas de chemin, servez servira le dossier actuel.

-

Si aucune de ces options ne vous convient, -il existe de nombreux autres serveurs simples parmi lesquels choisir.

-

Maintenant que vous avez configuré un serveur, nous pouvons passer aux textures.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/shadertoy.html b/manual/fr/shadertoy.html deleted file mode 100644 index f7a6d74eaa053a..00000000000000 --- a/manual/fr/shadertoy.html +++ /dev/null @@ -1,322 +0,0 @@ - - - Three.js et Shadertoy - - - - - - - - - - - - - -
-
-

Three.js et Shadertoy

-
-
-
-

Shadertoy est un site web célèbre qui héberge des expériences de shaders incroyables. Les gens demandent souvent comment ils peuvent utiliser ces shaders avec Three.js.

-

Il est important de reconnaître que cela s'appelle ShaderTOY pour une raison. En général, les shaders shadertoy ne sont pas axés sur les meilleures pratiques. Il s'agit plutôt d'un défi amusant, similaire à dwitter (écrire du code en 140 caractères) ou js13kGames (faire un jeu en 13k ou moins).

-

Dans le cas de Shadertoy, le défi est : écrire une fonction qui, pour une position de pixel donnée, produit une couleur qui dessine quelque chose d'intéressant. C'est un défi amusant et de nombreux résultats sont incroyables. Mais ce n'est pas la meilleure pratique.

-

Comparez ce shader shadertoy incroyable qui dessine une ville entière

-
- -

En plein écran sur mon GPU, il tourne à environ 5 images par seconde. Comparez cela à un jeu comme Cities: Skylines

-
- -

Ce jeu tourne à 30-60 images par seconde sur la même machine car il utilise des techniques plus traditionnelles, dessinant des bâtiments faits de triangles avec des textures, etc...

-

Néanmoins, passons en revue l'utilisation d'un shader Shadertoy avec three.js.

-

C'est le shader shadertoy par défaut si vous choisissez "New" sur shadertoy.com, du moins en janvier 2019.

-
// Par iq: https://www.shadertoy.com/user/iq
-// licence: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    // Coordonnées normalisées des pixels (de 0 à 1)
-    vec2 uv = fragCoord/iResolution.xy;
-
-    // Couleur variable des pixels avec le temps
-    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-
-    // Sortie à l'écran
-    fragColor = vec4(col,1.0);
-}
-
-

Une chose importante à comprendre à propos des shaders est qu'ils sont écrits dans un langage appelé GLSL (Graphics Library Shading Language) conçu pour les mathématiques 3D qui inclut des types spéciaux. Ci-dessus, nous voyons vec4, vec2, vec3 comme 3 de ces types spéciaux. Un vec2 a 2 valeurs, un vec3 3, un vec4 4 valeurs. Ils peuvent être adressés de plusieurs manières. Les manières les plus courantes sont avec x, y, z et w comme dans

-
vec4 v1 = vec4(1.0, 2.0, 3.0, 4.0);
-float v2 = v1.x + v1.y;  // adds 1.0 + 2.0
-
-

Contrairement à JavaScript, GLSL ressemble plus à C/C++ où les variables doivent avoir leur type déclaré, donc au lieu de var v = 1.2; c'est float v = 1.2; déclarant v comme un nombre à virgule flottante.

-

Expliquer GLSL en détail dépasse le cadre de cet article. Pour un aperçu rapide, consultez cet article et peut-être poursuivez avec cette série.

-

Il convient de noter que, du moins en janvier 2019, shadertoy.com ne s'occupe que des fragment shaders. La responsabilité d'un fragment shader est, étant donné une position de pixel, de produire une couleur pour ce pixel.

-

En regardant la fonction ci-dessus, nous pouvons voir que le shader a un paramètre out appelé fragColor. out signifie output (sortie). C'est un paramètre pour lequel la fonction est censée fournir une valeur. Nous devons le définir à une certaine couleur.

-

Il a également un paramètre in (pour input, entrée) appelé fragCoord. C'est la coordonnée du pixel qui est sur le point d'être dessinée. Nous pouvons utiliser cette coordonnée pour décider d'une couleur. Si le canevas sur lequel nous dessinons est de 400x300 pixels, alors la fonction sera appelée 400x300 fois, soit 120 000 fois. À chaque fois, fragCoord sera une coordonnée de pixel différente.

-

Il y a 2 autres variables utilisées qui ne sont pas définies dans le code. L'une est iResolution. Elle est définie à la résolution du canevas. Si le canevas est de 400x300, alors iResolution serait 400,300, donc au fur et à mesure que les coordonnées des pixels changent, cela fait passer uv de 0.0 à 1.0 en travers et vers le haut de la texture. Travailler avec des valeurs normalisées rend souvent les choses plus faciles, c'est pourquoi la majorité des shaders shadertoy commencent par quelque chose comme ça.

-

L'autre variable non définie dans le shader est iTime. C'est le temps écoulé depuis le chargement de la page en secondes.

-

Dans le jargon des shaders, ces variables globales sont appelées variables uniformes. Elles sont appelées uniformes car elles ne changent pas, elles restent uniformes d'une itération du shader à la suivante. Il est important de noter qu'elles sont toutes spécifiques à shadertoy. Ce ne sont pas des variables GLSL officielles. Ce sont des variables que les créateurs de shadertoy ont inventées.

-

La documentation de Shadertoy en définit plusieurs autres. Pour l'instant, écrivons quelque chose qui gère les deux utilisées dans le shader ci-dessus.

-

La première chose à faire est de créer un simple plan qui remplit le canevas. Si vous ne l'avez pas encore lu, nous l'avons fait dans l'article sur les arrière-plans, alors prenons cet exemple mais retirons les cubes. C'est assez court, voici donc l'intégralité :

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const camera = new THREE.OrthographicCamera(
-    -1, // left
-     1, // right
-     1, // top
-    -1, // bottom
-    -1, // near,
-     1, // far
-  );
-  const scene = new THREE.Scene();
-  const plane = new THREE.PlaneGeometry(2, 2);
-  const material = new THREE.MeshBasicMaterial({
-      color: 'red',
-  });
-  scene.add(new THREE.Mesh(plane, material));
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render() {
-    resizeRendererToDisplaySize(renderer);
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-
-

Comme expliqué dans l'article sur les arrière-plans, une OrthographicCamera avec ces paramètres et un plan de 2 unités remplira le canevas. Pour l'instant, tout ce que nous obtiendrons est un canevas rouge car notre plan utilise un MeshBasicMaterial rouge.

-

- -

-

Maintenant que nous avons quelque chose qui fonctionne, ajoutons le shader shadertoy.

-
const fragmentShader = `
-#include <common>
-
-uniform vec3 iResolution;
-uniform float iTime;
-
-// Par iq: https://www.shadertoy.com/user/iq
-// licence: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    // Coordonnées normalisées des pixels (de 0 à 1)
-    vec2 uv = fragCoord/iResolution.xy;
-
-    // Couleur variable des pixels avec le temps
-    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-
-    // Sortie à l'écran
-    fragColor = vec4(col,1.0);
-}
-
-void main() {
-  mainImage(gl_FragColor, gl_FragCoord.xy);
-}
-`;
-
-

Ci-dessus, nous avons déclaré les 2 variables uniformes dont nous avons parlé. Ensuite, nous avons inséré le code GLSL du shader de shadertoy. Enfin, nous avons appelé mainImage en lui passant gl_FragColor et gl_FragCoord.xy. gl_FragColor est une variable globale WebGL officielle que le shader est responsable de définir à la couleur qu'il souhaite pour le pixel actuel. gl_FragCoord est une autre variable globale WebGL officielle qui nous indique la coordonnée du pixel pour lequel nous choisissons actuellement une couleur.

-

Nous devons ensuite configurer les uniformes de three.js afin de pouvoir fournir des valeurs au shader.

-
const uniforms = {
-  iTime: { value: 0 },
-  iResolution:  { value: new THREE.Vector3() },
-};
-
-

Chaque uniforme dans THREE.js a un paramètre value. Cette valeur doit correspondre au type de l'uniforme.

-

Ensuite, nous passons le fragment shader et les uniformes à un ShaderMaterial.

-
-const material = new THREE.MeshBasicMaterial({
--    color: 'red',
--});
-+const material = new THREE.ShaderMaterial({
-+  fragmentShader,
-+  uniforms,
-+});
-
-

et avant de rendre, nous devons définir les valeurs des uniformes

-
-function render() {
-+function render(time) {
-+  time *= 0.001;  // convertir en secondes
-
-  resizeRendererToDisplaySize(renderer);
-
-+  const canvas = renderer.domElement;
-+  uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
-+  uniforms.iTime.value = time;
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-
-

Note : Je n'ai aucune idée pourquoi iResolution est un vec3 et ce que contient la 3ème valeur n'est pas documenté sur shadertoy.com. Elle n'est pas utilisée ci-dessus, donc je la définis juste à 1 pour l'instant. ¯\_(ツ)_/¯

-
-

- -

-

Cela correspond à ce que nous voyons sur Shadertoy pour un nouveau shader, du moins en janvier 2019 😉. Que fait le shader ci-dessus ?

-
    -
  • uv va de 0 à 1.
  • -
  • cos(uv.xyx) nous donne 3 valeurs de cosinus sous forme de vec3. Une pour uv.x, une autre pour uv.y et une autre pour uv.x à nouveau.
  • -
  • L'ajout du temps, cos(iTime+uv.xyx), les rend animés.
  • -
  • L'ajout de vec3(0,2,4) comme dans cos(iTime+uv.xyx+vec3(0,2,4)) décale les ondes cosinusoïdales
  • -
  • cos va de -1 à 1, donc 0.5 * 0.5 + cos(...) convertit de -1 <-> 1 à 0.0 <-> 1.0
  • -
  • les résultats sont ensuite utilisés comme couleur RVB pour le pixel actuel
  • -
-

Un petit changement facilitera la visualisation des ondes cosinusoïdales. Actuellement, uv ne va que de 0 à 1. Un cosinus se répète à 2π, alors faisons-le aller de 0 à 40 en multipliant par 40.0. Cela devrait le faire se répéter environ 6,3 fois.

-
-vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-+vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx*40.0+vec3(0,2,4));
-
-

En comptant ci-dessous, je vois environ 6,3 répétitions. Nous pouvons voir le bleu entre le rouge car il est décalé de 4 via le +vec3(0,2,4). Sans cela, le bleu et le rouge se chevaucheraient parfaitement, créant du violet.

-

- -

-

Savoir à quel point les entrées sont simples et ensuite voir des résultats comme un canal urbain, une forêt, un escargot, un champignon rend le défi d'autant plus impressionnant. Espérons qu'ils expliquent également clairement pourquoi ce n'est généralement pas la bonne approche par rapport aux méthodes plus traditionnelles de création de scènes à partir de triangles. Le fait qu'il faille faire autant de calculs pour déterminer la couleur de chaque pixel signifie que ces exemples tournent très lentement.

-

Certains shaders shadertoy prennent des textures en entrée, comme celui-ci.

-
// Par Daedelus: https://www.shadertoy.com/user/Daedelus
-// licence: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-#define TIMESCALE 0.25
-#define TILES 8
-#define COLOR 0.7, 1.6, 2.8
-
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    vec2 uv = fragCoord.xy / iResolution.xy;
-    uv.x *= iResolution.x / iResolution.y;
-
-    vec4 noise = texture2D(iChannel0, floor(uv * float(TILES)) / float(TILES));
-    float p = 1.0 - mod(noise.r + noise.g + noise.b + iTime * float(TIMESCALE), 1.0);
-    p = min(max(p * 3.0 - 1.8, 0.1), 2.0);
-
-    vec2 r = mod(uv * float(TILES), 1.0);
-    r = vec2(pow(r.x - 0.5, 2.0), pow(r.y - 0.5, 2.0));
-    p *= 1.0 - pow(min(1.0, 12.0 * dot(r, r)), 2.0);
-
-    fragColor = vec4(COLOR, 1.0) * p;
-}
-
-

Passer une texture à un shader est similaire à en passer une à un matériau normal, mais nous devons configurer la texture sur les uniformes.

-

Tout d'abord, ajoutons l'uniforme pour la texture au shader. Ils sont appelés sampler2D en GLSL.

-
const fragmentShader = `
-#include <common>
-
-uniform vec3 iResolution;
-uniform float iTime;
-+uniform sampler2D iChannel0;
-
-...
-
-

Ensuite, nous pouvons charger une texture comme nous l'avons vu ici et affecter la valeur de l'uniforme.

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load('resources/images/bayer.png');
-+texture.minFilter = THREE.NearestFilter;
-+texture.magFilter = THREE.NearestFilter;
-+texture.wrapS = THREE.RepeatWrapping;
-+texture.wrapT = THREE.RepeatWrapping;
-const uniforms = {
-  iTime: { value: 0 },
-  iResolution:  { value: new THREE.Vector3() },
-+  iChannel0: { value: texture },
-};
-
-

- -

-

Jusqu'à présent, nous avons utilisé les shaders Shadertoy tels qu'ils sont utilisés sur Shadertoy.com, à savoir pour couvrir le canevas. Il n'y a cependant aucune raison de nous limiter à ce cas d'utilisation. L'important à retenir est que les fonctions que les gens écrivent sur shadertoy prennent généralement juste une entrée fragCoord et une iResolution. fragCoord n'a pas à provenir des coordonnées de pixels ; nous pourrions utiliser autre chose, comme des coordonnées de texture, et les utiliser ensuite un peu comme d'autres textures. Cette technique d'utilisation d'une fonction pour générer des textures est souvent appelée une texture procédurale.

-

Modifions le shader ci-dessus pour faire cela. La chose la plus simple à faire pourrait être de prendre les coordonnées de texture que three.js fournit normalement, de les multiplier par iResolution et de les passer pour fragCoords.

-

Pour ce faire, nous ajoutons un varying. Un varying est une valeur passée du vertex shader au fragment shader qui est interpolée (ou varie) entre les sommets. Pour l'utiliser dans notre fragment shader, nous la déclarons. Three.js fait référence à ses coordonnées de texture comme uv avec le v devant signifiant varying (variable).

-
...
-
-+varying vec2 vUv;
-
-void main() {
--  mainImage(gl_FragColor, gl_FragCoord.xy);
-+  mainImage(gl_FragColor, vUv * iResolution.xy);
-}
-
-

Ensuite, nous devons également fournir notre propre vertex shader. Voici un vertex shader three.js minimal assez courant. Three.js déclare et fournira des valeurs pour uv, projectionMatrix, modelViewMatrix et position.

-
const vertexShader = `
-  varying vec2 vUv;
-  void main() {
-    vUv = uv;
-    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
-  }
-`;
-
-

Nous devons passer le vertex shader au ShaderMaterial

-
const material = new THREE.ShaderMaterial({
-  vertexShader,
-  fragmentShader,
-  uniforms,
-});
-
-

Nous pouvons définir la valeur de l'uniforme iResolution au moment de l'initialisation car elle ne changera plus.

-
const uniforms = {
-  iTime: { value: 0 },
--  iResolution:  { value: new THREE.Vector3() },
-+  iResolution:  { value: new THREE.Vector3(1, 1, 1) },
-  iChannel0: { value: texture },
-};
-
-

et nous n'avons plus besoin de la définir au moment du rendu

-
-const canvas = renderer.domElement;
--uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
-uniforms.iTime.value = time;
-
-

Sinon, j'ai copié à nouveau la caméra originale et le code qui configure 3 cubes en rotation de l'article sur la réactivité. Le résultat :

-

- -

-

J'espère que cela vous donnera au moins une base sur la façon d'utiliser un shader shadertoy avec three.js. Encore une fois, il est important de se rappeler que la plupart des shaders shadertoy sont un défi intéressant (tout dessiner avec une seule fonction) plutôt que la méthode recommandée pour réellement afficher des choses de manière performante. Néanmoins, ils sont incroyables, impressionnants, beaux, et vous pouvez apprendre énormément en voyant comment ils fonctionnent.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/shadows.html b/manual/fr/shadows.html deleted file mode 100644 index a1d75a9e98d8d2..00000000000000 --- a/manual/fr/shadows.html +++ /dev/null @@ -1,464 +0,0 @@ - - - Ombres - - - - - - - - - - - - - -
-
-

Ombres

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. Le -premier article est les fondamentaux de three.js. Si -vous ne l'avez pas encore lu et que vous débutez avec three.js, vous pourriez envisager de -commencer par là. L'article précédent portait sur les caméras, ce qui est -important à lire avant de lire cet article, tout comme -l'article précédent sur les lumières.

-

Les ombres sur ordinateur peuvent être un sujet complexe. Il existe diverses -solutions et toutes impliquent des compromis, y compris les solutions -disponibles dans three.js.

-

Three.js utilise par défaut des cartes d'ombres. Le fonctionnement d'une carte d'ombres -est le suivant : pour chaque lumière qui projette des ombres, tous les objets marqués pour projeter -des ombres sont rendus du point de vue de la lumière. **LISEZ CELA -À NOUVEAU !** et laissez-le s'imprégner.

-

En d'autres termes, si vous avez 20 objets et 5 lumières, et que -les 20 objets projettent des ombres et les 5 lumières projettent -des ombres, alors toute votre scène sera dessinée 6 fois. Les 20 objets -seront dessinés pour la lumière n°1, puis les 20 objets seront dessinés pour -la lumière n°2, puis n°3, etc., et enfin la scène réelle sera dessinée -en utilisant les données des 5 premiers rendus.

-

Pire encore, si vous avez une lumière ponctuelle (point light) qui projette des ombres, la scène -doit être dessinée 6 fois juste pour cette lumière !

-

Pour ces raisons, il est courant de trouver d'autres solutions plutôt que d'avoir -un tas de lumières générant toutes des ombres. Une solution courante -consiste à avoir plusieurs lumières mais seulement une lumière directionnelle (directional light) générant -des ombres.

-

Une autre solution consiste à utiliser des lightmaps (cartes d'éclairage) et/ou des ambient occlusion maps -(cartes d'occlusion ambiante) pour pré-calculer les effets d'éclairage hors ligne. Cela se traduit par un éclairage statique -ou des indices d'éclairage statique, mais au moins c'est rapide. Nous -aborderons ces deux points dans un autre article.

-

Une autre solution consiste à utiliser de fausses ombres. Créez un plan, placez une texture en niveaux de gris -sur le plan qui approxime une ombre, -dessinez-le au-dessus du sol, sous votre objet.

-

Par exemple, utilisons cette texture comme fausse ombre

-
- -

Nous utiliserons une partie du code de l'article précédent.

-

Définissons la couleur de fond sur blanc.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-

Ensuite, nous allons configurer le même sol en damier, mais cette fois-ci en utilisant -un MeshBasicMaterial car nous n'avons pas besoin d'éclairage pour le sol.

-
+const loader = new THREE.TextureLoader();
-
-{
-  const planeSize = 40;
-
--  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/checker.png');
-  texture.wrapS = THREE.RepeatWrapping;
-  texture.wrapT = THREE.RepeatWrapping;
-  texture.magFilter = THREE.NearestFilter;
-  const repeats = planeSize / 2;
-  texture.repeat.set(repeats, repeats);
-
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-  const planeMat = new THREE.MeshBasicMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-+  planeMat.color.setRGB(1.5, 1.5, 1.5);
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  mesh.rotation.x = Math.PI * -.5;
-  scene.add(mesh);
-}
-
-

Notez que nous définissons la couleur sur 1.5, 1.5, 1.5. Cela multipliera les couleurs -de la texture en damier par 1.5, 1.5, 1.5. Étant donné que les couleurs de la texture sont 0x808080 et 0xC0C0C0, -ce qui correspond à un gris moyen et un gris clair, les multiplier par 1.5 nous donnera un damier -blanc et gris clair.

-

Chargeons la texture d'ombre

-
const shadowTexture = loader.load('resources/images/roundshadow.png');
-
-

et créons un tableau pour mémoriser chaque sphère et les objets associés.

-
const sphereShadowBases = [];
-
-

Ensuite, nous allons créer une géométrie de sphère

-
const sphereRadius = 1;
-const sphereWidthDivisions = 32;
-const sphereHeightDivisions = 16;
-const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-
-

Et une géométrie de plan pour la fausse ombre

-
const planeSize = 1;
-const shadowGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-
-

Maintenant, nous allons créer un tas de sphères. Pour chaque sphère, nous créerons une base -THREE.Object3D et nous ferons du maillage du plan d'ombre et du maillage de la sphère des enfants de la base. -De cette façon, si nous déplaçons la base, la sphère et l'ombre se déplaceront. Nous devons placer l'ombre légèrement au-dessus du sol pour éviter le z-fighting. -Nous définissons également depthWrite à false afin que les ombres ne s'entremêlent pas. -Nous aborderons ces deux problèmes dans un autre article. -L'ombre est un MeshBasicMaterial car elle n'a pas besoin d'éclairage.

-

Nous donnons à chaque sphère une teinte différente, puis nous enregistrons la base, le maillage de la sphère, -le maillage de l'ombre et la position y initiale de chaque sphère.

-
const numSpheres = 15;
-for (let i = 0; i < numSpheres; ++i) {
-  // créer une base pour l'ombre et la sphère
-  // afin qu'elles se déplacent ensemble.
-  const base = new THREE.Object3D();
-  scene.add(base);
-
-  // ajouter l'ombre à la base
-  // note : nous créons un nouveau matériau pour chaque sphère
-  // afin de pouvoir définir la transparence du matériau de cette sphère
-  // séparément.
-  const shadowMat = new THREE.MeshBasicMaterial({
-    map: shadowTexture,
-    transparent: true,    // pour que nous puissions voir le sol
-    depthWrite: false,    // pour ne pas avoir à trier
-  });
-  const shadowMesh = new THREE.Mesh(shadowGeo, shadowMat);
-  shadowMesh.position.y = 0.001;  // pour être légèrement au-dessus du sol
-  shadowMesh.rotation.x = Math.PI * -.5;
-  const shadowSize = sphereRadius * 4;
-  shadowMesh.scale.set(shadowSize, shadowSize, shadowSize);
-  base.add(shadowMesh);
-
-  // ajouter la sphère à la base
-  const u = i / numSpheres;   // va de 0 à 1 au fur et à mesure que nous parcourons les sphères.
-  const sphereMat = new THREE.MeshPhongMaterial();
-  sphereMat.color.setHSL(u, 1, .75);
-  const sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
-  sphereMesh.position.set(0, sphereRadius + 2, 0);
-  base.add(sphereMesh);
-
-  // mémoriser les 3 plus la position y
-  sphereShadowBases.push({base, sphereMesh, shadowMesh, y: sphereMesh.position.y});
-}
-
-

Nous configurons 2 lumières. L'une est une HemisphereLight avec l'intensité définie à 2 pour vraiment -éclaircir les choses.

-
{
-  const skyColor = 0xB1E1FF;  // bleu clair
-  const groundColor = 0xB97A20;  // orange brunâtre
-  const intensity = 2;
-  const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
-  scene.add(light);
-}
-
-

L'autre est une DirectionalLight afin que les sphères obtiennent une certaine définition

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(0, 10, 5);
-  light.target.position.set(-5, 0, 0);
-  scene.add(light);
-  scene.add(light.target);
-}
-
-

Cela rendrait tel quel, mais animons ces sphères. -Pour chaque ensemble sphère, ombre, base, nous déplaçons la base dans le plan xz, nous -déplaçons la sphère de haut en bas en utilisant Math.abs(Math.sin(time)) -ce qui nous donne une animation rebondissante. Et nous définissons également l'opacité du matériau de l'ombre -afin que, à mesure que chaque sphère monte, son ombre s'estompe.

-
function render(time) {
-  time *= 0.001;  // convertir en secondes
-
-  ...
-
-  sphereShadowBases.forEach((sphereShadowBase, ndx) => {
-    const {base, sphereMesh, shadowMesh, y} = sphereShadowBase;
-
-    // u est une valeur qui va de 0 à 1 au fur et à mesure que nous parcourons les sphères
-    const u = ndx / sphereShadowBases.length;
-
-    // calculer une position pour la base. Cela déplacera
-    // à la fois la sphère et son ombre
-    const speed = time * .2;
-    const angle = speed + u * Math.PI * 2 * (ndx % 1 ? 1 : -1);
-    const radius = Math.sin(speed - ndx) * 10;
-    base.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);
-
-    // yOff est une valeur qui va de 0 à 1
-    const yOff = Math.abs(Math.sin(time * 2 + ndx));
-    // déplacer la sphère de haut en bas
-    sphereMesh.position.y = y + THREE.MathUtils.lerp(-2, 2, yOff);
-    // estomper l'ombre à mesure que la sphère monte
-    shadowMesh.material.opacity = THREE.MathUtils.lerp(1, .25, yOff);
-  });
-
-  ...
-
-

Et voici 15 sortes de balles rebondissantes.

-

- -

-

Dans certaines applications, il est courant d'utiliser une ombre ronde ou ovale pour tout, mais -bien sûr, vous pourriez aussi utiliser des textures d'ombre de formes différentes. Vous pourriez également -donner à l'ombre un bord plus net. Un bon exemple de l'utilisation de ce type -d'ombre est Animal Crossing Pocket Camp -où vous pouvez voir que chaque personnage a une simple ombre ronde. C'est efficace et peu coûteux. -Monument Valley -semble également utiliser ce type d'ombre pour le personnage principal.

-

Passons maintenant aux cartes d'ombres. Il existe 3 types de lumières qui peuvent projeter des ombres : la DirectionalLight, -la PointLight et la SpotLight.

-

Commençons par la DirectionalLight en utilisant l'exemple avec helper de l'article sur les lumières.

-

La première chose à faire est d'activer les ombres dans le rendu (renderer).

-
const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+renderer.shadowMap.enabled = true;
-
-

Ensuite, nous devons également dire à la lumière de projeter une ombre

-
const light = new THREE.DirectionalLight(color, intensity);
-+light.castShadow = true;
-
-

Nous devons également parcourir chaque maillage dans la scène et décider s'il doit -à la fois projeter des ombres et/ou recevoir des ombres.

-

Faisons en sorte que le plan (le sol) reçoive uniquement les ombres, car nous ne -nous soucions pas vraiment de ce qui se passe en dessous.

-
const mesh = new THREE.Mesh(planeGeo, planeMat);
-mesh.receiveShadow = true;
-
-

Pour le cube et la sphère, faisons en sorte qu'ils reçoivent et projettent tous deux des ombres

-
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-mesh.castShadow = true;
-mesh.receiveShadow = true;
-
-...
-
-const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-mesh.castShadow = true;
-mesh.receiveShadow = true;
-
-

Et ensuite, nous l'exécutons.

-

- -

-

Que s'est-il passé ? Pourquoi des parties des ombres sont-elles manquantes ?

-

La raison est que les cartes d'ombres sont créées en rendant la scène du point -de vue de la lumière. Dans ce cas, il y a une caméra au niveau de la DirectionalLight -qui regarde sa cible. Tout comme les caméras que nous avons précédemment couvertes, -la caméra d'ombre de la lumière définit une zone à l'intérieur de laquelle -les ombres sont rendues. Dans l'exemple ci-dessus, cette zone est trop petite.

-

Afin de visualiser cette zone, nous pouvons obtenir la caméra d'ombre de la lumière et ajouter -un CameraHelper à la scène.

-
const cameraHelper = new THREE.CameraHelper(light.shadow.camera);
-scene.add(cameraHelper);
-
-

Et maintenant, vous pouvez voir la zone pour laquelle les ombres sont projetées et reçues.

-

- -

-

Ajustez la valeur x de la cible d'avant en arrière et il devrait être assez clair que seules -les ombres sont dessinées dans la zone de la caméra d'ombre de la lumière.

-

Nous pouvons ajuster la taille de cette boîte en ajustant la caméra d'ombre de la lumière.

-

Ajoutons des paramètres d'interface graphique pour ajuster la boîte de la caméra d'ombre de la lumière. Comme une -DirectionalLight représente une lumière allant dans une direction parallèle, la -DirectionalLight utilise une OrthographicCamera pour sa caméra d'ombre. -Nous avons vu comment fonctionne une OrthographicCamera dans l'article précédent sur les caméras.

-

Rappelons qu'une OrthographicCamera définit -sa boîte ou son frustum de visualisation par ses propriétés left, right, top, bottom, near, far, -et zoom.

-

À nouveau, créons une classe d'aide pour lil-gui. Nous créerons une DimensionGUIHelper -à laquelle nous passerons un objet et 2 propriétés. Elle présentera une propriété que lil-gui -peut ajuster et, en réponse, définira les deux propriétés, l'une positive et l'autre négative. -Nous pouvons l'utiliser pour définir left et right comme width, et up et down comme height.

-
class DimensionGUIHelper {
-  constructor(obj, minProp, maxProp) {
-    this.obj = obj;
-    this.minProp = minProp;
-    this.maxProp = maxProp;
-  }
-  get value() {
-    return this.obj[this.maxProp] * 2;
-  }
-  set value(v) {
-    this.obj[this.maxProp] = v /  2;
-    this.obj[this.minProp] = v / -2;
-  }
-}
-
-

Nous utiliserons également la MinMaxGUIHelper que nous avons créée dans l'article sur les caméras -pour ajuster near et far.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 2, 0.01);
-+{
-+  const folder = gui.addFolder('Caméra d\'ombre');
-+  folder.open();
-+  folder.add(new DimensionGUIHelper(light.shadow.camera, 'left', 'right'), 'value', 1, 100)
-+    .name('largeur')
-+    .onChange(updateCamera);
-+  folder.add(new DimensionGUIHelper(light.shadow.camera, 'bottom', 'top'), 'value', 1, 100)
-+    .name('hauteur')
-+    .onChange(updateCamera);
-+  const minMaxGUIHelper = new MinMaxGUIHelper(light.shadow.camera, 'near', 'far', 0.1);
-+  folder.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('proche').onChange(updateCamera);
-+  folder.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('loin').onChange(updateCamera);
-+  folder.add(light.shadow.camera, 'zoom', 0.01, 1.5, 0.01).onChange(updateCamera);
-+}
-
-

Nous demandons à l'interface graphique d'appeler notre fonction updateCamera chaque fois que quelque chose change. -Écrivons cette fonction pour mettre à jour la lumière, l'helper pour la lumière, la -caméra d'ombre de la lumière et l'helper affichant la caméra d'ombre de la lumière.

-
function updateCamera() {
-  // mettre à jour le matrixWorld de la cible de la lumière car il est nécessaire pour l'helper
-  light.target.updateMatrixWorld();
-  helper.update();
-  // mettre à jour la matrice de projection de la caméra d'ombre de la lumière
-  light.shadow.camera.updateProjectionMatrix();
-  // et maintenant mettre à jour l'helper caméra que nous utilisons pour afficher la caméra d'ombre de la lumière
-  cameraHelper.update();
-}
-updateCamera();
-
-

Et maintenant que nous avons donné à la caméra d'ombre de la lumière une interface graphique, nous pouvons jouer avec les valeurs.

-

- -

-

Définissez la largeur et la hauteur à environ 30 et vous pourrez voir que les ombres sont correctes -et que les zones qui doivent être dans l'ombre pour cette scène sont entièrement couvertes.

-

Mais cela soulève la question : pourquoi ne pas simplement définir la largeur et la hauteur à des -nombres géants pour tout couvrir ? Définissez la largeur et la hauteur à 100 -et vous pourriez voir quelque chose comme ceci

-
- -

Qu'est-ce qui se passe avec ces ombres basse résolution ?!

-

Ce problème est un autre paramètre lié aux ombres dont il faut être conscient. -Les cartes d'ombres sont des textures dans lesquelles les ombres sont dessinées. -Ces textures ont une taille. La zone de la caméra d'ombre que nous avons définie ci-dessus est étirée -sur cette taille. Cela signifie que plus la zone que vous définissez est grande, plus vos ombres seront -pixelisées.

-

Vous pouvez définir la résolution de la texture de la carte d'ombre en définissant light.shadow.mapSize.width -et light.shadow.mapSize.height. Par défaut, elles sont de 512x512. -Plus vous les augmentez, plus elles consomment de mémoire et plus elles sont lentes à calculer, vous voulez donc -les définir aussi petites que possible tout en faisant fonctionner votre scène. Il en va de même pour la -zone de la caméra d'ombre de la lumière. Plus elle est petite, meilleures sont les ombres, alors rendez la zone aussi petite que possible et -continuez à couvrir votre scène. Sachez que la machine de chaque utilisateur a une taille de texture maximale -autorisée qui est disponible sur le renderer sous la forme de renderer.capabilities.maxTextureSize.

- -

En passant à la SpotLight, la caméra d'ombre de la lumière devient une PerspectiveCamera. Contrairement à la caméra d'ombre -de la DirectionalLight où nous pouvions définir manuellement la plupart de ses paramètres, la caméra d'ombre -de la SpotLight est contrôlée par la SpotLight elle-même. Le fov (champ de vision) pour l'ombre -de la caméra est directement lié au paramètre angle de la SpotLight. -L'aspect est défini automatiquement en fonction de la taille de la carte d'ombre.

-
-const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.SpotLight(color, intensity);
-
-

et nous avons rajouté les paramètres penumbra et angle -de notre article sur les lumières.

-

- -

- -

Et enfin, il y a les ombres avec une PointLight. Comme une PointLight -brille dans toutes les directions, les seuls paramètres pertinents sont near et far. -Sinon, l'ombre d'une PointLight est effectivement composée de 6 ombres de SpotLight -, chacune pointant vers une face d'un cube autour de la lumière. Cela signifie -que les ombres des PointLight sont beaucoup plus lentes car toute la scène doit être -dessinée 6 fois, une pour chaque direction.

-

Mettons une boîte autour de notre scène pour que nous puissions voir les ombres sur les murs -et le plafond. Nous définirons la propriété side du matériau sur THREE.BackSide -afin de rendre l'intérieur de la boîte au lieu de l'extérieur. Comme le sol, -nous la définirons pour qu'elle ne reçoive que les ombres. De plus, nous définirons la position de la -boîte de manière à ce que son bas soit légèrement en dessous du sol afin que le sol et le bas -de la boîte ne causent pas de z-fighting.

-
{
-  const cubeSize = 30;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-  const cubeMat = new THREE.MeshPhongMaterial({
-    color: '#CCC',
-    side: THREE.BackSide,
-  });
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.receiveShadow = true;
-  mesh.position.set(0, cubeSize / 2 - 0.1, 0);
-  scene.add(mesh);
-}
-
-

Et bien sûr, nous devons changer la lumière en PointLight.

-
-const light = new THREE.SpotLight(color, intensity);
-+const light = new THREE.PointLight(color, intensity);
-
-....
-
-// pour pouvoir facilement voir où se trouve la lumière ponctuelle
-+const helper = new THREE.PointLightHelper(light);
-+scene.add(helper);
-
-

- -

-

Utilisez les paramètres d'interface graphique position pour déplacer la lumière -et vous verrez les ombres tomber sur tous les murs. Vous pouvez -également ajuster les paramètres near et far et voir, tout comme -pour les autres ombres, que lorsque les objets sont plus proches que near, ils -ne reçoivent plus d'ombre et lorsqu'ils sont plus loin que far, ils sont toujours dans l'ombre.

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/textures.html b/manual/fr/textures.html deleted file mode 100644 index a8b2c1da837e78..00000000000000 --- a/manual/fr/textures.html +++ /dev/null @@ -1,566 +0,0 @@ - - - Textures - - - - - - - - - - - - - -
-
-

Textures

-
-
-
-

Cet article fait partie d'une série d'articles sur three.js. -Le premier article concernait les bases de three.js. -L'article précédent expliquait comment se préparer pour cet article. -Si vous ne l'avez pas encore lu, vous pourriez vouloir commencer par là.

-

Les textures sont un sujet assez vaste dans Three.js et -je ne suis pas sûr à 100% du niveau auquel les expliquer, mais je vais essayer. -Il y a de nombreux sujets et beaucoup d'entre eux sont interdépendants, il est donc difficile d'expliquer -tout en une seule fois. Voici une table des matières rapide pour cet article.

- - -

Bonjour la texture

-

Les textures sont généralement des images qui sont le plus souvent créées -dans un programme tiers comme Photoshop ou GIMP. Par exemple, mettons -cette image sur un cube.

-
- -
- -

Nous allons modifier un de nos premiers exemples. Tout ce que nous avons à faire est de créer un TextureLoader. Appelez sa -méthode load avec l'URL d'une -image et définissez la propriété map du matériau sur le résultat au lieu de définir sa color.

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load( 'resources/images/wall.jpg' );
-+texture.colorSpace = THREE.SRGBColorSpace;
-
-const material = new THREE.MeshBasicMaterial({
--  color: 0xFF8844,
-+  map: texture,
-});
-
-

Notez que nous utilisons MeshBasicMaterial, donc pas besoin de lumières.

-

- -

-

6 textures, une différente sur chaque face d'un cube

-

Que diriez-vous de 6 textures, une sur chaque face d'un cube ?

-
-
- - - -
-
- - - -
-
- -

Nous créons simplement 6 matériaux et les passons sous forme de tableau lorsque nous créons le Mesh

-
const loader = new THREE.TextureLoader();
--const texture = loader.load( 'resources/images/wall.jpg' );
--texture.colorSpace = THREE.SRGBColorSpace;
-
--const material = new THREE.MeshBasicMaterial({
--  map: texture,
--});
-+const materials = [
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-1.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-2.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-3.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-4.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-5.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-6.jpg')}),
-+];
--const cube = new THREE.Mesh(geometry, material);
-+const cube = new THREE.Mesh(geometry, materials);
-
-+function loadColorTexture( path ) {
-+  const texture = loader.load( path );
-+  texture.colorSpace = THREE.SRGBColorSpace;
-+  return texture;
-+}
-
-

Ça marche !

-

- -

-

Il convient de noter cependant que tous les types de géométrie ne supportent pas plusieurs -matériaux. BoxGeometry peut utiliser 6 matériaux, un pour chaque face. -ConeGeometry peut utiliser 2 matériaux, un pour le fond et un pour le cône. -CylinderGeometry peut utiliser 3 matériaux : fond, haut et côté. -Dans d'autres cas, vous devrez construire ou charger une géométrie personnalisée et/ou modifier les coordonnées de texture.

-

Il est beaucoup plus courant dans d'autres moteurs 3D et beaucoup plus performant d'utiliser un -atlas de textures -si vous souhaitez autoriser plusieurs images sur une seule géométrie. Un atlas de textures -est un endroit où vous placez plusieurs images dans une seule texture et utilisez ensuite les coordonnées de texture -sur les sommets de votre géométrie pour sélectionner quelles parties d'une texture sont utilisées -sur chaque triangle de votre géométrie.

-

Que sont les coordonnées de texture ? Ce sont des données ajoutées à chaque sommet d'une pièce de géométrie -qui spécifient quelle partie de la texture correspond à ce sommet spécifique. -Nous les aborderons lorsque nous commencerons à construire une géométrie personnalisée.

-

Chargement des textures

-

La manière simple

-

La plupart du code sur ce site utilise la méthode la plus simple pour charger des textures. -Nous créons un TextureLoader, puis appelons sa méthode load. -Cela renvoie un objet Texture.

-
const texture = loader.load('resources/images/flower-1.jpg');
-
-

Il est important de noter qu'en utilisant cette méthode, notre texture sera transparente jusqu'à -ce que l'image soit chargée de manière asynchrone par three.js, moment auquel elle mettra à jour la texture -avec l'image téléchargée.

-

Cela présente le grand avantage de ne pas avoir à attendre le chargement de la texture et notre -page commencera à s'afficher immédiatement. C'est probablement acceptable pour un grand nombre de cas d'utilisation -mais si nous le souhaitons, nous pouvons demander à three.js de nous informer lorsque la texture a fini de se télécharger.

-

Attendre le chargement d'une texture

-

Pour attendre le chargement d'une texture, la méthode load du chargeur de textures prend un rappel -qui sera appelé lorsque la texture aura fini de se charger. En reprenant notre premier exemple, -nous pouvons attendre le chargement de la texture avant de créer notre Mesh et de l'ajouter à la scène -comme ceci

-
const loader = new THREE.TextureLoader();
-loader.load('resources/images/wall.jpg', (texture) => {
-  texture.colorSpace = THREE.SRGBColorSpace;
-  const material = new THREE.MeshBasicMaterial({
-    map: texture,
-  });
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-});
-
-

À moins que vous ne vidiez le cache de votre navigateur et que vous ayez une connexion lente, il est peu probable -que vous voyiez une différence, mais soyez assuré qu'elle attend le chargement de la texture.

-

- -

-

Attendre le chargement de plusieurs textures

-

Pour attendre que toutes les textures soient chargées, vous pouvez utiliser un LoadingManager. Créez-en un -et passez-le au TextureLoader, puis définissez sa propriété onLoad -sur un rappel.

-
+const loadManager = new THREE.LoadingManager();
-*const loader = new THREE.TextureLoader(loadManager);
-
-const materials = [
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-1.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-2.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-3.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-4.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-5.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-6.jpg')}),
-];
-
-+loadManager.onLoad = () => {
-+  const cube = new THREE.Mesh(geometry, materials);
-+  scene.add(cube);
-+  cubes.push(cube);  // add to our list of cubes to rotate
-+};
-
-

Le LoadingManager a également une propriété onProgress -que nous pouvons définir sur un autre rappel pour afficher un indicateur de progression.

-

Nous allons d'abord ajouter une barre de progression en HTML

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="loading">
-+    <div class="progress"><div class="progressbar"></div></div>
-+  </div>
-</body>
-
-

et le CSS associé

-
#loading {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-}
-#loading .progress {
-    margin: 1.5em;
-    border: 1px solid white;
-    width: 50vw;
-}
-#loading .progressbar {
-    margin: 2px;
-    background: white;
-    height: 1em;
-    transform-origin: top left;
-    transform: scaleX(0);
-}
-
-

Ensuite, dans le code, nous mettrons à jour l'échelle de la progressbar dans notre rappel onProgress. Il est -appelé avec l'URL du dernier élément chargé, le nombre d'éléments chargés jusqu'à présent et le nombre total -d'éléments à charger.

-
+const loadingElem = document.querySelector('#loading');
-+const progressBarElem = loadingElem.querySelector('.progressbar');
-
-loadManager.onLoad = () => {
-+  loadingElem.style.display = 'none';
-  const cube = new THREE.Mesh(geometry, materials);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-};
-
-+loadManager.onProgress = (urlOfLastItemLoaded, itemsLoaded, itemsTotal) => {
-+  const progress = itemsLoaded / itemsTotal;
-+  progressBarElem.style.transform = `scaleX(${progress})`;
-+};
-
-

À moins que vous ne vidiez votre cache et que vous ayez une connexion lente, il est possible que vous ne voyiez -pas la barre de chargement.

-

- -

-

Charger des textures depuis d'autres origines

-

Pour utiliser des images provenant d'autres serveurs, ces serveurs doivent envoyer les en-têtes corrects. -S'ils ne le font pas, vous ne pouvez pas utiliser les images dans three.js et vous obtiendrez une erreur. -Si vous gérez le serveur fournissant les images, assurez-vous qu'il -envoie les en-têtes corrects. -Si vous ne contrôlez pas le serveur hébergeant les images et qu'il n'envoie pas les -en-têtes d'autorisation, vous ne pouvez pas utiliser les images de ce serveur.

-

Par exemple, imgur, flickr et -github envoient tous des en-têtes vous permettant d'utiliser les images -hébergées sur leurs serveurs dans three.js. La plupart des autres sites web ne le font pas.

-

Utilisation de la mémoire

-

Les textures sont souvent la partie d'une application three.js qui utilise le plus de mémoire. Il est important de comprendre -qu'en général, les textures prennent largeur * hauteur * 4 * 1.33 octets de mémoire.

-

Notez que cela ne dit rien sur la compression. Je peux créer une image .jpg et régler sa compression très élevée. -Par exemple, disons que je créais une scène d'une maison. À l'intérieur de la maison, il y a une table -et je décide de mettre cette texture de bois sur la surface supérieure de la table

-
- -

Cette image ne fait que 157k, elle se téléchargera donc relativement rapidement, mais sa taille est en réalité -de 3024 x 3761 pixels. -En suivant l'équation ci-dessus, cela donne

-
3024 * 3761 * 4 * 1.33 = 60505764.5
-

Cette image prendra 60 MÉGAOCTETS DE MÉMOIRE ! dans three.js. -Quelques textures comme celle-là et vous serez à court de mémoire.

-

Je soulève ce point car il est important de savoir que l'utilisation des textures a un coût caché. -Pour que three.js puisse utiliser la texture, il doit la transmettre au GPU, et le -GPU en général nécessite que les données de la texture soient décompressées.

-

La morale de l'histoire est de rendre vos textures petites en dimensions, pas seulement petites -en taille de fichier. Petite taille de fichier = téléchargement rapide. Petites dimensions = prend -moins de mémoire. Quelle taille devraient-elles avoir ? -Aussi petites que possible tout en conservant l'apparence dont vous avez besoin.

-

JPG vs PNG

-

C'est à peu près la même chose qu'en HTML classique : les JPG ont une compression avec perte, -les PNG ont une compression sans perte, donc les PNG sont généralement plus lents à télécharger. -Mais les PNG supportent la transparence. Les PNG sont également probablement le format -approprié pour les données non-image comme les normal maps et d'autres types de maps non-image que nous verrons plus tard.

-

Il est important de se rappeler qu'un JPG n'utilise -pas moins de mémoire qu'un PNG dans WebGL. Voir ci-dessus.

-

Filtrage et Mips

-

Appliquons cette texture 16x16

-
- -

À un cube

-
- -

Dessinons ce cube très petit

-
- -

Hmmm, je suppose que c'est difficile à voir. Agrandissons ce tout petit cube

-
- -

Comment le GPU sait-il quelles couleurs donner à chaque pixel qu'il dessine pour le petit cube ? -Que se passerait-il si le cube était si petit qu'il ne fasse qu'un ou deux pixels ?

-

C'est à cela que sert le filtrage.

-

Si c'était Photoshop, Photoshop ferait la moyenne de presque tous les pixels pour déterminer la couleur -à donner à ces 1 ou 2 pixels. Ce serait une opération très lente. Les GPU résolvent ce problème -en utilisant les mipmaps.

-

Les mips sont des copies de la texture, chacune faisant la moitié de la largeur et la moitié de la hauteur du mip précédent, -où les pixels ont été mélangés pour créer le mip suivant plus petit. Les mips sont créés -jusqu'à ce que l'on arrive à un mip de 1x1 pixel. Pour l'image ci-dessus, tous les mips ressembleraient -à ceci

-
- -

Maintenant, lorsque le cube est dessiné si petit qu'il ne fait qu'un ou deux pixels, le GPU peut choisir -d'utiliser uniquement le mip le plus petit ou le mip juste avant le plus petit pour décider de la couleur -à donner au petit cube.

-

Dans three.js, vous pouvez choisir ce qui se passe à la fois lorsque la texture est dessinée -plus grande que sa taille d'origine et ce qui se passe lorsqu'elle est dessinée plus petite que sa -taille d'origine.

-

Pour définir le filtre lorsque la texture est dessinée plus grande que sa taille d'origine, -vous définissez la propriété texture.magFilter sur THREE.NearestFilter ou - THREE.LinearFilter. NearestFilter signifie -simplement choisir le pixel unique le plus proche de la texture d'origine. Avec une texture -basse résolution, cela donne un aspect très pixélisé comme dans Minecraft.

-

LinearFilter signifie choisir les 4 pixels de la texture qui sont les plus proches -de l'endroit où nous devrions choisir une couleur et les mélanger dans les -proportions appropriées par rapport à la distance entre le point réel et -chacun des 4 pixels.

-
-
-
-
Plus proche
-
-
-
-
Linéaire
-
-
- -

Pour définir le filtre lorsque la texture est dessinée plus petite que sa taille d'origine, -vous définissez la propriété texture.minFilter sur l'une des 6 valeurs suivantes.

-
    -
  • THREE.NearestFilter

    -

    identique à ci-dessus, choisir le pixel le plus proche dans la texture

    -
  • -
  • THREE.LinearFilter

    -

    identique à ci-dessus, choisir 4 pixels de la texture et les mélanger

    -
  • -
  • THREE.NearestMipmapNearestFilter

    -

    choisir le mip approprié puis choisir un pixel

    -
  • -
  • THREE.NearestMipmapLinearFilter

    -

    choisir 2 mips, choisir un pixel de chaque, mélanger les 2 pixels

    -
  • -
  • THREE.LinearMipmapNearestFilter

    -

    choisir le mip approprié puis choisir 4 pixels et les mélanger

    -
  • -
  • THREE.LinearMipmapLinearFilter

    -

    choisir 2 mips, choisir 4 pixels de chaque et mélanger les 8 en 1 pixel

    -
  • -
-

Voici un exemple montrant les 6 paramètres

-
-
-
-
cliquer pour
changer la
texture
-
-
plus proche
-
linéaire
-
plus proche
mipmap
plus proche
-
plus proche
mipmap
linéaire
-
linéaire
mipmap
plus proche
-
linéaire
mipmap
linéaire
-
-
- -

Une chose à remarquer est que le coin supérieur gauche et le milieu supérieur utilisant NearestFilter et LinearFilter -n'utilisent pas les mips. De ce fait, ils scintillent au loin car le GPU sélectionne -des pixels de la texture d'origine. À gauche, un seul pixel est choisi et -au milieu, 4 sont choisis et mélangés, mais ce n'est pas suffisant pour obtenir une bonne -couleur représentative. Les 4 autres bandes s'en sortent mieux, -celle en bas à droite, LinearMipmapLinearFilter, étant la meilleure.

-

Si vous cliquez sur l'image ci-dessus, elle basculera entre la texture que nous avons utilisée ci-dessus -et une texture où chaque niveau de mip est d'une couleur différente.

-
-
-
- -

Cela rend plus clair -ce qui se passe. Vous pouvez voir en haut à gauche et au milieu supérieur que le premier mip est utilisé jusqu'au loin. -En haut à droite et au milieu inférieur, vous pouvez clairement voir où un mip différent -est utilisé.

-

En revenant à la texture d'origine, vous pouvez voir que celle en bas à droite est la plus lisse, -de la plus haute qualité. Vous pourriez vous demander pourquoi ne pas toujours utiliser ce mode. La raison -la plus évidente est que parfois vous voulez que les choses soient pixélisées pour un look rétro ou pour une autre raison. -La raison suivante la plus courante est que lire 8 pixels et les mélanger est plus lent -que de lire 1 pixel et de le mélanger. Bien qu'il soit peu probable qu'une seule texture -fasse la différence entre rapide et lent, à mesure que nous progresserons dans ces articles, -nous aurons finalement des matériaux qui utilisent 4 ou 5 textures en même temps. -4 textures * 8 pixels par texture, c'est rechercher 32 pixels pour chaque pixel rendu. -Cela peut être particulièrement important à considérer sur les appareils mobiles.

-

Répétition, décalage, rotation, habillage d'une texture

-

Les textures ont des paramètres pour la répétition, le décalage et la rotation d'une texture.

-

Par défaut, les textures dans three.js ne se répètent pas. Pour définir si une -texture se répète ou non, il existe 2 propriétés : wrapS pour l'habillage horizontal -et wrapT pour l'habillage vertical.

-

Ils peuvent être définis sur l'une des valeurs suivantes :

-
    -
  • THREE.ClampToEdgeWrapping

    -

    le dernier pixel sur chaque bord est répété indéfiniment

    -
  • -
  • THREE.RepeatWrapping

    -

    la texture est répétée

    -
  • -
  • THREE.MirroredRepeatWrapping

    -

    la texture est mise en miroir et répétée

    -
  • -
-

Par exemple, pour activer l'habillage dans les deux directions :

-
someTexture.wrapS = THREE.RepeatWrapping;
-someTexture.wrapT = THREE.RepeatWrapping;
-
-

La répétition est définie avec la propriété [repeat] repeat.

-
const timesToRepeatHorizontally = 4;
-const timesToRepeatVertically = 2;
-someTexture.repeat.set(timesToRepeatHorizontally, timesToRepeatVertically);
-
-

Le décalage de la texture peut être effectué en définissant la propriété offset. Les textures -sont décalées avec des unités où 1 unité = 1 taille de texture. Autrement dit, 0 = pas de décalage -et 1 = décalage d'une quantité de texture complète.

-
const xOffset = .5;   // offset by half the texture
-const yOffset = .25;  // offset by 1/4 the texture
-someTexture.offset.set(xOffset, yOffset);
-
-

La rotation de la texture peut être définie en définissant la propriété rotation en radians -ainsi que la propriété center pour choisir le centre de rotation. -Elle est par défaut à 0,0, ce qui correspond à une rotation depuis le coin inférieur gauche. Comme pour le décalage, -ces unités sont en taille de texture, donc les définir à .5, .5 effectuerait une rotation -autour du centre de la texture.

-
someTexture.center.set(.5, .5);
-someTexture.rotation = THREE.MathUtils.degToRad(45);
-
-

Modifions l'exemple du haut ci-dessus pour jouer avec ces valeurs

-

Tout d'abord, nous allons conserver une référence à la texture afin de pouvoir la manipuler

-
+const texture = loader.load('resources/images/wall.jpg');
-const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg');
-+  map: texture,
-});
-
-

Ensuite, nous utiliserons à nouveau lil-gui pour fournir une interface simple.

-
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

Comme nous l'avons fait dans les exemples précédents avec lil-gui, nous utiliserons une classe simple pour -donner à lil-gui un objet qu'il peut manipuler en degrés -mais qui définira une propriété en radians.

-
class DegRadHelper {
-  constructor(obj, prop) {
-    this.obj = obj;
-    this.prop = prop;
-  }
-  get value() {
-    return THREE.MathUtils.radToDeg(this.obj[this.prop]);
-  }
-  set value(v) {
-    this.obj[this.prop] = THREE.MathUtils.degToRad(v);
-  }
-}
-
-

Nous avons également besoin d'une classe qui convertira une chaîne de caractères comme "123" en un -nombre comme 123, car three.js nécessite des nombres pour les paramètres d'énumération -comme wrapS et wrapT, mais lil-gui n'utilise que des chaînes de caractères pour les énumérations.

-
class StringToNumberHelper {
-  constructor(obj, prop) {
-    this.obj = obj;
-    this.prop = prop;
-  }
-  get value() {
-    return this.obj[this.prop];
-  }
-  set value(v) {
-    this.obj[this.prop] = parseFloat(v);
-  }
-}
-
-

En utilisant ces classes, nous pouvons configurer une interface graphique simple pour les paramètres ci-dessus

-
const wrapModes = {
-  'ClampToEdgeWrapping': THREE.ClampToEdgeWrapping,
-  'RepeatWrapping': THREE.RepeatWrapping,
-  'MirroredRepeatWrapping': THREE.MirroredRepeatWrapping,
-};
-
-function updateTexture() {
-  texture.needsUpdate = true;
-}
-
-const gui = new GUI();
-gui.add(new StringToNumberHelper(texture, 'wrapS'), 'value', wrapModes)
-  .name('texture.wrapS')
-  .onChange(updateTexture);
-gui.add(new StringToNumberHelper(texture, 'wrapT'), 'value', wrapModes)
-  .name('texture.wrapT')
-  .onChange(updateTexture);
-gui.add(texture.repeat, 'x', 0, 5, .01).name('texture.repeat.x');
-gui.add(texture.repeat, 'y', 0, 5, .01).name('texture.repeat.y');
-gui.add(texture.offset, 'x', -2, 2, .01).name('texture.offset.x');
-gui.add(texture.offset, 'y', -2, 2, .01).name('texture.offset.y');
-gui.add(texture.center, 'x', -.5, 1.5, .01).name('texture.center.x');
-gui.add(texture.center, 'y', -.5, 1.5, .01).name('texture.center.y');
-gui.add(new DegRadHelper(texture, 'rotation'), 'value', -360, 360)
-  .name('texture.rotation');
-
-

La dernière chose à noter à propos de l'exemple est que si vous changez wrapS ou -wrapT sur la texture, vous devez également définir texture.needsUpdate -afin que three.js sache qu'il doit appliquer ces paramètres. Les autres paramètres sont appliqués automatiquement.

-

- -

-

Ce n'est qu'une étape dans le sujet des textures. À un moment donné, nous aborderons -les coordonnées de texture ainsi que 9 autres types de textures qui peuvent être appliqués -aux matériaux.

-

Pour l'instant, passons aux lumières.

- -

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/tips.html b/manual/fr/tips.html deleted file mode 100644 index 5f025d7f6cca1c..00000000000000 --- a/manual/fr/tips.html +++ /dev/null @@ -1,344 +0,0 @@ - - - Conseils - - - - - - - - - - - - - -
-
-

Conseils

-
-
-
-

Cet article est une collection de petits problèmes que vous pourriez rencontrer -en utilisant three.js, qui semblaient trop mineurs pour avoir leur propre article.

-
-

-

Faire une capture d'écran du Canvas

-

Dans le navigateur, il y a effectivement 2 fonctions qui permettent de prendre une capture d'écran. -L'ancienne -canvas.toDataURL -et la nouvelle, meilleure, -canvas.toBlob

-

On pourrait donc penser qu'il serait facile de prendre une capture d'écran en ajoutant simplement du code comme

-
<canvas id="c"></canvas>
-+<button id="screenshot" type="button">Enregistrer...</button>
-
-
const elem = document.querySelector('#screenshot');
-elem.addEventListener('click', () => {
-  canvas.toBlob((blob) => {
-    saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`);
-  });
-});
-
-const saveBlob = (function() {
-  const a = document.createElement('a');
-  document.body.appendChild(a);
-  a.style.display = 'none';
-  return function saveData(blob, fileName) {
-     const url = window.URL.createObjectURL(blob);
-     a.href = url;
-     a.download = fileName;
-     a.click();
-  };
-}());
-
-

Voici l'exemple de l'article sur la réactivité -avec le code ci-dessus ajouté et un peu de CSS pour positionner le bouton

-

- -

-

Lorsque je l'ai essayé, j'ai obtenu cette capture d'écran

-
- -

Oui, c'est juste une image noire.

-

Il est possible que cela ait fonctionné pour vous selon votre navigateur/OS mais en général, -il est peu probable que cela fonctionne.

-

Le problème est que, pour des raisons de performance et de compatibilité, par défaut, le navigateur -efface le buffer de dessin d'un canvas WebGL après y avoir dessiné.

-

La solution est d'appeler votre code de rendu juste avant la capture.

-

Dans notre code, nous devons ajuster quelques éléments. D'abord, séparons -le code de rendu.

-
+const state = {
-+  time: 0,
-+};
-
--function render(time) {
--  time *= 0.001;
-+function render() {
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
--    const rot = time * speed;
-+    const rot = state.time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
-+function animate(time) {
-+  state.time = time * 0.001;
-+
-+  render();
-+
-+  requestAnimationFrame(animate);
-+}
-+requestAnimationFrame(animate);
-
-

Maintenant que render ne s'occupe que du rendu effectif, -nous pouvons l'appeler juste avant de capturer le canvas.

-
const elem = document.querySelector('#screenshot');
-elem.addEventListener('click', () => {
-+  render();
-  canvas.toBlob((blob) => {
-    saveBlob(blob, `screencapture-${canvas.width}x-${canvas.height}.png`);
-  });
-});
-
-

Et maintenant, ça devrait marcher.

-

- -

-

Pour une solution différente, voir l'élément suivant.

-
-

-

Empêcher l'effacement du canvas

-

Supposons que vous vouliez permettre à l'utilisateur de peindre avec un objet -animé. Vous devez passer preserveDrawingBuffer: true lorsque -vous créez le WebGLRenderer. Cela empêche le navigateur d'effacer -le canvas. Vous devez également dire à three.js de ne pas effacer -le canvas.

-
const canvas = document.querySelector('#c');
--const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  canvas,
-+  preserveDrawingBuffer: true,
-+  alpha: true,
-+});
-+renderer.autoClearColor = false;
-
-

- -

-

Notez que si vous étiez sérieux au sujet de la création d'un programme de dessin, ce ne serait pas une -solution car le navigateur effacera toujours le canvas chaque fois que sa -résolution change. Nous modifions sa résolution en fonction de sa taille d'affichage. Sa taille d'affichage -change lorsque la fenêtre change de taille. Cela inclut lorsque l'utilisateur télécharge -un fichier, même dans un autre onglet, et que le navigateur ajoute une barre d'état. Cela inclut également lorsque -l'utilisateur tourne son téléphone et que le navigateur passe du mode portrait au mode paysage.

-

Si vous vouliez vraiment créer un programme de dessin, vous devriez -faire le rendu sur une texture en utilisant une cible de rendu.

-
-

-

Obtenir la saisie clavier

-

Tout au long de ces tutoriels, nous avons souvent attaché des écouteurs d'événements au canvas. -Bien que de nombreux événements fonctionnent, un qui ne fonctionne pas par défaut est l'événement -clavier.

-

Pour obtenir les événements clavier, définissez le tabindex -du canvas à 0 ou plus. Par exemple :

-
<canvas tabindex="0"></canvas>
-
-

Cela finit cependant par causer un nouveau problème. Tout élément ayant un tabindex défini -sera mis en évidence lorsqu'il aura le focus. Pour résoudre ce problème, définissez son contour de focus CSS -à none (aucun)

-
canvas:focus {
-  outline:none;
-}
-
-

Pour démontrer, voici 3 canvas

-
<canvas id="c1"></canvas>
-<canvas id="c2" tabindex="0"></canvas>
-<canvas id="c3" tabindex="1"></canvas>
-
-

et un peu de css juste pour le dernier canvas

-
#c3:focus {
-    outline: none;
-}
-
-

Notez que vous ne pouvez pas faire en sorte que le premier canvas accepte les saisies clavier. -Le deuxième canvas le peut, mais il est mis en évidence. Le 3ème -canvas a les deux solutions appliquées.

-

- -

-
-

-

Rendre le Canvas Transparent

-

Par défaut, THREE.js rend le canvas opaque. Si vous voulez que le -canvas soit transparent, passez alpha:true lorsque vous créez -le WebGLRenderer

-
const canvas = document.querySelector('#c');
--const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  canvas,
-+  alpha: true,
-+});
-
-

Vous voudrez probablement aussi lui dire que vos résultats n'utilisent pas l'alpha prémultiplié

-
const canvas = document.querySelector('#c');
-const renderer = new THREE.WebGLRenderer({
-  canvas,
-  alpha: true,
-+  premultipliedAlpha: false,
-});
-
-

Three.js utilise par défaut premultipliedAlpha: true pour le canvas, -mais par défaut, les matériaux génèrent premultipliedAlpha: false.

-

Si vous souhaitez mieux comprendre quand utiliser ou non l'alpha prémultiplié, -voici un bon article à ce sujet.

-

En tout cas, configurons un exemple simple avec un canvas transparent.

-

Nous avons appliqué les paramètres ci-dessus à l'exemple de l'article sur la réactivité. -Rendons également les matériaux plus transparents.

-
function makeInstance(geometry, color, x) {
--  const material = new THREE.MeshPhongMaterial({color});
-+  const material = new THREE.MeshPhongMaterial({
-+    color,
-+    opacity: 0.5,
-+  });
-
-...
-
-

Et ajoutons un peu de contenu HTML

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="content">
-+    <div>
-+      <h1>Cubes-R-Us !</h1>
-+      <p>Nous fabriquons les meilleurs cubes !</p>
-+    </div>
-+  </div>
-</body>
-
-

ainsi qu'un peu de CSS pour placer le canvas devant

-
body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-+    position: fixed;
-+    left: 0;
-+    top: 0;
-+    z-index: 2;
-+    pointer-events: none;
-}
-+#content {
-+  font-size: 7vw;
-+  font-family: sans-serif;
-+  text-align: center;
-+  width: 100%;
-+  height: 100%;
-+  display: flex;
-+  justify-content: center;
-+  align-items: center;
-+}
-
-

Notez que pointer-events: none rend le canvas invisible aux événements de souris -et tactiles afin que vous puissiez sélectionner le texte en dessous.

-

- -

-
-

-

Faire de votre arrière-plan une animation three.js

-

Une question courante est de savoir comment faire en sorte qu'une animation three.js serve d'arrière-plan à -une page web.

-

Il y a 2 façons évidentes.

-
    -
  • Définir la propriété CSS position du canvas sur fixed comme dans
  • -
-
#c {
- position: fixed;
- left: 0;
- top: 0;
- ...
-}
-
-

Vous pouvez voir cette solution exacte dans l'exemple précédent. Il suffit de définir z-index à -1 -et les cubes apparaîtront derrière le texte.

-

Un petit inconvénient de cette solution est que votre JavaScript doit s'intégrer à la page -et si vous avez une page complexe, vous devez vous assurer qu'aucun des scripts JavaScript de votre -visualisation three.js n'entre en conflit avec le JavaScript effectuant d'autres tâches dans la page.

-
    -
  • Utiliser une iframe
  • -
-

C'est la solution utilisée sur la page d'accueil de ce site.

-

Dans votre page web, insérez simplement une iframe, par exemple :

-
<iframe id="background" src="responsive.html">
-<div>
-  Votre contenu ici.
-</div>
-
-

Ensuite, stylisez l'iframe pour qu'elle remplisse la fenêtre et soit en arrière-plan, -ce qui est essentiellement le même code que nous avons utilisé ci-dessus pour le canvas, -sauf que nous devons également définir border à none car les iframes ont -une bordure par défaut.

-
#background {
-    position: fixed;
-    width: 100%;
-    height: 100%;
-    left: 0;
-    top: 0;
-    z-index: -1;
-    border: none;
-    pointer-events: none;
-}
-

- -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/transparency.html b/manual/fr/transparency.html deleted file mode 100644 index ff4420a9f94ae0..00000000000000 --- a/manual/fr/transparency.html +++ /dev/null @@ -1,401 +0,0 @@ - - - Transparence - - - - - - - - - - - - - -
-
-

Transparence

-
-
-
-

La transparence dans three.js est à la fois facile et difficile.

-

Nous allons d'abord aborder la partie facile. Créons une -scène avec 8 cubes placés sur une grille 2x2x2.

-

Nous allons commencer par l'exemple de -l'article sur le rendu à la demande -qui contenait 3 cubes et le modifier pour en avoir 8. Modifions d'abord notre -fonction makeInstance pour qu'elle prenne -x, y et z

-
-function makeInstance(geometry, color) {
-+function makeInstance(geometry, color, x, y, z) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
--  cube.position.x = x;
-+  cube.position.set(x, y, z);
-
-  return cube;
-}
-
-

Ensuite, nous pouvons créer 8 cubes.

-
+function hsl(h, s, l) {
-+  return (new THREE.Color()).setHSL(h, s, l);
-+}
-
--makeInstance(geometry, 0x44aa88,  0);
--makeInstance(geometry, 0x8844aa, -2);
--makeInstance(geometry, 0xaa8844,  2);
-
-+{
-+  const d = 0.8;
-+  makeInstance(geometry, hsl(0 / 8, 1, .5), -d, -d, -d);
-+  makeInstance(geometry, hsl(1 / 8, 1, .5),  d, -d, -d);
-+  makeInstance(geometry, hsl(2 / 8, 1, .5), -d,  d, -d);
-+  makeInstance(geometry, hsl(3 / 8, 1, .5),  d,  d, -d);
-+  makeInstance(geometry, hsl(4 / 8, 1, .5), -d, -d,  d);
-+  makeInstance(geometry, hsl(5 / 8, 1, .5),  d, -d,  d);
-+  makeInstance(geometry, hsl(6 / 8, 1, .5), -d,  d,  d);
-+  makeInstance(geometry, hsl(7 / 8, 1, .5),  d,  d,  d);
-+}
-
-

J'ai aussi ajusté la caméra.

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 25;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 4;
-+camera.position.z = 2;
-
-

Définissez le fond en blanc.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-

Et ajouté une deuxième lumière pour que toutes les faces des cubes reçoivent de l'éclairage.

-
-{
-+function addLight(...pos) {
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
--  light.position.set(-1, 2, 4);
-+  light.position.set(...pos);
-  scene.add(light);
-}
-+addLight(-1, 2, 4);
-+addLight( 1, -1, -2);
-
-

Pour rendre les cubes transparents, il suffit de définir le -drapeau transparent et de définir un -niveau d'opacity, 1 étant complètement opaque -et 0 étant complètement transparent.

-
function makeInstance(geometry, color, x, y, z) {
--  const material = new THREE.MeshPhongMaterial({color});
-+  const material = new THREE.MeshPhongMaterial({
-+    color,
-+    opacity: 0.5,
-+    transparent: true,
-+  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.set(x, y, z);
-
-  return cube;
-}
-
-

et avec cela, nous obtenons 8 cubes transparents.

-

- -

-

Faites glisser sur l'exemple pour faire pivoter la vue.

-

Cela semble donc facile mais... regardez de plus près. Les cubes n'ont pas -de faces arrière.

-
-
pas de faces arrière
- -

Nous avons découvert la propriété de matériau side dans -l'article sur les matériaux. -Définissons-la donc sur THREE.DoubleSide pour que les deux faces de chaque cube soient dessinées.

-
const material = new THREE.MeshPhongMaterial({
-  color,
-  map: loader.load(url),
-  opacity: 0.5,
-  transparent: true,
-+  side: THREE.DoubleSide,
-});
-
-

Et nous obtenons

-

- -

-

Faites-le tourner. Cela semble fonctionner car nous pouvons voir les faces arrière, -sauf qu'en y regardant de plus près, parfois ce n'est pas le cas.

-
-
la face arrière gauche de chaque cube est manquante
- -

Cela se produit en raison de la manière dont les objets 3D sont généralement dessinés. Pour chaque géométrie, -chaque triangle est dessiné un par un. Lorsque chaque pixel du triangle est dessiné, -2 choses sont enregistrées. Premièrement, la couleur de ce pixel, et deuxièmement, la profondeur de ce pixel. -Lorsque le triangle suivant est dessiné, pour chaque pixel, si la profondeur est plus importante que la -profondeur précédemment enregistrée, aucun pixel n'est dessiné.

-

Cela fonctionne très bien pour les objets opaques, mais échoue pour les objets transparents.

-

La solution consiste à trier les objets transparents et à dessiner ceux situés à l'arrière avant -de dessiner ceux à l'avant. THREE.js le fait pour les objets comme les Mesh, -sinon le tout premier exemple aurait échoué entre les cubes, certains cubes bloquant les autres. -Malheureusement, pour les triangles individuels, le tri serait extrêmement lent.

-

Le cube a 12 triangles, 2 pour chaque face, et l'ordre dans lequel ils sont dessinés est -le même que celui dans lequel ils sont construits dans la géométrie. -Ainsi, selon la direction dans laquelle nous regardons, les triangles les plus proches de la caméra -peuvent être dessinés en premier. Dans ce cas, les triangles à l'arrière ne sont pas dessinés. -C'est pourquoi parfois nous ne voyons pas les faces arrière.

-

Pour un objet convexe comme une sphère ou un cube, une sorte de solution consiste à ajouter -chaque cube à la scène deux fois. Une fois avec un matériau qui dessine -uniquement les triangles orientés vers l'arrière, et une autre fois avec un matériau qui dessine uniquement -les triangles orientés vers l'avant.

-
function makeInstance(geometry, color, x, y, z) {
-+  [THREE.BackSide, THREE.FrontSide].forEach((side) => {
-    const material = new THREE.MeshPhongMaterial({
-      color,
-      opacity: 0.5,
-      transparent: true,
-+      side,
-    });
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.set(x, y, z);
-+  });
-}
-
-

Et avec cela, cela semble fonctionner.

-

- -

-

Cela suppose que le tri de three.js est stable. C'est-à-dire que parce que nous -avons ajouté le mesh side: THREE.BackSide en premier et parce qu'il est exactement à la même -position, il sera dessiné avant le mesh side: THREE.FrontSide.

-

Créons 2 plans qui se croisent (après avoir supprimé tout le code relatif aux cubes). -Nous allons ajouter une texture à chaque plan.

-
const planeWidth = 1;
-const planeHeight = 1;
-const geometry = new THREE.PlaneGeometry(planeWidth, planeHeight);
-
-const loader = new THREE.TextureLoader();
-
-function makeInstance(geometry, color, rotY, url) {
-  const texture = loader.load(url, render);
-  const material = new THREE.MeshPhongMaterial({
-    color,
-    map: texture,
-    opacity: 0.5,
-    transparent: true,
-    side: THREE.DoubleSide,
-  });
-
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-
-  mesh.rotation.y = rotY;
-}
-
-makeInstance(geometry, 'pink',       0,             'resources/images/happyface.png');
-makeInstance(geometry, 'lightblue',  Math.PI * 0.5, 'resources/images/hmmmface.png');
-
-

Cette fois, nous pouvons utiliser side: THREE.DoubleSide car nous ne pouvons jamais voir qu'une -seule face d'un plan à la fois. Notez également que nous passons notre fonction render à la fonction de chargement de texture -afin que lorsque la texture a fini de charger, nous rendions à nouveau la scène. -C'est parce que cet exemple effectue un rendu à la demande -au lieu d'un rendu continu.

-

- -

-

Et encore une fois, nous voyons un problème similaire.

-
-
la moitié d'une face est manquante
- -

La solution ici est de diviser manuellement chaque plan en 2 plans -afin qu'il n'y ait réellement aucune intersection.

-
function makeInstance(geometry, color, rotY, url) {
-+  const base = new THREE.Object3D();
-+  scene.add(base);
-+  base.rotation.y = rotY;
-
-+  [-1, 1].forEach((x) => {
-    const texture = loader.load(url, render);
-+    texture.offset.x = x < 0 ? 0 : 0.5;
-+    texture.repeat.x = .5;
-    const material = new THREE.MeshPhongMaterial({
-      color,
-      map: texture,
-      opacity: 0.5,
-      transparent: true,
-      side: THREE.DoubleSide,
-    });
-
-    const mesh = new THREE.Mesh(geometry, material);
--    scene.add(mesh);
-+    base.add(mesh);
-
--    mesh.rotation.y = rotY;
-+    mesh.position.x = x * .25;
-  });
-}
-
-

La manière d'y parvenir dépend de vous. Si j'utilisais un logiciel de modélisation comme -Blender, je le ferais probablement manuellement en ajustant -les coordonnées de texture. Ici cependant, nous utilisons PlaneGeometry qui, par défaut, -étire la texture sur tout le plan. Comme nous l'avons vu précédemment, -en définissant texture.repeat -et texture.offset, nous pouvons mettre à l'échelle et déplacer la texture pour obtenir -la bonne moitié de la texture de face sur chaque plan.

-

Le code ci-dessus crée également un Object3D et lui attache les 2 plans en tant qu'enfants. -Il semblait plus facile de faire pivoter un Object3D parent que de faire les calculs nécessaires -pour le faire sans.

-

- -

-

Cette solution ne fonctionne vraiment que pour des choses simples comme 2 plans dont -la position d'intersection ne change pas.

-

Pour les objets texturés, une autre solution consiste à définir un test alpha.

-

Un test alpha est un niveau d'alpha en dessous duquel three.js ne dessinera pas -le pixel. Si nous ne dessinons pas du tout un pixel, alors les problèmes de profondeur -mentionnés ci-dessus disparaissent. Pour les textures aux bords relativement nets, -cela fonctionne assez bien. Les exemples incluent les textures de feuilles sur une plante ou un arbre, -ou souvent une parcelle d'herbe.

-

Essayons sur les 2 plans. Utilisons d'abord des textures différentes. -Les textures ci-dessus étaient 100% opaques. Ces 2 utilisent la transparence.

-
-
-
-
- -

Retournons aux 2 plans qui se croisent (avant de les diviser) et utilisons -ces textures et définissons un alphaTest.

-
function makeInstance(geometry, color, rotY, url) {
-  const texture = loader.load(url, render);
-  const material = new THREE.MeshPhongMaterial({
-    color,
-    map: texture,
--    opacity: 0.5,
-    transparent: true,
-+    alphaTest: 0.5,
-    side: THREE.DoubleSide,
-  });
-
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-
-  mesh.rotation.y = rotY;
-}
-
--makeInstance(geometry, 'pink',       0,             'resources/images/happyface.png');
--makeInstance(geometry, 'lightblue',  Math.PI * 0.5, 'resources/images/hmmmface.png');
-+makeInstance(geometry, 'white', 0,             'resources/images/tree-01.png');
-+makeInstance(geometry, 'white', Math.PI * 0.5, 'resources/images/tree-02.png');
-
-

Avant d'exécuter cela, ajoutons une petite interface utilisateur pour pouvoir jouer plus facilement avec les paramètres alphaTest -et transparent. Nous utiliserons lil-gui comme nous l'avons présenté -dans l'article sur le graphe de scène de three.js.

-

Nous allons d'abord créer une aide pour lil-gui qui définit une valeur pour chaque matériau de la scène.

-
class AllMaterialPropertyGUIHelper {
-  constructor(prop, scene) {
-    this.prop = prop;
-    this.scene = scene;
-  }
-  get value() {
-    const {scene, prop} = this;
-    let v;
-    scene.traverse((obj) => {
-      if (obj.material && obj.material[prop] !== undefined) {
-        v = obj.material[prop];
-      }
-    });
-    return v;
-  }
-  set value(v) {
-    const {scene, prop} = this;
-    scene.traverse((obj) => {
-      if (obj.material && obj.material[prop] !== undefined) {
-        obj.material[prop] = v;
-        obj.material.needsUpdate = true;
-      }
-    });
-  }
-}
-
-

Ensuite, nous allons ajouter l'interface graphique.

-
const gui = new GUI();
-gui.add(new AllMaterialPropertyGUIHelper('alphaTest', scene), 'value', 0, 1)
-    .name('alphaTest')
-    .onChange(requestRenderIfNotRequested);
-gui.add(new AllMaterialPropertyGUIHelper('transparent', scene), 'value')
-    .name('transparent')
-    .onChange(requestRenderIfNotRequested);
-
-

et bien sûr, nous devons inclure lil-gui.

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

et voici les résultats.

-

- -

-

Vous pouvez voir que cela fonctionne, mais zoomez et vous verrez qu'un plan a des lignes blanches.

-
- -

C'est le même problème de profondeur qu'auparavant. Ce plan a été dessiné en premier, -donc le plan situé derrière n'est pas dessiné. Il n'y a pas de solution parfaite. -Ajustez l'alphaTest et/ou désactivez transparent pour trouver une solution -qui correspond à votre cas d'utilisation.

-

La conclusion de cet article est que la transparence parfaite est difficile. -Il y a des problèmes, des compromis et des solutions de contournement.

-

Par exemple, disons que vous avez une voiture. -Les voitures ont généralement des pare-brise sur les 4 côtés. Si vous voulez éviter les problèmes de tri -ci-dessus, vous devrez faire de chaque fenêtre son propre objet afin que three.js puisse -trier les fenêtres et les dessiner dans le bon ordre.

-

Si vous créez des plantes ou de l'herbe, la solution du test alpha est courante.

-

La solution que vous choisissez dépend de vos besoins.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/uniform-types.html b/manual/fr/uniform-types.html deleted file mode 100644 index 1f511b7abb58c9..00000000000000 --- a/manual/fr/uniform-types.html +++ /dev/null @@ -1,254 +0,0 @@ - - - Types d'uniformes - - - - - - - - - - - - - -
-
-

Types d'uniformes

-
-
-
- -

- Chaque uniforme doit avoir une propriété `value`. Le type de la valeur doit - correspondre au type de la variable uniforme dans le code GLSL tel que - spécifié pour les types GLSL primitifs dans le tableau ci-dessous. Les structures et - tableaux d'uniformes sont également pris en charge. Les tableaux GLSL de type primitif - doivent être spécifiés soit comme un tableau des objets THREE correspondants, soit - comme un tableau plat contenant les données de tous les objets. En d'autres termes, - les primitives GLSL dans les tableaux ne doivent pas être représentées par des tableaux. Cette règle - ne s'applique pas de manière transitive. Un tableau de tableaux `vec2`, chacun d'une longueur - de cinq vecteurs, doit être un tableau de tableaux, soit de cinq objets `Vector2`, - soit de dix `number`s. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GLSL typeJavaScript type
intNumber
uintNumber
floatNumber
boolBoolean
boolNumber
vec2Vector2
vec2Float32Array (*)
vec2Array (*)
vec3Vector3
vec3Color
vec3Float32Array (*)
vec3Array (*)
vec4Vector4
vec4Quaternion
vec4Float32Array (*)
vec4Array (*)
mat2Float32Array (*)
mat2Array (*)
mat3Matrix3
mat3Float32Array (*)
mat3Array (*)
mat4Matrix4
mat4Float32Array (*)
mat4Array (*)
ivec2, bvec2Float32Array (*)
ivec2, bvec2Array (*)
ivec3, bvec3Int32Array (*)
ivec3, bvec3Array (*)
ivec4, bvec4Int32Array (*)
ivec4, bvec4Array (*)
sampler2DTexture
samplerCubeCubeTexture
- -

- (*) De même pour un tableau (le plus interne) (dimension) du même type GLSL, - contenant les composants de tous les vecteurs ou matrices du tableau. -

- -

Uniforms structurés

- -

- Parfois, vous voulez organiser les uniformes en tant que `structs` dans votre code de shader. - Le style suivant doit être utilisé pour que `three.js` puisse traiter - les données d'uniformes structurées. -

-
-uniforms = {
-  data: { 
-    value: {
-      position: new Vector3(), 
-      direction: new Vector3( 0, 0, 1 ) 
-    } 
-  } 
-};
-
- Cette définition peut être mappée sur le code GLSL suivant : -
-struct Data { 
-  vec3 position;
-  vec3 direction;
-};
-uniform Data data;
-
- -

Uniforms structurés avec tableaux

- -

- Il est également possible de gérer des `structs` dans des tableaux. La syntaxe pour ce cas d'utilisation - est la suivante : -

-
-const entry1 = {
-  position: new Vector3(),
-  direction: new Vector3( 0, 0, 1 )
-};
-const entry2 = {
-  position: new Vector3( 1, 1, 1 ),
-  direction: new Vector3( 0, 1, 0 )
-};
-
-uniforms = {
-  data: {
-    value: [ entry1, entry2 ]
-  }
-};
-
- Cette définition peut être mappée sur le code GLSL suivant : -
-struct Data { 
-  vec3 position; 
-  vec3 direction; 
-};
-uniform Data data[ 2 ];
-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/useful-links.html b/manual/fr/useful-links.html deleted file mode 100644 index 61ea23177180f2..00000000000000 --- a/manual/fr/useful-links.html +++ /dev/null @@ -1,193 +0,0 @@ - - - Liens utiles - - - - - - - - - - - - - -
-
-

Liens utiles

-
-
-
- -

- Voici une collection de liens qui pourraient vous être utiles pour apprendre three.js.
- Si vous trouvez quelque chose que vous aimeriez ajouter ici, ou si vous pensez que l'un des liens ci-dessous n'est plus pertinent ou ne fonctionne plus, n'hésitez pas à cliquer sur le bouton 'edit' en bas à droite et à apporter des modifications !

- - Notez également qu'étant donné que three.js est en développement rapide, de nombreux liens contiendront des informations obsolètes. Si quelque chose ne fonctionne pas comme prévu ou comme l'indique l'un de ces liens, vérifiez la console du navigateur pour les avertissements ou les erreurs. Consultez également les pages de documentation pertinentes. -

- -

Forums d'aide

-

- Three.js utilise officiellement le [link:https://discourse.threejs.org/ forum] et [link:http://stackoverflow.com/tags/three.js/info Stack Overflow] pour les demandes d'aide. - Si vous avez besoin d'aide pour quelque chose, c'est l'endroit où aller. NE PAS ouvrir de problème sur Github pour les demandes d'aide. -

- -

Tutoriels et cours

- -

Pour commencer avec three.js

-
    -
  • - [link:https://threejs.org/manual/#en/fundamentals Leçon d'introduction aux Fondamentaux de Three.js] -
  • -
  • - [link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Pour commencer avec la 3D WebGL] par [link:https://codepen.io/rachsmith/ Rachel Smith]. -
  • -
  • - [link:https://www.august.com.au/blog/animating-scenes-with-webgl-three-js/ Animer des scènes avec WebGL et three.js] -
  • -
- -

Articles et cours plus approfondis / avancés

-
    -
  • - [link:https://threejs-journey.com/ Three Journey] Cours par [link:https://bruno-simon.com/ Bruno Simon] - Apprend aux débutants à utiliser Three.js étape par étape -
  • -
  • - [link:https://discoverthreejs.com/ Découvrir three.js] -
  • -
  • - [link:http://blog.cjgammon.com/ Collection de tutoriels] par [link:http://www.cjgammon.com/ CJ Gammon]. -
  • -
  • - [link:https://medium.com/soffritti.pierfrancesco/glossy-spheres-in-three-js-bfd2785d4857 Sphères brillantes dans three.js]. -
  • -
  • - [link:https://www.udacity.com/course/interactive-3d-graphics--cs291 Graphismes 3D Interactifs] - un cours gratuit sur Udacity qui enseigne les fondamentaux des graphismes 3D et utilise three.js comme outil de codage. -
  • -
  • - [Link:https://aerotwist.com/tutorials/ Aerotwist] tutoriels par [link:https://github.com/paullewis/ Paul Lewis]. -
  • -
  • - [link:https://discourse.threejs.org/t/three-js-bookshelf/2468 Étagère à livres Three.js] - Vous cherchez plus de ressources sur three.js ou les graphismes par ordinateur en général ? Consultez la sélection de littérature recommandée par la communauté. -
  • -
- -

Nouvelles et mises à jour

-
    -
  • - [link:https://twitter.com/hashtag/threejs Three.js sur Twitter] -
  • -
  • - [link:http://www.reddit.com/r/threejs/ Three.js sur reddit] -
  • -
  • - [link:http://www.reddit.com/r/webgl/ WebGL sur reddit] -
  • -
- -

Exemples

-
    -
  • - [link:https://github.com/edwinwebb/three-seed/ three-seed] - projet de démarrage three.js avec ES6 et Webpack -
  • -
  • - [link:http://stemkoski.github.io/Three.js/index.html Exemples du Professeur Stemkoski] - une collection d'exemples adaptés aux débutants construits à l'aide de three.js r60. -
  • -
  • - [link:https://threejs.org/examples/ Exemples officiels de three.js] - ces exemples sont maintenus dans le cadre du dépôt three.js et utilisent toujours la dernière version de three.js. -
  • -
  • - [link:https://raw.githack.com/mrdoob/three.js/dev/examples/ Exemples officiels de la branche de développement three.js] - Identiques aux exemples ci-dessus, sauf qu'ils utilisent la branche de développement de three.js et sont utilisés pour vérifier que tout fonctionne correctement pendant le développement de three.js. -
  • -
- -

Outils

-
    -
  • - [link:https://github.com/tbensky/physgl physgl.org] - Interface front-end JavaScript avec des wrappers pour three.js, pour apporter les graphismes WebGL aux étudiants apprenant la physique et les mathématiques. -
  • -
  • - [link:https://whsjs.readme.io/ Whitestorm.js] – Framework three.js modulaire avec plugin physique AmmoNext. -
  • -
  • - [link:http://zz85.github.io/zz85-bookmarklets/threelabs.html Inspecteur Three.js] -
  • -
  • - [link:http://idflood.github.io/ThreeNodes.js/ ThreeNodes.js]. -
  • -
  • - [link:https://marketplace.visualstudio.com/items?itemName=slevesque.shader vscode shader] - Colorateur syntaxique pour le langage de shader. -
    - [link:https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates vscode comment-tagged-templates] - Coloration syntaxique pour les chaînes de gabarit marquées utilisant des commentaires pour le langage de shader, comme : glsl.js. -
  • -
  • - [link:https://github.com/MozillaReality/WebXR-emulator-extension WebXR-emulator-extension] -
  • -
- -

Références WebGL

-
    -
  • - [link:https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf webgl-reference-card.pdf] - Référence de tous les mots-clés, terminologie, syntaxe et définitions de WebGL et GLSL. -
  • -
- -

Anciens liens

-

- Ces liens sont conservés à des fins historiques - vous pouvez toujours les trouver utiles, mais sachez qu'ils peuvent contenir des informations relatives à de très anciennes versions de three.js. -

- -
    -
  • - [link:https://www.youtube.com/watch?v=Dir4KO9RdhM AlterQualia at WebGL Camp 3] -
  • -
  • - [link:http://yomotsu.github.io/threejs-examples/ Yomotsus Examples] - une collection d'exemples utilisant three.js r45. -
  • -
  • - [link:http://fhtr.org/BasicsOfThreeJS/#1 Introduction à Three.js] par [link:http://github.com/kig/ Ilmari Heikkinen] (diaporama). -
  • -
  • - [link:http://www.slideshare.net/yomotsu/webgl-and-threejs WebGL and Three.js] par [link:http://github.com/yomotsu Akihiro Oyamada] (diaporama). -
  • -
  • - [link:https://www.youtube.com/watch?v=VdQnOaolrPA Trigger Rally] par [link:https://github.com/jareiko jareiko] (vidéo). -
  • -
  • - [link:http://blackjk3.github.io/threefab/ ThreeFab] - éditeur de scène, maintenu jusqu'à environ three.js r50. -
  • -
  • - [link:http://bkcore.com/blog/3d/webgl-three-js-workflow-tips.html Max to Three.js workflow tips and tricks] par [link:https://github.com/BKcore BKcore] -
  • -
  • - [link:http://12devsofxmas.co.uk/2012/01/webgl-and-three-js/ Un aperçu rapide de Three.js] - par [link:http://github.com/nrocy Paul King] -
  • -
  • - [link:http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html Lueur sélective animée dans Three.js] - par [link:https://github.com/BKcore BKcore] -
  • -
  • - [link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - tutoriel three.js en japonais -
  • -
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/voxel-geometry.html b/manual/fr/voxel-geometry.html deleted file mode 100644 index 15dee6fdea8e02..00000000000000 --- a/manual/fr/voxel-geometry.html +++ /dev/null @@ -1,1116 +0,0 @@ - - - Géométrie Voxel (type Minecraft) - - - - - - - - - - - - - -
-
-

Géométrie Voxel (type Minecraft)

-
-
-
-

J'ai vu ce sujet revenir plus d'une fois à divers endroits. -C'est fondamentalement, "Comment faire un affichage de voxels comme Minecraft".

-

La plupart des gens essaient d'abord en créant une géométrie de cube, puis -en faisant un maillage à chaque position de voxel. Juste pour le plaisir, j'ai essayé -cela. J'ai créé un Uint8Array de 16777216 éléments pour représenter -un cube de voxels de 256x256x256.

-
const cellSize = 256;
-const cell = new Uint8Array(cellSize * cellSize * cellSize);
-
-

J'ai ensuite fait une seule couche avec une sorte de collines de -vagues sinusoïdales comme ceci

-
for (let y = 0; y < cellSize; ++y) {
-  for (let z = 0; z < cellSize; ++z) {
-    for (let x = 0; x < cellSize; ++x) {
-      const height = (Math.sin(x / cellSize * Math.PI * 4) + Math.sin(z / cellSize * Math.PI * 6)) * 20 + cellSize / 2;
-      if (height > y && height < y + 1) {
-        const offset = y * cellSize * cellSize +
-                       z * cellSize +
-                       x;
-        cell[offset] = 1;
-      }
-    }
-  }
-}
-
-

J'ai ensuite parcouru toutes les cellules et si elles n'étaient pas -à 0, j'ai créé un maillage avec un cube.

-
const geometry = new THREE.BoxGeometry(1, 1, 1);
-const material = new THREE.MeshPhongMaterial({color: 'green'});
-
-for (let y = 0; y < cellSize; ++y) {
-  for (let z = 0; z < cellSize; ++z) {
-    for (let x = 0; x < cellSize; ++x) {
-      const offset = y * cellSize * cellSize +
-                     z * cellSize +
-                     x;
-      const block = cell[offset];
-      const mesh = new THREE.Mesh(geometry, material);
-      mesh.position.set(x, y, z);
-      scene.add(mesh);
-    }
-  }
-}
-
-

Le reste du code est basé sur l'exemple de -l'article sur le rendu à la demande.

-

- -

-

Cela prend un certain temps pour démarrer et si vous essayez de bouger la caméra -c'est probablement trop lent. Comme dans l'article sur l'optimisation de nombreux objets -le problème est qu'il y a juste beaucoup trop d'objets. 256x256 -fait 65536 boîtes !

-

L'utilisation de la technique de fusion de la géométrie -résoudra le problème pour cet exemple, mais que se passerait-il si, au lieu de faire une simple couche, nous remplissions tout ce qui se trouve sous le sol avec des voxels ? -En d'autres termes, changez la boucle qui remplit les voxels comme ceci :

-
for (let y = 0; y < cellSize; ++y) {
-  for (let z = 0; z < cellSize; ++z) {
-    for (let x = 0; x < cellSize; ++x) {
-      const height = (Math.sin(x / cellSize * Math.PI * 4) + Math.sin(z / cellSize * Math.PI * 6)) * 20 + cellSize / 2;
--      if (height > y && height < y + 1) {
-+      if (height < y + 1) {
-        const offset = y * cellSize * cellSize +
-                       z * cellSize +
-                       x;
-        cell[offset] = 1;
-      }
-    }
-  }
-}
-
-

J'ai essayé une fois juste pour voir les résultats. Ça a mouliné pendant -environ une minute, puis ça a planté avec un message manque de mémoire 😅

-

Il y a plusieurs problèmes, mais le plus important est -que nous créons toutes ces faces à l'intérieur des cubes que -nous ne pouvons en fait jamais voir.

-

En d'autres termes, disons que nous avons une boîte de voxels -3x2x2. En fusionnant les cubes, nous obtenons ceci :

-
-
-
- -

mais nous voulons vraiment ceci

-
-
-
- -

Dans la boîte du haut, il y a des faces entre les voxels. Des faces -qui sont un gâchis car elles ne peuvent pas être vues. Ce n'est pas seulement -une face entre chaque voxel, il y a 2 faces, une pour -chaque voxel faisant face à son voisin qui sont un gâchis. Toutes ces faces supplémentaires, -surtout pour un grand volume de voxels, tueront les performances.

-

Il devrait être clair que nous ne pouvons pas simplement fusionner la géométrie. -Nous devons la construire nous-mêmes, en tenant compte du fait -que si un voxel a un voisin adjacent, il n'a pas besoin de la -face qui fait face à ce voisin.

-

Le problème suivant est que 256x256x256 est tout simplement trop grand. 16 Mo représentent beaucoup de mémoire et -si rien d'autre n'y est, une grande partie de l'espace est vide, ce qui représente beaucoup de mémoire gaspillée. C'est aussi un nombre énorme de voxels, 16 millions ! C'est trop à -considérer d'un coup.

-

Une solution consiste à diviser la zone en zones plus petites. -Toute zone qui ne contient rien n'a pas besoin de stockage. Utilisons -des zones de 32x32x32 (soit 32k) et ne créons une zone que si elle contient quelque chose. -Nous appellerons l'une de ces zones plus grandes de 32x32x32 une "cellule".

-

Découpons cela en morceaux. Tout d'abord, créons une classe pour gérer les données de voxel.

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-  }
-}
-
-

Créons la fonction qui génère la géométrie pour une cellule. -Supposons que vous passiez une position de cellule. -En d'autres termes, si vous voulez la géométrie pour la cellule qui couvre les voxels (0-31x, 0-31y, 0-31z) -alors vous passerez 0,0,0. Pour la cellule qui couvre les voxels (32-63x, 0-31y, 0-31z), vous passerez -1,0,0.

-

Nous devons pouvoir vérifier les voxels voisins, alors supposons que notre classe -dispose d'une fonction getVoxel qui, étant donné une position de voxel, renvoie la valeur -du voxel à cet endroit. En d'autres termes, si vous lui passez 35,0,0 et que la cellSize est de 32, -elle regardera la cellule 1,0,0 et dans cette cellule, elle regardera le voxel 3,0,0. -En utilisant cette fonction, nous pouvons regarder les voxels voisins d'un voxel, même s'ils -se trouvent dans des cellules voisines.

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-  }
-+  generateGeometryDataForCell(cellX, cellY, cellZ) {
-+    const {cellSize} = this;
-+    const startX = cellX * cellSize;
-+    const startY = cellY * cellSize;
-+    const startZ = cellZ * cellSize;
-+
-+    for (let y = 0; y < cellSize; ++y) {
-+      const voxelY = startY + y;
-+      for (let z = 0; z < cellSize; ++z) {
-+        const voxelZ = startZ + z;
-+        for (let x = 0; x < cellSize; ++x) {
-+          const voxelX = startX + x;
-+          const voxel = this.getVoxel(voxelX, voxelY, voxelZ);
-+          if (voxel) {
-+            for (const {dir} of VoxelWorld.faces) {
-+              const neighbor = this.getVoxel(
-+                  voxelX + dir[0],
-+                  voxelY + dir[1],
-+                  voxelZ + dir[2]);
-+              if (!neighbor) {
-+                // ce voxel n'a pas de voisin dans cette direction, nous avons donc besoin d'une face ici.
-+                // here.
-+              }
-+            }
-+          }
-+        }
-+      }
-+    }
-+  }
-}
-
-+VoxelWorld.faces = [
-+  { // gauche
-+    dir: [ -1,  0,  0, ],
-+  },
-+  { // droite
-+    dir: [  1,  0,  0, ],
-+  },
-+  { // bas
-+    dir: [  0, -1,  0, ],
-+  },
-+  { // haut
-+    dir: [  0,  1,  0, ],
-+  },
-+  { // arrière
-+    dir: [  0,  0, -1, ],
-+  },
-+  { // avant
-+    dir: [  0,  0,  1, ],
-+  },
-+];
-
-

Donc, en utilisant le code ci-dessus, nous savons quand nous avons besoin d'une face. Générons les faces.

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-  }
-  generateGeometryDataForCell(cellX, cellY, cellZ) {
-    const {cellSize} = this;
-+    const positions = [];
-+    const normals = [];
-+    const indices = [];
-    const startX = cellX * cellSize;
-    const startY = cellY * cellSize;
-    const startZ = cellZ * cellSize;
-
-    for (let y = 0; y < cellSize; ++y) {
-      const voxelY = startY + y;
-      for (let z = 0; z < cellSize; ++z) {
-        const voxelZ = startZ + z;
-        for (let x = 0; x < cellSize; ++x) {
-          const voxelX = startX + x;
-          const voxel = this.getVoxel(voxelX, voxelY, voxelZ);
-          if (voxel) {
--            for (const {dir} of VoxelWorld.faces) {
-+            for (const {dir, corners} of VoxelWorld.faces) {
-              const neighbor = this.getVoxel(
-                  voxelX + dir[0],
-                  voxelY + dir[1],
-                  voxelZ + dir[2]);
-              if (!neighbor) {
-                // ce voxel n'a pas de voisin dans cette direction, nous avons donc besoin d'une face.
-+                const ndx = positions.length / 3;
-+                for (const pos of corners) {
-+                  positions.push(pos[0] + x, pos[1] + y, pos[2] + z);
-+                  normals.push(...dir);
-+                }
-+                indices.push(
-+                  ndx, ndx + 1, ndx + 2,
-+                  ndx + 2, ndx + 1, ndx + 3,
-+                );
-              }
-            }
-          }
-        }
-      }
-    }
-+    return {
-+      positions,
-+      normals,
-+      indices,
-    };
-  }
-}
-
-VoxelWorld.faces = [
-  { // gauche
-    dir: [ -1,  0,  0, ],
-+    corners: [
-+      [ 0, 1, 0 ],
-+      [ 0, 0, 0 ],
-+      [ 0, 1, 1 ],
-+      [ 0, 0, 1 ],
-+    ],
-  },
-  { // droite
-    dir: [  1,  0,  0, ],
-+    corners: [
-+      [ 1, 1, 1 ],
-+      [ 1, 0, 1 ],
-+      [ 1, 1, 0 ],
-+      [ 1, 0, 0 ],
-+    ],
-  },
-  { // bas
-    dir: [  0, -1,  0, ],
-+    corners: [
-+      [ 1, 0, 1 ],
-+      [ 0, 0, 1 ],
-+      [ 1, 0, 0 ],
-+      [ 0, 0, 0 ],
-+    ],
-  },
-  { // haut
-    dir: [  0,  1,  0, ],
-+    corners: [
-+      [ 0, 1, 1 ],
-+      [ 1, 1, 1 ],
-+      [ 0, 1, 0 ],
-+      [ 1, 1, 0 ],
-+    ],
-  },
-  { // arrière
-    dir: [  0,  0, -1, ],
-+    corners: [
-+      [ 1, 0, 0 ],
-+      [ 0, 0, 0 ],
-+      [ 1, 1, 0 ],
-+      [ 0, 1, 0 ],
-+    ],
-  },
-  { // avant
-    dir: [  0,  0,  1, ],
-+    corners: [
-+      [ 0, 0, 1 ],
-+      [ 1, 0, 1 ],
-+      [ 0, 1, 1 ],
-+      [ 1, 1, 1 ],
-+    ],
-  },
-];
-
-

Le code ci-dessus générerait des données de géométrie de base pour nous. Il suffit de fournir -la fonction getVoxel. Commençons par une seule cellule codée en dur.

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-+    this.cell = new Uint8Array(cellSize * cellSize * cellSize);
-  }
-+  getCellForVoxel(x, y, z) {
-+    const {cellSize} = this;
-+    const cellX = Math.floor(x / cellSize);
-+    const cellY = Math.floor(y / cellSize);
-+    const cellZ = Math.floor(z / cellSize);
-+    if (cellX !== 0 || cellY !== 0 || cellZ !== 0) {
-+      return null
-+    }
-+    return this.cell;
-+  }
-+  getVoxel(x, y, z) {
-+    const cell = this.getCellForVoxel(x, y, z);
-+    if (!cell) {
-+      return 0;
-+    }
-+    const {cellSize} = this;
-+    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
-+    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
-+    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
-+    const voxelOffset = voxelY * cellSize * cellSize +
-+                        voxelZ * cellSize +
-+                        voxelX;
-+    return cell[voxelOffset];
-+  }
-  generateGeometryDataForCell(cellX, cellY, cellZ) {
-
-  ...
-}
-
-

Cela semble fonctionner. Créons une fonction setVoxel -pour pouvoir définir des données.

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-    this.cell = new Uint8Array(cellSize * cellSize * cellSize);
-  }
-  getCellForVoxel(x, y, z) {
-    const {cellSize} = this;
-    const cellX = Math.floor(x / cellSize);
-    const cellY = Math.floor(y / cellSize);
-    const cellZ = Math.floor(z / cellSize);
-    if (cellX !== 0 || cellY !== 0 || cellZ !== 0) {
-      return null
-    }
-    return this.cell;
-  }
-+  setVoxel(x, y, z, v) {
-+    let cell = this.getCellForVoxel(x, y, z);
-+    if (!cell) {
-+      return;  // TODO : ajouter une nouvelle cellule ?
-+    }
-+    const {cellSize} = this;
-+    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
-+    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
-+    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
-+    const voxelOffset = voxelY * cellSize * cellSize +
-+                        voxelZ * cellSize +
-+                        voxelX;
-+    cell[voxelOffset] = v;
-+  }
-  getVoxel(x, y, z) {
-    const cell = this.getCellForVoxel(x, y, z);
-    if (!cell) {
-      return 0;
-    }
-    const {cellSize} = this;
-    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
-    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
-    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
-    const voxelOffset = voxelY * cellSize * cellSize +
-                        voxelZ * cellSize +
-                        voxelX;
-    return cell[voxelOffset];
-  }
-  generateGeometryDataForCell(cellX, cellY, cellZ) {
-
-  ...
-}
-
-

Hmmm, je vois beaucoup de code répété. Arrangeons ça

-
class VoxelWorld {
-  constructor(cellSize) {
-    this.cellSize = cellSize;
-+    this.cellSliceSize = cellSize * cellSize;
-    this.cell = new Uint8Array(cellSize * cellSize * cellSize);
-  }
-  getCellForVoxel(x, y, z) {
-    const {cellSize} = this;
-    const cellX = Math.floor(x / cellSize);
-    const cellY = Math.floor(y / cellSize);
-    const cellZ = Math.floor(z / cellSize);
-    if (cellX !== 0 || cellY !== 0 || cellZ !== 0) {
-      return null;
-    }
-    return this.cell;
-  }
-+  computeVoxelOffset(x, y, z) {
-+    const {cellSize, cellSliceSize} = this;
-+    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
-+    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
-+    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
-+    return voxelY * cellSliceSize +
-+           voxelZ * cellSize +
-+           voxelX;
-+  }
-  setVoxel(x, y, z, v) {
-    const cell = this.getCellForVoxel(x, y, z);
-    if (!cell) {
-      return;  // TODO : ajouter une nouvelle cellule ?
-    }
--    const {cellSize} = this;
--    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
--    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
--    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
--    const voxelOffset = voxelY * cellSize * cellSize +
--                        voxelZ * cellSize +
--                        voxelX;
-+    const voxelOffset = this.computeVoxelOffset(x, y, z);
-    cell[voxelOffset] = v;
-  }
-  getVoxel(x, y, z) {
-    const cell = this.getCellForVoxel(x, y, z);
-    if (!cell) {
-      return 0;
-    }
--    const {cellSize} = this;
--    const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
--    const voxelY = THREE.MathUtils.euclideanModulo(y, cellSize) | 0;
--    const voxelZ = THREE.MathUtils.euclideanModulo(z, cellSize) | 0;
--    const voxelOffset = voxelY * cellSize * cellSize +
--                        voxelZ * cellSize +
--                        voxelX;
-+    const voxelOffset = this.computeVoxelOffset(x, y, z);
-    return cell[voxelOffset];
-  }
-  generateGeometryDataForCell(cellX, cellY, cellZ) {
-
-  ...
-}
-
-

Maintenant, créons du code pour remplir la première cellule avec des voxels.

-
const cellSize = 32;
-
-const world = new VoxelWorld(cellSize);
-
-for (let y = 0; y < cellSize; ++y) {
-  for (let z = 0; z < cellSize; ++z) {
-    for (let x = 0; x < cellSize; ++x) {
-      const height = (Math.sin(x / cellSize * Math.PI * 2) + Math.sin(z / cellSize * Math.PI * 3)) * (cellSize / 6) + (cellSize / 2);
-      if (y < height) {
-        world.setVoxel(x, y, z, 1);
-      }
-    }
-  }
-}
-
-

et du code pour effectivement générer la géométrie comme nous l'avons vu dans -l'article sur BufferGeometry personnalisé.

-
const {positions, normals, indices} = world.generateGeometryDataForCell(0, 0, 0);
-const geometry = new THREE.BufferGeometry();
-const material = new THREE.MeshLambertMaterial({color: 'green'});
-
-const positionNumComponents = 3;
-const normalNumComponents = 3;
-geometry.setAttribute(
-    'position',
-    new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-geometry.setIndex(indices);
-const mesh = new THREE.Mesh(geometry, material);
-scene.add(mesh);
-
-

essayons

-

- -

-

Cela semble fonctionner ! D'accord, ajoutons des textures.

-

En cherchant sur le net, j'ai trouvé cet ensemble -de textures minecraft sous licence CC-BY-NC-SA par Joshtimus. -J'en ai choisi quelques-unes au hasard et j'ai construit cette texture atlas.

-
- -

Pour simplifier les choses, elles sont arrangées un type de voxel par colonne, -où la rangée supérieure est le côté d'un voxel. La 2ème rangée est -le dessus du voxel, et la 3ème rangée est le dessous du voxel.

-

Sachant cela, nous pouvons ajouter des informations à nos données VoxelWorld.faces -pour spécifier pour chaque face quelle rangée utiliser et les UVs à utiliser -pour cette face.

-
VoxelWorld.faces = [
-  { // gauche
-+    uvRow: 0,
-    dir: [ -1,  0,  0, ],
-    corners: [
--      [ 0, 1, 0 ],
--      [ 0, 0, 0 ],
--      [ 0, 1, 1 ],
--      [ 0, 0, 1 ],
-+      { pos: [ 0, 1, 0 ], uv: [ 0, 1 ], },
-+      { pos: [ 0, 0, 0 ], uv: [ 0, 0 ], },
-+      { pos: [ 0, 1, 1 ], uv: [ 1, 1 ], },
-+      { pos: [ 0, 0, 1 ], uv: [ 1, 0 ], },
-    ],
-  },
-  { // droite
-+    uvRow: 0,
-    dir: [  1,  0,  0, ],
-    corners: [
--      [ 1, 1, 1 ],
--      [ 1, 0, 1 ],
--      [ 1, 1, 0 ],
--      [ 1, 0, 0 ],
-+      { pos: [ 1, 1, 1 ], uv: [ 0, 1 ], },
-+      { pos: [ 1, 0, 1 ], uv: [ 0, 0 ], },
-+      { pos: [ 1, 1, 0 ], uv: [ 1, 1 ], },
-+      { pos: [ 1, 0, 0 ], uv: [ 1, 0 ], },
-+    ],
-  },
-  { // bas
-+    uvRow: 1,
-    dir: [  0, -1,  0, ],
-    corners: [
--      [ 1, 0, 1 ],
--      [ 0, 0, 1 ],
--      [ 1, 0, 0 ],
--      [ 0, 0, 0 ],
-+      { pos: [ 1, 0, 1 ], uv: [ 1, 0 ], },
-+      { pos: [ 0, 0, 1 ], uv: [ 0, 0 ], },
-+      { pos: [ 1, 0, 0 ], uv: [ 1, 1 ], },
-+      { pos: [ 0, 0, 0 ], uv: [ 0, 1 ], },
-+    ],
-  },
-  { // haut
-+    uvRow: 2,
-    dir: [  0,  1,  0, ],
-    corners: [
--      [ 0, 1, 1 ],
--      [ 1, 1, 1 ],
--      [ 0, 1, 0 ],
--      [ 1, 1, 0 ],
-+      { pos: [ 0, 1, 1 ], uv: [ 1, 1 ], },
-+      { pos: [ 1, 1, 1 ], uv: [ 0, 1 ], },
-+      { pos: [ 0, 1, 0 ], uv: [ 1, 0 ], },
-+      { pos: [ 1, 1, 0 ], uv: [ 0, 0 ], },
-+    ],
-  },
-  { // arrière
-+    uvRow: 0,
-    dir: [  0,  0, -1, ],
-    corners: [
--      [ 1, 0, 0 ],
--      [ 0, 0, 0 ],
--      [ 1, 1, 0 ],
--      [ 0, 1, 0 ],
-+      { pos: [ 1, 0, 0 ], uv: [ 0, 0 ], },
-+      { pos: [ 0, 0, 0 ], uv: [ 1, 0 ], },
-+      { pos: [ 1, 1, 0 ], uv: [ 0, 1 ], },
-+      { pos: [ 0, 1, 0 ], uv: [ 1, 1 ], },
-+    ],
-  },
-  { // avant
-+    uvRow: 0,
-    dir: [  0,  0,  1, ],
-    corners: [
--      [ 0, 0, 1 ],
--      [ 1, 0, 1 ],
--      [ 0, 1, 1 ],
--      [ 1, 1, 1 ],
-+      { pos: [ 0, 0, 1 ], uv: [ 0, 0 ], },
-+      { pos: [ 1, 0, 1 ], uv: [ 1, 0 ], },
-+      { pos: [ 0, 1, 1 ], uv: [ 0, 1 ], },
-+      { pos: [ 1, 1, 1 ], uv: [ 1, 1 ], },
-+    ],
-  },
-];
-
-

Et nous pouvons mettre à jour le code pour utiliser ces données. Nous devons -connaître la taille d'une tuile dans la texture atlas et les dimensions -de la texture.

-
class VoxelWorld {
--  constructor(cellSize) {
--    this.cellSize = cellSize;
-+  constructor(options) {
-+    this.cellSize = options.cellSize;
-+    this.tileSize = options.tileSize;
-+    this.tileTextureWidth = options.tileTextureWidth;
-+    this.tileTextureHeight = options.tileTextureHeight;
-+    const {cellSize} = this;
-+    this.cellSliceSize = cellSize * cellSize;
-+    this.cell = new Uint8Array(cellSize * cellSize * cellSize);
-+  }
-
-  ...
-
-  generateGeometryDataForCell(cellX, cellY, cellZ) {
--    const {cellSize} = this;
-+    const {cellSize, tileSize, tileTextureWidth, tileTextureHeight} = this;
-    const positions = [];
-    const normals = [];
-+    const uvs = [];
-    const indices = [];
-    const startX = cellX * cellSize;
-    const startY = cellY * cellSize;
-    const startZ = cellZ * cellSize;
-
-    for (let y = 0; y < cellSize; ++y) {
-      const voxelY = startY + y;
-      for (let z = 0; z < cellSize; ++z) {
-        const voxelZ = startZ + z;
-        for (let x = 0; x < cellSize; ++x) {
-          const voxelX = startX + x;
-          const voxel = this.getVoxel(voxelX, voxelY, voxelZ);
-          if (voxel) {
-            const uvVoxel = voxel - 1;  // le voxel 0 est le ciel, donc pour les UVs nous commençons à 0
-            // There is a voxel here but do we need faces for it?
--            for (const {dir, corners} of VoxelWorld.faces) {
-+            for (const {dir, corners, uvRow} of VoxelWorld.faces) {
-              const neighbor = this.getVoxel(
-                  voxelX + dir[0],
-                  voxelY + dir[1],
-                  voxelZ + dir[2]);
-              if (!neighbor) {
-                // ce voxel n'a pas de voisin dans cette direction, nous avons donc besoin d'une face.
-                const ndx = positions.length / 3;
--                for (const pos of corners) {
-+                for (const {pos, uv} of corners) {
-                  positions.push(pos[0] + x, pos[1] + y, pos[2] + z);
-                  normals.push(...dir);
-+                  uvs.push(
-+                        (uvVoxel +   uv[0]) * tileSize / tileTextureWidth,
-+                    1 - (uvRow + 1 - uv[1]) * tileSize / tileTextureHeight);
-                }
-                indices.push(
-                  ndx, ndx + 1, ndx + 2,
-                  ndx + 2, ndx + 1, ndx + 3,
-                );
-              }
-            }
-          }
-        }
-      }
-    }
-
-    return {
-      positions,
-      normals,
-      uvs,
-      indices,
-    };
-  }
-}
-
-

Nous devons ensuite charger la texture

-
const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/minecraft/flourish-cc-by-nc-sa.png', render);
-texture.magFilter = THREE.NearestFilter;
-texture.minFilter = THREE.NearestFilter;
-texture.colorSpace = THREE.SRGBColorSpace;
-
-

et passer les paramètres à la classe VoxelWorld

-
+const tileSize = 16;
-+const tileTextureWidth = 256;
-+const tileTextureHeight = 64;
--const world = new VoxelWorld(cellSize);
-+const world = new VoxelWorld({
-+  cellSize,
-+  tileSize,
-+  tileTextureWidth,
-+  tileTextureHeight,
-+});
-
-

Utilisons réellement les UVs lors de la création de la géométrie -et la texture lorsque nous fabriquons le matériau

-
-const {positions, normals, indices} = world.generateGeometryDataForCell(0, 0, 0);
-+const {positions, normals, uvs, indices} = world.generateGeometryDataForCell(0, 0, 0);
-const geometry = new THREE.BufferGeometry();
--const material = new THREE.MeshLambertMaterial({color: 'green'});
-+const material = new THREE.MeshLambertMaterial({
-+  map: texture,
-+  side: THREE.DoubleSide,
-+  alphaTest: 0.1,
-+  transparent: true,
-+});
-
-const positionNumComponents = 3;
-const normalNumComponents = 3;
-+const uvNumComponents = 2;
-geometry.setAttribute(
-    'position',
-    new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-+geometry.setAttribute(
-+    'uv',
-+    new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-geometry.setIndex(indices);
-const mesh = new THREE.Mesh(geometry, material);
-scene.add(mesh);
-
-

Une dernière chose, nous devons réellement définir certains voxels -pour utiliser différentes textures.

-
for (let y = 0; y < cellSize; ++y) {
-  for (let z = 0; z < cellSize; ++z) {
-    for (let x = 0; x < cellSize; ++x) {
-      const height = (Math.sin(x / cellSize * Math.PI * 2) + Math.sin(z / cellSize * Math.PI * 3)) * (cellSize / 6) + (cellSize / 2);
-      if (y < height) {
--        world.setVoxel(x, y, z, 1);
-+        world.setVoxel(x, y, z, randInt(1, 17));
-+      }
-+    }
-+  }
-+}
-+
-+function randInt(min, max) {
-+  return Math.floor(Math.random() * (max - min) + min);
-+}
-
-

et avec cela, nous obtenons des textures !

-

- -

-

Supportons maintenant plus d'une cellule.

-

Pour ce faire, stockons les cellules dans un objet en utilisant des cell ids. -Un cell id sera simplement les coordonnées d'une cellule séparées par -une virgule. En d'autres termes, si nous demandons le voxel 35,0,0, -qui est dans la cellule 1,0,0, son id est donc "1,0,0".

-
class VoxelWorld {
-  constructor(options) {
-    this.cellSize = options.cellSize;
-    this.tileSize = options.tileSize;
-    this.tileTextureWidth = options.tileTextureWidth;
-    this.tileTextureHeight = options.tileTextureHeight;
-    const {cellSize} = this;
-    this.cellSliceSize = cellSize * cellSize;
--    this.cell = new Uint8Array(cellSize * cellSize * cellSize);
-+    this.cells = {};
-  }
-+  computeCellId(x, y, z) {
-+    const {cellSize} = this;
-+    const cellX = Math.floor(x / cellSize);
-+    const cellY = Math.floor(y / cellSize);
-+    const cellZ = Math.floor(z / cellSize);
-+    return `${cellX},${cellY},${cellZ}`;
-+  }
-+  getCellForVoxel(x, y, z) {
--    const cellX = Math.floor(x / cellSize);
--    const cellY = Math.floor(y / cellSize);
--    const cellZ = Math.floor(z / cellSize);
--    if (cellX !== 0 || cellY !== 0 || cellZ !== 0) {
--      return null;
--    }
--    return this.cell;
-+    return this.cells[this.computeCellId(x, y, z)];
-  }
-
-   ...
-}
-
-

et maintenant nous pouvons faire en sorte que setVoxel ajoute de nouvelles cellules si -nous essayons de définir un voxel dans une cellule qui n'existe pas encore

-
  setVoxel(x, y, z, v) {
--    const cell = this.getCellForVoxel(x, y, z);
-+    let cell = this.getCellForVoxel(x, y, z);
-    if (!cell) {
--      return 0;
-+      cell = this.addCellForVoxel(x, y, z);
-    }
-    const voxelOffset = this.computeVoxelOffset(x, y, z);
-    cell[voxelOffset] = v;
-  }
-+  addCellForVoxel(x, y, z) {
-+    const cellId = this.computeCellId(x, y, z);
-+    let cell = this.cells[cellId];
-+    if (!cell) {
-+      const {cellSize} = this;
-+      cell = new Uint8Array(cellSize * cellSize * cellSize);
-+      this.cells[cellId] = cell;
-+    }
-+    return cell;
-+  }
-
-

Rendons cela modifiable.

-

Tout d'abord, nous ajouterons une UI. En utilisant des boutons radio, nous pouvons créer un tableau de tuiles 8x2

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui">
-+    <div class="tiles">
-+      <input type="radio" name="voxel" id="voxel1" value="1"><label for="voxel1" style="background-position:   -0% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel2" value="2"><label for="voxel2" style="background-position: -100% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel3" value="3"><label for="voxel3" style="background-position: -200% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel4" value="4"><label for="voxel4" style="background-position: -300% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel5" value="5"><label for="voxel5" style="background-position: -400% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel6" value="6"><label for="voxel6" style="background-position: -500% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel7" value="7"><label for="voxel7" style="background-position: -600% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel8" value="8"><label for="voxel8" style="background-position: -700% -0%"></label>
-+    </div>
-+    <div class="tiles">
-+      <input type="radio" name="voxel" id="voxel9"  value="9" ><label for="voxel9"  style="background-position:  -800% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel10" value="10"><label for="voxel10" style="background-position:  -900% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel11" value="11"><label for="voxel11" style="background-position: -1000% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel12" value="12"><label for="voxel12" style="background-position: -1100% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel13" value="13"><label for="voxel13" style="background-position: -1200% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel14" value="14"><label for="voxel14" style="background-position: -1300% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel15" value="15"><label for="voxel15" style="background-position: -1400% -0%"></label>
-+      <input type="radio" name="voxel" id="voxel16" value="16"><label for="voxel16" style="background-position: -1500% -0%"></label>
-+    </div>
-+  </div>
-</body>
-
-

Et ajouter du CSS pour le styliser, afficher les tuiles et mettre en évidence -la sélection actuelle

-
body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-}
-+#ui {
-+    position: absolute;
-+    left: 10px;
-+    top: 10px;
-+    background: rgba(0, 0, 0, 0.8);
-+    padding: 5px;
-+}
-+#ui input[type=radio] {
-+  width: 0;
-+  height: 0;
-+  display: none;
-+}
-+#ui input[type=radio] + label {
-+  background-image: url('resources/images/minecraft/flourish-cc-by-nc-sa.png');
-+  background-size: 1600% 400%;
-+  image-rendering: pixelated;
-+  width: 64px;
-+  height: 64px;
-+  display: inline-block;
-+}
-+#ui input[type=radio]:checked + label {
-+  outline: 3px solid red;
-+}
-+@media (max-width: 600px), (max-height: 600px) {
-+  #ui input[type=radio] + label {
-+    width: 32px;
-+    height: 32px;
-+  }
-+}
-
-

L'expérience utilisateur (UX) sera la suivante. Si aucune tuile n'est sélectionnée et que vous cliquez sur un voxel, ce voxel sera effacé, ou si vous cliquez sur un voxel et que vous maintenez la touche Maj enfoncée, il sera effacé. Sinon, si une tuile est sélectionnée, elle sera ajoutée. Vous pouvez désélectionner le type de tuile sélectionné en cliquant à nouveau dessus.

-

Ce code permettra à l'utilisateur de désélectionner le -bouton radio surligné.

-
let currentVoxel = 0;
-let currentId;
-
-document.querySelectorAll('#ui .tiles input[type=radio][name=voxel]').forEach((elem) => {
-  elem.addEventListener('click', allowUncheck);
-});
-
-function allowUncheck() {
-  if (this.id === currentId) {
-    this.checked = false;
-    currentId = undefined;
-    currentVoxel = 0;
-  } else {
-    currentId = this.id;
-    currentVoxel = parseInt(this.value);
-  }
-}
-
-

Et le code ci-dessous nous permettra de définir un voxel en fonction de l'endroit -où l'utilisateur clique. Il utilise un code similaire à celui que nous avons -fait dans l'article sur la sélection -mais il n'utilise pas le RayCaster intégré. Au lieu de cela, -il utilise VoxelWorld.intersectRay qui renvoie -la position d'intersection et la normale de la face -touchée.

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function placeVoxel(event) {
-  const pos = getCanvasRelativePosition(event);
-  const x = (pos.x / canvas.width ) *  2 - 1;
-  const y = (pos.y / canvas.height) * -2 + 1;  // notez que nous inversons Y
-
-  const start = new THREE.Vector3();
-  const end = new THREE.Vector3();
-  start.setFromMatrixPosition(camera.matrixWorld);
-  end.set(x, y, 1).unproject(camera);
-
-  const intersection = world.intersectRay(start, end);
-  if (intersection) {
-    const voxelId = event.shiftKey ? 0 : currentVoxel;
-    // le point d'intersection est sur la face. Cela signifie
-    // que l'imprécision mathématique pourrait nous placer de chaque côté de la face.
-    // alors allons à la moitié de la normale DANS le voxel si nous supprimons (currentVoxel = 0)
-    // ou HORS du voxel si nous ajoutons (currentVoxel > 0)
-    const pos = intersection.position.map((v, ndx) => {
-      return v + intersection.normal[ndx] * (voxelId > 0 ? 0.5 : -0.5);
-    });
-    world.setVoxel(...pos, voxelId);
-    updateVoxelGeometry(...pos);
-    requestRenderIfNotRequested();
-  }
-}
-
-const mouse = {
-  x: 0,
-  y: 0,
-};
-
-function recordStartPosition(event) {
-  mouse.x = event.clientX;
-  mouse.y = event.clientY;
-  mouse.moveX = 0;
-  mouse.moveY = 0;
-}
-function recordMovement(event) {
-  mouse.moveX += Math.abs(mouse.x - event.clientX);
-  mouse.moveY += Math.abs(mouse.y - event.clientY);
-}
-function placeVoxelIfNoMovement(event) {
-  if (mouse.moveX < 5 && mouse.moveY < 5) {
-    placeVoxel(event);
-  }
-  window.removeEventListener('pointermove', recordMovement);
-  window.removeEventListener('pointerup', placeVoxelIfNoMovement);
-}
-canvas.addEventListener('pointerdown', (event) => {
-  event.preventDefault();
-  recordStartPosition(event);
-  window.addEventListener('pointermove', recordMovement);
-  window.addEventListener('pointerup', placeVoxelIfNoMovement);
-}, {passive: false});
-canvas.addEventListener('touchstart', (event) => {
-  // arrêter le défilement
-  event.preventDefault();
-}, {passive: false});
-
-

Il se passe beaucoup de choses dans le code ci-dessus. En gros, la souris a une double fonction. L'une est de déplacer la caméra. L'autre est d'éditer le monde. Placer/Effacer un voxel se produit lorsque vous relâchez la souris, mais uniquement si vous n'avez pas bougé la souris depuis que vous avez appuyé pour la première fois. C'est juste une supposition que si vous avez bougé la souris, vous essayiez de déplacer la caméra, pas de placer un bloc. moveX et moveY sont en mouvement absolu, donc si vous vous déplacez de 10 vers la gauche puis de 10 vers la droite, vous aurez parcouru 20 unités. Dans ce cas, l'utilisateur était probablement juste en train de faire pivoter le modèle d'avant en arrière et ne voulait pas placer de bloc. Je n'ai pas fait de tests pour voir si 5 est une bonne valeur ou non.

-

Dans le code, nous appelons world.setVoxel pour définir un voxel et -ensuite updateVoxelGeometry pour mettre à jour la géométrie three.js -en fonction de ce qui a changé.

-

Faisons cela maintenant. Si l'utilisateur clique sur un -voxel au bord d'une cellule, la géométrie du voxel -dans la cellule adjacente pourrait avoir besoin d'une nouvelle géométrie. Cela signifie -que nous devons vérifier la cellule du voxel que nous venons d'éditer -ainsi que dans les 6 directions à partir de cette cellule.

-
const neighborOffsets = [
-  [ 0,  0,  0], // soi-même
-  [-1,  0,  0], // gauche
-  [ 1,  0,  0], // droite
-  [ 0, -1,  0], // bas
-  [ 0,  1,  0], // haut
-  [ 0,  0, -1], // arrière
-  [ 0,  0,  1], // avant
-];
-function updateVoxelGeometry(x, y, z) {
-  const updatedCellIds = {};
-  for (const offset of neighborOffsets) {
-    const ox = x + offset[0];
-    const oy = y + offset[1];
-    const oz = z + offset[2];
-    const cellId = world.computeCellId(ox, oy, oz);
-    if (!updatedCellIds[cellId]) {
-      updatedCellIds[cellId] = true;
-      updateCellGeometry(ox, oy, oz);
-    }
-  }
-}
-
-

J'ai pensé à vérifier les cellules adjacentes comme

-
const voxelX = THREE.MathUtils.euclideanModulo(x, cellSize) | 0;
-if (voxelX === 0) {
-  // mettre à jour la cellule à gauche
-} else if (voxelX === cellSize - 1) {
-  // mettre à jour la cellule à droite
-}
-
-

et il y aurait 4 vérifications supplémentaires pour les 4 autres directions, -mais il m'est apparu que le code serait beaucoup plus simple avec -juste un tableau d'offsets et en sauvegardant les cell ids des -cellules que nous avons déjà mises à jour. Si le voxel mis à jour n'est pas -au bord d'une cellule, le test rejettera rapidement la mise à jour -de la même cellule.

-

Pour updateCellGeometry, nous allons simplement prendre le code que nous -avions auparavant et qui générait la géométrie pour une cellule -et le faire gérer plusieurs cellules.

-
const cellIdToMesh = {};
-function updateCellGeometry(x, y, z) {
-  const cellX = Math.floor(x / cellSize);
-  const cellY = Math.floor(y / cellSize);
-  const cellZ = Math.floor(z / cellSize);
-  const cellId = world.computeCellId(x, y, z);
-  let mesh = cellIdToMesh[cellId];
-  const geometry = mesh ? mesh.geometry : new THREE.BufferGeometry();
-
-  const {positions, normals, uvs, indices} = world.generateGeometryDataForCell(cellX, cellY, cellZ);
-  const positionNumComponents = 3;
-  geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  const normalNumComponents = 3;
-  geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  const uvNumComponents = 2;
-  geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-  geometry.setIndex(indices);
-  geometry.computeBoundingSphere();
-
-  if (!mesh) {
-    mesh = new THREE.Mesh(geometry, material);
-    mesh.name = cellId;
-    cellIdToMesh[cellId] = mesh;
-    scene.add(mesh);
-    mesh.position.set(cellX * cellSize, cellY * cellSize, cellZ * cellSize);
-  }
-}
-
-

Le code ci-dessus vérifie une map de cell ids vers les maillages. Si -nous demandons une cellule qui n'existe pas, un nouveau Mesh est créé -et ajouté au bon endroit dans l'espace monde. -À la fin, nous mettons à jour les attributes et les indices avec les nouvelles données.

-

- -

-

Quelques notes :

-

Le RayCaster aurait peut-être fonctionné très bien. Je n'ai pas essayé. -Au lieu de cela, j'ai trouvé un raycaster spécifique aux voxels. -qui est optimisé pour les voxels.

-

J'ai fait de intersectRay une partie de VoxelWorld car il semblait -que si cela devenait trop lent, nous pourrions lancer des rayons contre les cellules -avant de le faire sur les voxels comme une simple accélération si cela devenait -trop lent.

-

Vous pourriez vouloir changer la longueur du raycast -car actuellement, elle va jusqu'au Z-far. Je suppose que si l' -utilisateur clique sur quelque chose de trop éloigné, il ne veut pas vraiment -placer des blocs de l'autre côté du monde qui font 1 ou 2 pixels.

-

Appeler geometry.computeBoundingSphere pourrait être lent. -Nous pourrions simplement définir manuellement la bounding sphere pour qu'elle s'adapte -à la cellule entière.

-

Voulons-nous supprimer les cellules si tous les voxels de cette cellule sont à 0 ? -Ce serait probablement un changement raisonnable si nous voulions livrer ceci.

-

En réfléchissant à la manière dont cela fonctionne, il est clair que le -pire des cas absolu est un damier de voxels activés et désactivés. Je ne -sais pas d'emblée quelles autres stratégies utiliser -si les choses deviennent trop lentes. Peut-être que devenir trop lent -encouragerait simplement l'utilisateur à ne pas créer d'énormes zones en damier.

-

Pour simplifier, la texture atlas n'a qu'une seule colonne -par type de voxel. Il serait préférable de faire quelque chose de plus -flexible où nous aurions un tableau de types de voxels et chaque -type pourrait spécifier où se trouvent les textures de ses faces dans l'atlas. -Tel quel, beaucoup d'espace est gaspillé.

-

En regardant le vrai minecraft, il y a des tuiles qui ne sont pas -des voxels, pas des cubes. Comme une tuile de clôture ou des fleurs. Pour faire cela, -nous aurions à nouveau besoin d'un tableau de types de voxels et pour chaque -voxel, s'il s'agit d'un cube ou d'une autre géométrie. S'il ne s'agit pas d'un cube, -la vérification des voisins lors de la génération de la géométrie -devrait également changer. Un voxel de fleur à côté d'un autre -voxel ne devrait pas supprimer les faces entre eux.

-

Si vous voulez créer quelque chose de similaire à minecraft en utilisant three.js, -j'espère que cela vous a donné quelques idées pour commencer et comment -générer une géométrie quelque peu efficace.

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/webgl-compatibility-check.html b/manual/fr/webgl-compatibility-check.html deleted file mode 100644 index fcf1ea33abe92d..00000000000000 --- a/manual/fr/webgl-compatibility-check.html +++ /dev/null @@ -1,62 +0,0 @@ - - - Vérification de la compatibilité WebGL - - - - - - - - - - - - - -
-
-

Vérification de la compatibilité WebGL

-
-
-
- -

- Bien que cela devienne de moins en moins un problème, certains appareils ou navigateurs peuvent encore ne pas prendre en charge WebGL 2. - La méthode suivante vous permet de vérifier s'il est pris en charge et d'afficher un message à l'utilisateur si ce n'est pas le cas. - Importez le module de détection de la prise en charge WebGL et exécutez le code suivant avant de tenter de rendre quoi que ce soit. -

- -
-import WebGL from 'three/addons/capabilities/WebGL.js';
-
-if ( WebGL.isWebGL2Available() ) {
-
-  // Initialisez la fonction ou d'autres initialisations ici
-  animate();
-
-} else {
-
-  const warning = WebGL.getWebGL2ErrorMessage();
-  document.getElementById( 'container' ).appendChild( warning );
-
-}
-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/webxr-basics.html b/manual/fr/webxr-basics.html deleted file mode 100644 index ab8d3d186253f1..00000000000000 --- a/manual/fr/webxr-basics.html +++ /dev/null @@ -1,376 +0,0 @@ - - - RV - - - - - - - - - - - - - -
-
-

RV

-
-
-
-

Créer une application RV dans three.js est assez simple. Il suffit essentiellement de dire à -three.js que vous souhaitez utiliser WebXR. Si vous y réfléchissez, quelques points concernant WebXR -devraient être clairs. La direction vers laquelle la caméra pointe est fournie par le système RV -lui-même, puisque l'utilisateur tourne la tête pour choisir une direction à regarder. De même, -le champ de vision et l'aspect seront fournis par le système RV, car chaque système a un champ -de vision et un aspect d'affichage différents.

-

Prenons un exemple de l'article sur la création d'une page web responsive -et rendons-le compatible avec la RV.

-

Avant de commencer, vous aurez besoin d'un dispositif compatible RV comme un smartphone Android, -Google Daydream, Oculus Go, Oculus Rift, Vive, Samsung Gear VR, un iPhone avec un -navigateur WebXR.

-

Ensuite, si vous exécutez localement, vous devez exécuter un simple serveur web, comme -expliqué dans l'article sur la configuration.

-

Si l'appareil que vous utilisez pour visualiser la RV n'est pas le même ordinateur sur lequel vous -exécutez, vous devez servir votre page web via https, sinon le navigateur ne permettra pas d'utiliser -l'API WebXR. Le serveur mentionné dans l'article sur la configuration -appelé Servez a une option pour utiliser https. -Cochez-le et démarrez le serveur.

-
- -

Notez les URL. Vous avez besoin de celle qui correspond à l'adresse IP locale de votre ordinateur. -Elle commencera généralement par 192, 172 ou 10. Saisissez cette adresse complète, y compris la partie https:// -dans le navigateur de votre appareil RV. Note : Votre ordinateur et votre appareil RV doivent être sur le même réseau local -ou WiFi, et vous devez probablement être sur un réseau domestique. note : De nombreux cafés sont configurés pour interdire ce type -de connexion machine à machine.

-

Vous serez accueilli par une erreur ressemblant à celle ci-dessous. Cliquez sur "avancé" puis cliquez sur -continuer.

-
- -

Vous pouvez maintenant exécuter vos exemples.

-

Si vous vous lancez vraiment dans le développement WebXR, une autre chose que vous devriez apprendre est -le débogage à distance -afin de pouvoir voir les avertissements, les erreurs de console, et bien sûr, réellement -déboguer votre code.

-

Si vous voulez juste voir le code fonctionner ci-dessous, vous pouvez simplement exécuter le code depuis -ce site.

-

La première chose à faire est d'inclure le support RV après -avoir inclus three.js

-
import * as THREE from 'three';
-+import {VRButton} from 'three/addons/webxr/VRButton.js';
-
-

Ensuite, nous devons activer le support WebXR de three.js et ajouter son -bouton RV à notre page

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  renderer.xr.enabled = true;
-+  document.body.appendChild(VRButton.createButton(renderer));
-
-

Nous devons laisser three.js exécuter notre boucle de rendu. Jusqu'à présent, nous avons utilisé une -boucle requestAnimationFrame, mais pour supporter la RV, nous devons laisser three.js gérer -notre boucle de rendu pour nous. Nous pouvons le faire en appelant -WebGLRenderer.setAnimationLoop et en passant une fonction à appeler pour la boucle.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
--requestAnimationFrame(render);
-+renderer.setAnimationLoop(render);
-
-

Il y a un détail de plus. Nous devrions probablement définir une hauteur de caméra -qui soit à peu près moyenne pour un utilisateur debout.

-
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-+camera.position.set(0, 1.6, 0);
-
-

et déplacer les cubes pour qu'ils soient devant la caméra

-
const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-
-cube.position.x = x;
-+cube.position.y = 1.6;
-+cube.position.z = -2;
-
-

Nous les avons définis à z = -2 car la caméra sera maintenant à z = 0 et -la caméra par défaut regarde vers l'axe -z.

-

Cela soulève un point extrêmement important. Les unités en RV sont des mètres. -En d'autres termes, Une Unité = Un Mètre. Cela signifie que la caméra est à 1,6 mètres au-dessus de 0. -Les centres des cubes sont à 2 mètres devant la caméra. Chaque cube -a une taille de 1x1x1 mètre. C'est important car la RV doit ajuster les choses à l'utilisateur -dans le monde réel. Cela signifie que les unités utilisées dans three.js doivent correspondre -aux mouvements de l'utilisateur lui-même.

-

Et avec cela, nous devrions obtenir 3 cubes tournant devant -la caméra avec un bouton pour entrer en RV.

-

- -

-

Je trouve que la RV fonctionne mieux si nous avons quelque chose entourant la caméra, comme -une pièce pour référence, alors ajoutons une simple cubemap en grille comme nous l'avons vu dans -l'article sur les arrière-plans. Nous utiliserons simplement la même texture de grille -pour chaque côté du cube, ce qui donnera une salle en grille.

-
const scene = new THREE.Scene();
-+{
-+  const loader = new THREE.CubeTextureLoader();
-+  const texture = loader.load([
-+    'resources/images/grid-1024.png',
-+    'resources/images/grid-1024.png',
-+    'resources/images/grid-1024.png',
-+    'resources/images/grid-1024.png',
-+    'resources/images/grid-1024.png',
-+    'resources/images/grid-1024.png',
-+  ]);
-+  scene.background = texture;
-+}
-
-

C'est mieux.

-

- -

-

Note : Pour voir réellement la RV, vous aurez besoin d'un appareil compatible WebXR. -Je crois que la plupart des téléphones Android peuvent supporter WebXR en utilisant Chrome ou Firefox. -Pour iOS, vous pourriez pouvoir utiliser cette application WebXR, -bien qu'en général, le support WebXR sur iOS ne soit pas supporté en mai 2019.

-

Pour utiliser WebXR sur Android ou iPhone, vous aurez besoin d'un Casque RV -pour téléphones. Vous pouvez en trouver entre 5$ pour un fait de carton -et 100$. Malheureusement, je ne sais pas lesquels recommander. J'en ai acheté -6 au fil des ans et ils sont tous de qualité variable. Je n'ai -jamais payé plus d'environ 25$.

-

Juste pour mentionner quelques-uns des problèmes

-
    -
  1. Sont-ils compatibles avec votre téléphone

    -

    Les téléphones existent en différentes tailles et les casques RV doivent donc correspondre. -De nombreux casques prétendent correspondre à une grande variété de tailles. Mon expérience -est que plus ils correspondent à de tailles, moins ils sont performants, car au lieu -d'être conçus pour une taille spécifique, ils doivent faire des compromis -pour correspondre à plus de tailles. Malheureusement, les casques multi-tailles sont le type le plus courant.

    -
  2. -
  3. Peuvent-ils faire la mise au point pour votre visage

    -

    Certains appareils ont plus d'ajustements que d'autres. Généralement, il y a -au maximum 2 ajustements. La distance entre les lentilles et vos yeux -et la distance entre les lentilles.

    -
  4. -
  5. Sont-ils trop réfléchissants

    -

    De nombreux casques ont un cône en plastique entre votre œil et le téléphone. -Si ce plastique est brillant ou réfléchissant, il agira comme -un miroir reflétant l'écran et sera très distrayant.

    -

    Peu de critiques, voire aucune, ne semblent couvrir ce problème.

    -
  6. -
  7. Sont-ils confortables sur votre visage.

    -

    La plupart des appareils reposent sur votre nez comme une paire de lunettes. -Cela peut faire mal après quelques minutes. Certains ont des sangles qui passent -autour de votre tête. D'autres ont une 3ème sangle qui passe par-dessus votre tête. Cela -peut aider ou non à maintenir l'appareil au bon endroit.

    -

    Il s'avère que pour la plupart (tous ?) des appareils, vos yeux doivent être centrés -avec les lentilles. Si les lentilles sont légèrement au-dessus ou en dessous de vos -yeux, l'image devient floue. Cela peut être très frustrant -car les choses peuvent commencer nettes, mais 45 à 60 secondes plus tard, l'appareil -s'est déplacé de 1 millimètre vers le haut ou vers le bas et vous réalisez soudain que vous avez -lutté pour faire la mise au point sur une image floue.

    -
  8. -
  9. Sont-ils compatibles avec vos lunettes.

    -

    Si vous portez des lunettes, vous devrez lire les critiques pour voir -si un casque particulier fonctionne bien avec les lunettes.

    -
  10. -
-

Je ne peux vraiment pas faire de recommandations malheureusement. Google propose quelques recommandations -bon marché faites en carton, -certains à partir de 5$, alors peut-être commencer par là et si vous aimez, -envisagez de passer à la vitesse supérieure. 5$ c'est le prix d'un café, alors sérieusement, essayez !

-

Il existe également 3 types de dispositifs de base.

-
    -
  1. 3 degrés de liberté (3dof), pas de dispositif d'entrée

    -

    C'est généralement le style téléphone, bien que parfois vous puissiez -acheter un dispositif d'entrée tiers. Les 3 degrés de liberté -signifient que vous pouvez regarder vers le haut/bas (1), gauche/droite (2) et que vous pouvez incliner -la tête gauche et droite (3).

    -
  2. -
  3. 3 degrés de liberté (3dof) avec 1 dispositif d'entrée (3dof)

    -

    C'est fondamentalement Google Daydream et Oculus GO

    -

    Ceux-ci permettent également 3 degrés de liberté et incluent un petit -contrôleur qui agit comme un pointeur laser dans la RV. -Le pointeur laser n'a également que 3 degrés de liberté. Le -système peut dire dans quelle direction le dispositif d'entrée pointe, mais -il ne peut pas dire où se trouve le dispositif.

    -
  4. -
  5. 6 degrés de liberté (6dof) avec dispositifs d'entrée (6dof)

    -

    Ceux-ci sont le vrai truc haha. 6 degrés de liberté -signifie que non seulement ces appareils savent dans quelle direction vous regardez, -mais ils savent aussi où se trouve réellement votre tête. Cela signifie que -si vous vous déplacez de gauche à droite ou d'avant en arrière ou si vous vous levez / vous asseyez, -les appareils peuvent enregistrer cela et tout dans la RV se déplace en conséquence. -C'est incroyablement et étonnamment réaliste. Avec une bonne démo, -vous serez époustouflé, ou du moins je l'ai été et je le suis toujours.

    -

    De plus, ces appareils incluent généralement 2 contrôleurs, un -pour chaque main, et le système peut dire exactement où se trouvent vos -mains et dans quelle orientation elles sont, de sorte que vous pouvez -manipuler des choses en RV en tendant simplement la main, touchant, -poussant, tournant, etc...

    -

    Les appareils à 6 degrés de liberté incluent le Vive et Vive Pro, -l'Oculus Rift et Quest, et je crois tous les appareils Windows MR.

    -
  6. -
-

Avec tout cela couvert, je ne sais pas avec certitude quels appareils fonctionneront avec WebXR. -Je suis sûr à 99% que la plupart des téléphones Android fonctionneront avec Chrome. Vous pourriez -avoir besoin d'activer le support WebXR dans about:flags. Je sais aussi que Google -Daydream fonctionnera également et de même, vous devez activer le support WebXR dans -about:flags. Oculus Rift, Vive et Vive Pro fonctionneront via -Chrome ou Firefox. Je suis moins sûr pour Oculus Go et Oculus Quest car les deux -utilisent des systèmes d'exploitation personnalisés, mais selon Internet, ils semblent tous deux fonctionner.

-

Bien, après cette longue digression sur les dispositifs RV et WebXR, il y a certaines choses à couvrir

-
    -
  • Prise en charge de la RV et de la non-RV

    -

    Pour autant que je sache, du moins depuis la version r112, il n'y a pas de moyen simple de prendre en charge -les modes RV et non-RV avec three.js. Idéalement, -si vous n'êtes pas en mode RV, vous devriez pouvoir contrôler la caméra en utilisant -les moyens que vous souhaitez, par exemple les OrbitControls, -et vous devriez obtenir un événement lors du passage en mode RV et -de la sortie du mode RV afin que vous puissiez activer/désactiver les contrôles.

    -
  • -
-

Si three.js ajoute un support pour faire les deux, j'essaierai de mettre à jour -cet article. En attendant, vous pourriez avoir besoin de 2 versions de votre -site OU de passer un drapeau dans l'URL, quelque chose comme

-
https://mysite.com/mycooldemo?allowvr=true
-

Alors nous pourrions ajouter des liens pour changer de mode

-
<body>
-  <canvas id="c"></canvas>
-+  <div class="mode">
-+    <a href="?allowvr=true" id="vr">Autoriser la RV</a>
-+    <a href="?" id="nonvr">Utiliser le mode non-RV</a>
-+  </div>
-</body>
-
-

et du CSS pour les positionner

-
body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-}
-+.mode {
-+  position: absolute;
-+  right: 1em;
-+  top: 1em;
-+}
-
-

dans votre code, vous pourriez utiliser ce paramètre comme ceci

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
--  renderer.xr.enabled = true;
--  document.body.appendChild(VRButton.createButton(renderer));
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 1.6, 0);
-
-+  const params = (new URL(document.location)).searchParams;
-+  const allowvr = params.get('allowvr') === 'true';
-+  if (allowvr) {
-+    renderer.xr.enabled = true;
-+    document.body.appendChild(VRButton.createButton(renderer));
-+    document.querySelector('#vr').style.display = 'none';
-+  } else {
-+    // no VR, add some controls
-+    const controls = new OrbitControls(camera, canvas);
-+    controls.target.set(0, 1.6, -2);
-+    controls.update();
-+    document.querySelector('#nonvr').style.display = 'none';
-+  }
-
-

Que ce soit bon ou mauvais, je ne sais pas. J'ai l'impression que les différences -entre ce qui est nécessaire pour la RV et ce qui est nécessaire pour la non-RV sont souvent -très différentes, donc pour tout sauf les choses les plus simples, peut-être que 2 pages séparées -sont meilleures ? Vous devrez décider.

-

Note : pour diverses raisons, cela ne fonctionnera pas dans l'éditeur en direct -sur ce site, donc si vous voulez le vérifier, -cliquez ici. -Il devrait démarrer en mode non-RV et vous pouvez utiliser la souris ou les doigts pour déplacer -la caméra. Cliquer sur "Autoriser la RV" devrait basculer pour permettre le mode RV et vous devriez -pouvoir cliquer sur "Entrer en RV" si vous êtes sur un dispositif RV.

-
    -
  • Décider du niveau de support RV

    -

    Ci-dessus, nous avons couvert 3 types de dispositifs RV.

    -
      -
    • 3DOF sans entrée
    • -
    • 3DOF + entrée 3DOF
    • -
    • 6DOF + entrée 6DOF
    • -
    -

    Vous devez décider combien d'efforts vous êtes prêt à investir -pour supporter chaque type de dispositif.

    -

    Par exemple, le dispositif le plus simple n'a pas d'entrée. Le mieux que vous puissiez -généralement faire est de faire en sorte qu'il y ait des boutons ou des objets dans la vue de l'utilisateur -et si l'utilisateur aligne un marqueur au centre de l'affichage -sur ces objets pendant une demi-seconde environ, alors ce bouton est cliqué. -Une UX courante consiste à afficher un petit minuteur qui apparaîtra au-dessus de l'objet indiquant -que si vous maintenez le marqueur à cet endroit pendant un moment, l'objet/bouton sera sélectionné.

    -

    Puisqu'il n'y a pas d'autre entrée, c'est à peu près le mieux que vous puissiez faire

    -

    Au niveau supérieur, vous avez un dispositif d'entrée 3DOF. Généralement, il -peut pointer vers des choses et l'utilisateur dispose d'au moins 2 boutons. Le Daydream -possède également un pavé tactile qui fournit des entrées tactiles normales.

    -

    Dans tous les cas, si un utilisateur dispose de ce type d'appareil, il est beaucoup plus -confortable pour l'utilisateur de pouvoir pointer les choses avec -son contrôleur que de devoir le faire avec sa tête en regardant les choses.

    -

    Un niveau similaire pourrait être un appareil 3DOF ou 6DOF avec un -contrôleur de console de jeu. Vous devrez décider quoi faire ici. -Je soupçonne que la chose la plus courante est que l'utilisateur doit toujours regarder -pour pointer et le contrôleur est juste utilisé pour les boutons.

    -

    Le dernier niveau est un utilisateur avec un casque 6DOF et 2 contrôleurs 6DOF. -Ces utilisateurs trouveront souvent une expérience qui n'est que 3DOF -frustrante. De même, ils s'attendent généralement à pouvoir -manipuler virtuellement des choses avec leurs mains en RV, donc vous devrez -décider si vous voulez supporter cela ou non.

    -
  • -
-

Comme vous pouvez le voir, commencer en RV est assez facile, mais réaliser quelque chose de livrable en RV -nécessitera beaucoup de décisions et de conception.

-

Ceci était une brève introduction à la RV avec three.js. Nous aborderons -certaines méthodes d'entrée dans des articles futurs.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/webxr-look-to-select.html b/manual/fr/webxr-look-to-select.html deleted file mode 100644 index bf60125decee3f..00000000000000 --- a/manual/fr/webxr-look-to-select.html +++ /dev/null @@ -1,388 +0,0 @@ - - - VR - Sélection par le regard - - - - - - - - - - - - - -
-
-

VR - Sélection par le regard

-
-
-
-

NOTE : Les exemples de cette page nécessitent un appareil compatible VR. Sans cela, ils ne fonctionneront pas. Voir l'article précédent pour comprendre pourquoi.

-

Dans l'article précédent, nous avons abordé un exemple VR très simple utilisant three.js et nous avons discuté des différents types de systèmes VR.

-

Le plus simple et probablement le plus courant est le style VR Google Cardboard qui consiste essentiellement en un téléphone placé dans un masque facial coûtant entre 5 et 50 dollars. Ce type de VR n'a pas de contrôleur, les gens doivent donc trouver des solutions créatives pour permettre l'entrée utilisateur.

-

La solution la plus courante est la "sélection par le regard" où si l'utilisateur pointe sa tête vers quelque chose pendant un moment, cela est sélectionné.

-

Implémentons la "sélection par le regard" ! Nous allons commencer par un exemple de l'article précédent et pour ce faire, nous ajouterons le PickHelper que nous avons créé dans l'article sur le picking. Le voici.

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // restaurer la couleur s'il y a un objet sélectionné
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // lancer un rayon à travers le frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // obtenir la liste des objets intersectés par le rayon
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // sélectionner le premier objet. C'est le plus proche
-      this.pickedObject = intersectedObjects[0].object;
-      // sauvegarder sa couleur
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // définir sa couleur d'émission sur rouge/jaune clignotant
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

Pour une explication de ce code, voir l'article sur le picking.

-

Pour l'utiliser, il suffit de créer une instance et de l'appeler dans notre boucle de rendu.

-
+const pickHelper = new PickHelper();
-
-...
-function render(time) {
-  time *= 0.001;
-
-  ...
-
-+  // 0, 0 est le centre de la vue en coordonnées normalisées.
-+  pickHelper.pick({x: 0, y: 0}, scene, camera, time);
-
-

Dans l'exemple de picking original, nous avons converti les coordonnées de la souris des pixels CSS en coordonnées normalisées qui vont de -1 à +1 sur le canevas.

-

Dans ce cas, cependant, nous sélectionnerons toujours l'endroit où la caméra est dirigée, c'est-à-dire le centre de l'écran, nous passons donc 0 pour x et y, ce qui correspond au centre en coordonnées normalisées.

-

Et avec cela, les objets clignoteront lorsque nous les regarderons.

-

- -

-

Généralement, nous ne voulons pas que la sélection soit immédiate. Au lieu de cela, nous demandons à l'utilisateur de maintenir la caméra sur l'objet qu'il souhaite sélectionner pendant quelques instants afin de lui donner une chance de ne pas sélectionner quelque chose par accident.

-

Pour ce faire, nous avons besoin d'une sorte de compteur ou de jauge ou d'un moyen quelconque pour indiquer que l'utilisateur doit continuer à regarder et pendant combien de temps.

-

Une façon simple de procéder est de créer une texture à 2 couleurs et d'utiliser un décalage de texture pour faire glisser la texture sur un modèle.

-

Faisons cela séparément pour voir comment cela fonctionne avant de l'ajouter à l'exemple VR.

-

Tout d'abord, nous créons une OrthographicCamera.

-
const left = -2;    // Utiliser les valeurs pour gauche
-const right = 2;    // droite, haut et bas
-const top = 1;      // qui correspondent à la taille
-const bottom = -1;  // par défaut du canevas.
-const near = -1;
-const far = 1;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-
-

Et bien sûr, la mettre à jour si la taille du canevas change.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    const aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.left = -aspect;
-+    camera.right = aspect;
-    camera.updateProjectionMatrix();
-  }
-  ...
-
-

Nous avons maintenant une caméra qui montre 2 unités au-dessus et en dessous du centre et des unités d'aspect à gauche et à droite.

-

Ensuite, créons une texture à 2 couleurs. Nous utiliserons une DataTexture que nous avons utilisée à quelques autres endroits.

-
function makeDataTexture(data, width, height) {
-  const texture = new THREE.DataTexture(data, width, height, THREE.RGBAFormat);
-  texture.minFilter = THREE.NearestFilter;
-  texture.magFilter = THREE.NearestFilter;
-  texture.needsUpdate = true;
-  return texture;
-}
-
-const cursorColors = new Uint8Array([
-  64, 64, 64, 64,       // gris foncé
-  255, 255, 255, 255,   // blanc
-]);
-const cursorTexture = makeDataTexture(cursorColors, 2, 1);
-
-

Nous utiliserons ensuite cette texture sur une TorusGeometry.

-
const ringRadius = 0.4;
-const tubeRadius = 0.1;
-const tubeSegments = 4;
-const ringSegments = 64;
-const cursorGeometry = new THREE.TorusGeometry(
-    ringRadius, tubeRadius, tubeSegments, ringSegments);
-
-const cursorMaterial = new THREE.MeshBasicMaterial({
-  color: 'white',
-  map: cursorTexture,
-  transparent: true,
-  blending: THREE.CustomBlending,
-  blendSrc: THREE.OneMinusDstColorFactor,
-  blendDst: THREE.OneMinusSrcColorFactor,
-});
-const cursor = new THREE.Mesh(cursorGeometry, cursorMaterial);
-scene.add(cursor);
-
-

et ensuite dans render, ajustons le décalage de la texture.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    const aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.left = -aspect;
-    camera.right = aspect;
-    camera.updateProjectionMatrix();
-  }
-
-+  const fromStart = 0;
-+  const fromEnd = 2;
-+  const toStart = -0.5;
-+  const toEnd = 0.5;
-+  cursorTexture.offset.x = THREE.MathUtils.mapLinear(
-+      time % 2,
-+      fromStart, fromEnd,
-+      toStart, toEnd);
-
-  renderer.render(scene, camera);
-}
-
-

THREE.MathUtils.mapLinear prend une valeur qui se situe entre fromStart et fromEnd et la mappe à une valeur entre toStart et toEnd. Dans le cas ci-dessus, nous prenons time % 2, ce qui signifie une valeur qui va de 0 à 2 et la mappons à une valeur qui va de -0.5 à 0.5.

-

Les textures sont mappées à la géométrie en utilisant des coordonnées de texture normalisées qui vont de 0 à 1. Cela signifie que notre image de 2x1 pixels, définie sur le mode de répétition par défaut de THREE.ClampToEdge, si nous ajustons les coordonnées de texture de -0.5, alors toute la maille sera de la première couleur et si nous ajustons les coordonnées de texture de +0.5, toute la maille sera de la deuxième couleur. Entre les deux, avec le filtrage défini sur THREE.NearestFilter, nous pourrons déplacer la transition entre les 2 couleurs à travers la géométrie.

-

Ajoutons une texture d'arrière-plan tant que nous y sommes, comme nous l'avons vu dans l'article sur les arrière-plans. Nous utiliserons simplement un ensemble de couleurs 2x2, mais définirons les paramètres de répétition de la texture pour nous donner une grille 8x8. Cela donnera à notre curseur quelque chose sur lequel être rendu afin que nous puissions le vérifier par rapport à différentes couleurs.

-
+const backgroundColors = new Uint8Array([
-+    0,   0,   0, 255,  // noir
-+   90,  38,  38, 255,  // rouge foncé
-+  100, 175, 103, 255,  // vert moyen
-+  255, 239, 151, 255,  // jaune clair
-+]);
-+const backgroundTexture = makeDataTexture(backgroundColors, 2, 2);
-+backgroundTexture.wrapS = THREE.RepeatWrapping;
-+backgroundTexture.wrapT = THREE.RepeatWrapping;
-+backgroundTexture.repeat.set(4, 4);
-
-const scene = new THREE.Scene();
-+scene.background = backgroundTexture;
-
-

Maintenant, si nous exécutons cela, vous verrez que nous obtenons une jauge en forme de cercle et que nous pouvons définir où se trouve la jauge.

-

- -

-

Quelques points à noter et à essayer.

-
    -
  • Nous avons défini les propriétés blending, blendSrc et blendDst du cursorMaterial comme suit :

    -
      blending: THREE.CustomBlending,
    -  blendSrc: THREE.OneMinusDstColorFactor,
    -  blendDst: THREE.OneMinusSrcColorFactor,
    -

    Cela donne un effet de type inverse. Commentez ces 3 lignes et vous verrez la différence. Je suppose simplement que l'effet inverse est le meilleur ici, car de cette façon, nous pouvons, espérons-le, voir le curseur quelles que soient les couleurs sur lesquelles il se trouve.

    -
  • -
  • Nous utilisons une TorusGeometry et non une RingGeometry.

    -

    Pour une raison quelconque, la RingGeometry utilise un schéma de mappage UV plat. De ce fait, si nous utilisons une RingGeometry, la texture glisse horizontalement sur l'anneau au lieu de l'entourer comme c'est le cas ci-dessus.

    -

    Essayez, changez la TorusGeometry en une RingGeometry (elle est simplement commentée dans l'exemple ci-dessus) et vous verrez ce que je veux dire.

    -

    La chose la plus correcte à faire (selon une certaine définition de correct) serait soit d'utiliser la RingGeometry mais de corriger les coordonnées de texture pour qu'elles fassent le tour de l'anneau. Ou bien, générer notre propre géométrie d'anneau. Mais, le tore fonctionne très bien. Placé directement devant la caméra avec un MeshBasicMaterial, il ressemblera exactement à un anneau et les coordonnées de texture font le tour de l'anneau, donc cela fonctionne pour nos besoins.

    -
  • -
-

Intégrons-le avec notre code VR ci-dessus.

-
class PickHelper {
--  constructor() {
-+  constructor(camera) {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
--    this.pickedObjectSavedColor = 0;
-
-+    const cursorColors = new Uint8Array([
-+      64, 64, 64, 64,       // gris foncé
-+      255, 255, 255, 255,   // blanc
-+    ]);
-+    this.cursorTexture = makeDataTexture(cursorColors, 2, 1);
-+
-+    const ringRadius = 0.4;
-+    const tubeRadius = 0.1;
-+    const tubeSegments = 4;
-+    const ringSegments = 64;
-+    const cursorGeometry = new THREE.TorusGeometry(
-+        ringRadius, tubeRadius, tubeSegments, ringSegments);
-+
-+    const cursorMaterial = new THREE.MeshBasicMaterial({
-+      color: 'white',
-+      map: this.cursorTexture,
-+      transparent: true,
-+      blending: THREE.CustomBlending,
-+      blendSrc: THREE.OneMinusDstColorFactor,
-+      blendDst: THREE.OneMinusSrcColorFactor,
-+    });
-+    const cursor = new THREE.Mesh(cursorGeometry, cursorMaterial);
-+    // ajouter le curseur comme enfant de la caméra
-+    camera.add(cursor);
-+    // et le déplacer devant la caméra
-+    cursor.position.z = -1;
-+    const scale = 0.05;
-+    cursor.scale.set(scale, scale, scale);
-+    this.cursor = cursor;
-+
-+    this.selectTimer = 0;
-+    this.selectDuration = 2;
-+    this.lastTime = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-+    const elapsedTime = time - this.lastTime;
-+    this.lastTime = time;
-
--    // restore the color if there is a picked object
--    if (this.pickedObject) {
--      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
--      this.pickedObject = undefined;
--    }
-
-+    const lastPickedObject = this.pickedObject;
-+    this.pickedObject = undefined;
-
-    // lancer un rayon à travers le frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // obtenir la liste des objets intersectés par le rayon
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // sélectionner le premier objet. C'est le plus proche
-      this.pickedObject = intersectedObjects[0].object;
--      // save its color
--      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
--      // set its emissive color to flashing red/yellow
--      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-
-+    // afficher le curseur uniquement s'il touche quelque chose
-+    this.cursor.visible = this.pickedObject ? true : false;
-+
-+    let selected = false;
-+
-+    // si nous regardons le même objet qu'avant
-+    // incrémenter le minuteur de sélection
-+    if (this.pickedObject && lastPickedObject === this.pickedObject) {
-+      this.selectTimer += elapsedTime;
-+      if (this.selectTimer >= this.selectDuration) {
-+        this.selectTimer = 0;
-+        selected = true;
-+      }
-+    } else {
-+      this.selectTimer = 0;
-+    }
-+
-+    // définir le matériau du curseur pour afficher l'état du minuteur
-+    const fromStart = 0;
-+    const fromEnd = this.selectDuration;
-+    const toStart = -0.5;
-+    const toEnd = 0.5;
-+    this.cursorTexture.offset.x = THREE.MathUtils.mapLinear(
-+        this.selectTimer,
-+        fromStart, fromEnd,
-+        toStart, toEnd);
-+
-+    return selected ? this.pickedObject : undefined;
-  }
-}
-
-

Vous pouvez voir dans le code ci-dessus que nous avons ajouté tout le code pour créer la géométrie, la texture et le matériau du curseur, et nous l'avons ajouté comme enfant de la caméra afin qu'il soit toujours devant la caméra. Notez que nous devons ajouter la caméra à la scène, sinon le curseur ne sera pas rendu.

-
+scene.add(camera);
-
-

Nous vérifions ensuite si l'objet que nous sélectionnons cette fois est le même que la dernière fois. Si c'est le cas, nous ajoutons le temps écoulé à un minuteur et si le minuteur atteint sa limite, nous retournons l'élément sélectionné.

-

Maintenant, utilisons cela pour sélectionner les cubes. Comme simple exemple, nous allons ajouter également 3 sphères. Lorsqu'un cube est sélectionné, nous cachons le cube et révélons la sphère correspondante.

-

Donc, d'abord, nous allons créer une géométrie de sphère.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
--const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-+const boxGeometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-+
-+const sphereRadius = 0.5;
-+const sphereGeometry = new THREE.SphereGeometry(sphereRadius);
-
-

Ensuite, créons 3 paires de maillages (meshes) boîte et sphère. Nous utiliserons une Map afin de pouvoir associer chaque Mesh à son partenaire.

-
-const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
--];
-+const meshToMeshMap = new Map();
-+[
-+  { x:  0, boxColor: 0x44aa88, sphereColor: 0xFF4444, },
-+  { x:  2, boxColor: 0x8844aa, sphereColor: 0x44FF44, },
-+  { x: -2, boxColor: 0xaa8844, sphereColor: 0x4444FF, },
-+].forEach((info) => {
-+  const {x, boxColor, sphereColor} = info;
-+  const sphere = makeInstance(sphereGeometry, sphereColor, x);
-+  const box = makeInstance(boxGeometry, boxColor, x);
-+  // cacher la sphère
-+  sphere.visible = false;
-+  // mapper la sphère à la boîte
-+  meshToMeshMap.set(box, sphere);
-+  // mapper la boîte à la sphère
-+  meshToMeshMap.set(sphere, box);
-+});
-
-

Dans render, où nous faisons tourner les cubes, nous devons itérer sur meshToMeshMap au lieu de cubes.

-
-cubes.forEach((cube, ndx) => {
-+let ndx = 0;
-+for (const mesh of meshToMeshMap.keys()) {
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
--  cube.rotation.x = rot;
--  cube.rotation.y = rot;
--});
-+  mesh.rotation.x = rot;
-+  mesh.rotation.y = rot;
-+  ++ndx;
-+}
-
-

Et maintenant, nous pouvons utiliser notre nouvelle implémentation de PickHelper pour sélectionner l'un des objets. Lorsqu'il est sélectionné, nous cachons cet objet et révélons son partenaire.

-
// 0, 0 est le centre de la vue en coordonnées normalisées.
--pickHelper.pick({x: 0, y: 0}, scene, camera, time);
-+const selectedObject = pickHelper.pick({x: 0, y: 0}, scene, camera, time);
-+if (selectedObject) {
-+  selectedObject.visible = false;
-+  const partnerObject = meshToMeshMap.get(selectedObject);
-+  partnerObject.visible = true;
-+}
-
-

Et avec cela, nous devrions avoir une implémentation assez correcte de la sélection par le regard.

-

- -

-

J'espère que cet exemple vous a donné quelques idées sur la façon d'implémenter une interface utilisateur de type "sélection par le regard" au niveau de Google Cardboard. Faire glisser des textures en utilisant les décalages des coordonnées de texture est également une technique couramment utile.

-

Ensuite, permettons à l'utilisateur disposant d'un contrôleur VR de pointer et de déplacer des objets.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/fr/webxr-point-to-select.html b/manual/fr/webxr-point-to-select.html deleted file mode 100644 index 87dd35db187cb9..00000000000000 --- a/manual/fr/webxr-point-to-select.html +++ /dev/null @@ -1,347 +0,0 @@ - - - VR - Sélection par Pointage 3DOF - - - - - - - - - - - - - -
-
-

VR - Sélection par Pointage 3DOF

-
-
-
-

NOTE : Les exemples sur cette page nécessitent un appareil compatible VR avec un dispositif de pointage. Sans cela, ils ne fonctionneront pas. Voir cet article pour comprendre pourquoi.

-

Dans l'article précédent, nous avons examiné un exemple VR très simple où l'utilisateur pouvait choisir des éléments en pointant via le regard. Dans cet article, nous irons un peu plus loin et laisserons l'utilisateur choisir avec un dispositif de pointage.

-

Three.js rend les choses relativement faciles en fournissant 2 objets contrôleurs en VR et essaie de gérer les deux cas : un seul contrôleur 3DOF et deux contrôleurs 6DOF. Chacun des contrôleurs est un objet Object3D qui donne l'orientation et la position de ce contrôleur. Ils fournissent également les événements selectstart, select et selectend lorsque l'utilisateur commence à appuyer, appuie, et cesse d'appuyer (termine) sur le bouton "principal" du contrôleur.

-

En partant du dernier exemple de l'article précédent, changeons le PickHelper en un ControllerPickHelper.

-

Notre nouvelle implémentation émettra un événement select qui nous donnera l'objet qui a été sélectionné, donc pour l'utiliser, nous aurons juste besoin de faire ceci.

-
const pickHelper = new ControllerPickHelper(scene);
-pickHelper.addEventListener('select', (event) => {
-  event.selectedObject.visible = false;
-  const partnerObject = meshToMeshMap.get(event.selectedObject);
-  partnerObject.visible = true;
-});
-
-

Rappelez-vous de notre code précédent : meshToMeshMap mappe nos boîtes et sphères les unes aux autres, donc si nous en avons une, nous pouvons trouver son partenaire via meshToMeshMap. Ici, nous cachons simplement l'objet sélectionné et rendons son partenaire visible.

-

Quant à l'implémentation réelle de ControllerPickHelper, nous devons d'abord ajouter les objets contrôleurs VR à la scène et y ajouter des lignes 3D que nous pouvons utiliser pour afficher où l'utilisateur pointe. Nous sauvegardons à la fois les contrôleurs et leurs lignes.

-
class ControllerPickHelper {
-  constructor(scene) {
-    const pointerGeometry = new THREE.BufferGeometry().setFromPoints([
-      new THREE.Vector3(0, 0, 0),
-      new THREE.Vector3(0, 0, -1),
-    ]);
-
-    this.controllers = [];
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
-      scene.add(controller);
-
-      const line = new THREE.Line(pointerGeometry);
-      line.scale.z = 5;
-      controller.add(line);
-      this.controllers.push({controller, line});
-    }
-  }
-}
-
-

Sans rien faire d'autre, cela seul nous donnerait 1 ou 2 lignes dans la scène montrant où se trouvent les dispositifs de pointage de l'utilisateur et dans quelle direction ils pointent.

-

Cependant, nous avons un problème : nous ne voulons pas que notre RayCaster sélectionne la ligne elle-même. Une solution facile est de séparer les objets que nous voulions pouvoir sélectionner des objets que nous ne voulons pas en les plaçant sous un autre Object3D.

-
const scene = new THREE.Scene();
-+// objet pour placer les objets sélectionnables afin de pouvoir les
-+// séparer facilement des objets non sélectionnables
-+const pickRoot = new THREE.Object3D();
-+scene.add(pickRoot);
-
-...
-
-function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
--  scene.add(cube);
-+  pickRoot.add(cube);
-
-...
-
-

Ajoutons ensuite du code pour sélectionner à partir des contrôleurs. C'est la première fois que nous sélectionnons avec autre chose que la caméra. Dans notre article sur la sélection, l'utilisateur utilise la souris ou le doigt pour sélectionner, ce qui signifie que la sélection provient de la caméra vers l'écran. Dans l'article précédent, nous sélectionnions en fonction de la direction dans laquelle l'utilisateur regardait, donc cela venait aussi de la caméra. Cette fois, cependant, nous sélectionnons à partir de la position des contrôleurs, donc nous n'utilisons pas la caméra.

-
class ControllerPickHelper {
-  constructor(scene) {
-+    this.raycaster = new THREE.Raycaster();
-+    this.objectToColorMap = new Map();
-+    this.controllerToObjectMap = new Map();
-+    this.tempMatrix = new THREE.Matrix4();
-
-    const pointerGeometry = new THREE.BufferGeometry().setFromPoints([
-      new THREE.Vector3(0, 0, 0),
-      new THREE.Vector3(0, 0, -1),
-    ]);
-
-    this.controllers = [];
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
-      scene.add(controller);
-
-      const line = new THREE.Line(pointerGeometry);
-      line.scale.z = 5;
-      controller.add(line);
-      this.controllers.push({controller, line});
-    }
-+  update(pickablesParent, time) {
-+    this.reset();
-+    for (const {controller, line} of this.controllers) {
-+      // lancer un rayon depuis le contrôleur
-+      this.tempMatrix.identity().extractRotation(controller.matrixWorld);
-+      this.raycaster.ray.origin.setFromMatrixPosition(controller.matrixWorld);
-+      this.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(this.tempMatrix);
-+      // obtenir la liste des objets intersectés par le rayon
-+      const intersections = this.raycaster.intersectObjects(pickablesParent.children);
-+      if (intersections.length) {
-+        const intersection = intersections[0];
-+        // faire en sorte que la ligne touche l'objet
-+        line.scale.z = intersection.distance;
-+        // sélectionner le premier objet. C'est le plus proche
-+        const pickedObject = intersection.object;
-+        // sauvegarder quel objet ce contrôleur a sélectionné
-+        this.controllerToObjectMap.set(controller, pickedObject);
-+        // mettre en évidence l'objet si ce n'est pas déjà fait
-+        if (this.objectToColorMap.get(pickedObject) === undefined) {
-+          // sauvegarder sa couleur
-+          this.objectToColorMap.set(pickedObject, pickedObject.material.emissive.getHex());
-+          // définir sa couleur émissive en rouge/jaune clignotant
-+          pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFF2000 : 0xFF0000);
-+        }
-+      } else {
-+        line.scale.z = 5;
-+      }
-+    }
-+  }
-}
-
-

Comme précédemment, nous utilisons un Raycaster, mais cette fois, nous prenons le rayon depuis le contrôleur. Dans notre précédent PickHelper, il n'y avait qu'une seule chose pour la sélection, mais ici nous avons jusqu'à 2 contrôleurs, un pour chaque main. Nous sauvegardons l'objet que chaque contrôleur regarde dans controllerToObjectMap. Nous sauvegardons également la couleur émissive d'origine dans objectToColorMap et nous faisons en sorte que la ligne soit assez longue pour toucher ce vers quoi elle pointe.

-

Nous devons ajouter du code pour réinitialiser ces paramètres à chaque image.

-
class ControllerPickHelper {
-
-  ...
-
-+  _reset() {
-+    // restaurer les couleurs
-+    this.objectToColorMap.forEach((color, object) => {
-+      object.material.emissive.setHex(color);
-+    });
-+    this.objectToColorMap.clear();
-+    this.controllerToObjectMap.clear();
-+  }
-  update(pickablesParent, time) {
-+    this._reset();
-
-    ...
-
-}
-
-

Ensuite, nous voulons émettre un événement select lorsque l'utilisateur clique sur le contrôleur. Pour ce faire, nous pouvons étendre l'EventDispatcher de three.js, puis nous vérifierons quand nous recevons un événement select du contrôleur. Si ce contrôleur pointe vers quelque chose, nous émettrons ce vers quoi le contrôleur pointe comme notre propre événement select.

-
-class ControllerPickHelper {
-+class ControllerPickHelper extends THREE.EventDispatcher {
-  constructor(scene) {
-+    super();
-    this.raycaster = new THREE.Raycaster();
--    this.objectToColorMap = new Map();  // object to save color and picked object
-+    this.objectToColorMap = new Map();  // objet pour sauvegarder la couleur et l'objet sélectionné
-    this.controllerToObjectMap = new Map();
-    this.tempMatrix = new THREE.Matrix4();
-
-    const pointerGeometry = new THREE.BufferGeometry().setFromPoints([
-      new THREE.Vector3(0, 0, 0),
-      new THREE.Vector3(0, 0, -1),
-    ]);
-
-    this.controllers = [];
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
-+      controller.addEventListener('select', (event) => {
-+        const controller = event.target;
-+        const selectedObject = this.controllerToObjectMap.get(controller);
-+        if (selectedObject) {
-+          this.dispatchEvent({type: 'select', controller, selectedObject});
-+        }
-+      });
-      scene.add(controller);
-
-      const line = new THREE.Line(pointerGeometry);
-      line.scale.z = 5;
-      controller.add(line);
-      this.controllers.push({controller, line});
-    }
-  }
-}
-
-

Il ne reste plus qu'à appeler update dans notre boucle de rendu.

-
function render(time) {
-
-  ...
-
-+  pickHelper.update(pickablesParent, time);
-
-  renderer.render(scene, camera);
-}
-
-

et en supposant que vous ayez un appareil VR avec un contrôleur, vous devriez pouvoir utiliser les contrôleurs pour sélectionner des éléments.

-

- -

-

Et si nous voulions pouvoir déplacer les objets ?

-

C'est relativement facile. Déplaçons notre code d'écouteur 'select' du contrôleur dans une fonction afin de pouvoir l'utiliser pour plus d'une chose.

-
class ControllerPickHelper extends THREE.EventDispatcher {
-  constructor(scene) {
-    super();
-
-    ...
-
-    this.controllers = [];
-
-+    const selectListener = (event) => {
-+      const controller = event.target;
-+      const selectedObject = this.controllerToObjectMap.get(event.target);
-+      if (selectedObject) {
-+        this.dispatchEvent({type: 'select', controller, selectedObject});
-+      }
-+    };
-
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
--      controller.addEventListener('select', (event) => {
--        const controller = event.target;
--        const selectedObject = this.controllerToObjectMap.get(event.target);
--        if (selectedObject) {
--          this.dispatchEvent({type: 'select', controller, selectedObject});
--        }
--      });
-+      controller.addEventListener('select', selectListener);
-
-       ...
-
-

Utilisons-le ensuite pour selectstart et select.

-
class ControllerPickHelper extends THREE.EventDispatcher {
-  constructor(scene) {
-    super();
-
-    ...
-
-    this.controllers = [];
-
-    const selectListener = (event) => {
-      const controller = event.target;
-      const selectedObject = this.controllerToObjectMap.get(event.target);
-      if (selectedObject) {
--        this.dispatchEvent({type: 'select', controller, selectedObject});
-+        this.dispatchEvent({type: event.type, controller, selectedObject});
-      }
-    };
-
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
-      controller.addEventListener('select', selectListener);
-      controller.addEventListener('selectstart', selectListener);
-
-       ...
-
-

et transmettons également l'événement selectend que three.js envoie lorsque l'utilisateur relâche le bouton du contrôleur.

-
class ControllerPickHelper extends THREE.EventDispatcher {
-  constructor(scene) {
-    super();
-
-    ...
-
-    this.controllers = [];
-
-    const selectListener = (event) => {
-      const controller = event.target;
-      const selectedObject = this.controllerToObjectMap.get(event.target);
-      if (selectedObject) {
-        this.dispatchEvent({type: event.type, controller, selectedObject});
-      }
-    };
-
-+    const endListener = (event) => {
-+      const controller = event.target;
-+      this.dispatchEvent({type: event.type, controller});
-+    };
-
-    for (let i = 0; i < 2; ++i) {
-      const controller = renderer.xr.getController(i);
-      controller.addEventListener('select', selectListener);
-      controller.addEventListener('selectstart', selectListener);
-+      controller.addEventListener('selectend', endListener);
-
-       ...
-
-

Maintenant, modifions le code de manière à ce que, lorsque nous recevons un événement selectstart, nous retirions l'objet sélectionné de la scène et en fassions un enfant du contrôleur. Cela signifie qu'il se déplacera avec le contrôleur. Lorsque nous recevrons un événement selectend, nous le remettrons dans la scène.

-
const pickHelper = new ControllerPickHelper(scene);
--pickHelper.addEventListener('select', (event) => {
--  event.selectedObject.visible = false;
--  const partnerObject = meshToMeshMap.get(event.selectedObject);
--  partnerObject.visible = true;
--});
-
-+const controllerToSelection = new Map();
-+pickHelper.addEventListener('selectstart', (event) => {
-+  const {controller, selectedObject} = event;
-+  const existingSelection = controllerToSelection.get(controller);
-+  if (!existingSelection) {
-+    controllerToSelection.set(controller, {
-+      object: selectedObject,
-+      parent: selectedObject.parent,
-+    });
-+    controller.attach(selectedObject);
-+  }
-+});
-+
-+pickHelper.addEventListener('selectend', (event) => {
-+  const {controller} = event;
-+  const selection = controllerToSelection.get(controller);
-+  if (selection) {
-+    controllerToSelection.delete(controller);
-+    selection.parent.attach(selection.object);
-+  }
-+});
-
-

Lorsqu'un objet est sélectionné, nous sauvegardons cet objet et son parent d'origine. Lorsque l'utilisateur a terminé, nous pouvons remettre l'objet en place.

-

Nous utilisons Object3D.attach pour changer le parent des objets sélectionnés. Ces fonctions nous permettent de modifier le parent d'un objet sans modifier son orientation et sa position dans la scène.

-

Et avec cela, nous devrions pouvoir déplacer les objets avec un contrôleur 6DOF ou au moins changer leur orientation avec un contrôleur 3DOF.

-

- -

-

Pour être honnête, je ne suis pas sûr à 100 % que ce ControllerPickHelper soit la meilleure façon d'organiser le code, mais il est utile pour démontrer les différentes parties nécessaires pour faire fonctionner quelque chose de simple en VR avec three.js.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/index.html b/manual/index.html index e3091f1d7acfdb..e535f5decfbb33 100644 --- a/manual/index.html +++ b/manual/index.html @@ -33,14 +33,6 @@

three.js

-

@@ -72,37 +64,7 @@

three.js

const list = await ( await fetch( 'list.json' ) ).json(); - const hash = window.location.hash.substring( 1 ); - - // Localization - - let language = 'en'; - - const hashLanguage = /^(.*?)\//.exec( hash ); - - if ( hashLanguage ) { - - language = hashLanguage[ 1 ]; - - } - - const languageSelect = document.querySelector( '#language' ); - languageSelect.value = language; - languageSelect.addEventListener( 'change', function () { - - setLanguage( this.value ); - - } ); - - function setLanguage( value ) { - - language = value; - - createNavigation( list, language ); - updateFilter(); - autoChangeUrlLanguage( language ); - - } + redirectLegacyLanguage(); // Functionality for hamburger button (on small devices) @@ -157,14 +119,28 @@

three.js

window.onpopstate = function () { + redirectLegacyLanguage(); updateNavigation(); createNewIframe(); }; + // Redirect legacy localized deep links entered directly in the address bar + + window.addEventListener( 'hashchange', function () { + + if ( redirectLegacyLanguage() ) { + + updateNavigation(); + createNewIframe(); + + } + + } ); + // Create the navigation panel and configure the iframe - createNavigation( list, language ); + createNavigation( list ); createNewIframe(); // Handle search query @@ -186,7 +162,7 @@

three.js

function createLink( pageName, pageURL ) { const link = document.createElement( 'a' ); - const url = new URL( pageURL, window.location.href ); + const url = new URL( 'pages/' + pageURL, window.location.href ); url.pathname += '.html'; link.href = url.href; link.textContent = pageName; @@ -206,7 +182,7 @@

three.js

} - function createNavigation( list, language ) { + function createNavigation( list ) { if ( navigation !== undefined ) { @@ -219,13 +195,7 @@

three.js

navigation = document.createElement( 'div' ); content.appendChild( navigation ); - if ( language === 'ar' ) { - - navigation.style.direction = 'rtl'; - - } - - const categories = list[ language ]; + const categories = list; const selectedPage = window.location.hash.substring( 1 ).replace( /\.html$/, '' ); for ( const category in categories ) { @@ -302,7 +272,7 @@

three.js

content.querySelectorAll( 'a' ).forEach( function ( item ) { - if ( item.href.includes( selectedPage ) ) { + if ( selectedPage !== '' && item.href.includes( selectedPage ) ) { item.classList.add( 'selected' ); @@ -316,17 +286,6 @@

three.js

} - // Auto change language url. If a reader open a document in English, when they click "zh", the document they read will auto change into Chinese version - - function autoChangeUrlLanguage( language ) { - - const hash = location.hash; - if ( hash === '' ) return; - const docLink = hash.slice( hash.indexOf( '/' ) ); - location.href = '#' + language + docLink; - - } - // Filtering function extractQuery() { @@ -445,7 +404,7 @@

three.js

const [ , base, path ] = m; if ( base.includes( 'manual' ) ) { - const newHash = `#${ path.replace( '.html', '' ) }`; + const newHash = `#${ path.replace( 'pages/', '' ).replace( '.html', '' ) }`; // Only create new iframe if we're actually changing pages. // We could just be going to an anchor on the same page. const newPrefix = newHash.split( '#' )[ 1 ]; @@ -481,6 +440,25 @@

three.js

} + function redirectLegacyLanguage() { + + // Legacy language-qualified deep links (e.g. #en/installation, #fr/installation) + // now resolve to the language-neutral URL (e.g. #installation). + + const legacyLanguage = /^#(en|fr|ja|ko|ru|zh)(\/|$)/; + + if ( legacyLanguage.test( window.location.hash ) ) { + + window.history.replaceState( null, '', window.location.hash.replace( legacyLanguage, '#' ) ); + + return true; + + } + + return false; + + } + function createNewIframe() { // Change the content displayed in the iframe @@ -503,18 +481,18 @@

three.js

// We can have 2 hashes. One for the main page, one for the page it's referencing // In other words - // #en/somePage#someSectionOfPage + // #somePage#someSectionOfPage const subHash = splitHash[ 0 ].indexOf( '#' ); let src; if ( subHash >= 0 ) { const beforeSubHash = splitHash[ 0 ].slice( 0, subHash ); const afterSubHash = splitHash[ 0 ].slice( subHash ); - src = `${beforeSubHash}.html${afterSubHash}${splitHash[ 1 ]}`; + src = `pages/${beforeSubHash}.html${afterSubHash}${splitHash[ 1 ]}`; } else { - src = splitHash[ 0 ] + '.html' + splitHash[ 1 ]; + src = 'pages/' + splitHash[ 0 ] + '.html' + splitHash[ 1 ]; } diff --git a/manual/ja/align-html-elements-to-3d.html b/manual/ja/align-html-elements-to-3d.html deleted file mode 100644 index f918af1c8f22ae..00000000000000 --- a/manual/ja/align-html-elements-to-3d.html +++ /dev/null @@ -1,701 +0,0 @@ - - - でHTML要素を3Dに揃える - - - - - - - - - - - - - -
-
-

でHTML要素を3Dに揃える

-
-
-
-

この記事はThree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでいない場合、そこから始めると良いかもしれません。

-

3Dシーンにテキスト表示させたい場合があると思います。 -メリットとデメリットを持つ多くの方法があります。

-
    -
  • 3Dテキストを使用する

    -

    プリミティブの記事を見ると TextGeometry があり、3Dテキストが作れます。 -ロゴを飛ばすには便利ですが、統計や情報、ラベル付けなどにはあまり便利でないかもしれません。

    -
  • -
  • テキストが描かれたテクスチャを使用する

    -

    この記事ではキャンバスをテクスチャとして使いました。 -キャンバスにテキストを描画してビルボードとして表示できます。 -この方法のメリットは、3Dシーンにテキストが組み込まれている事かもしれません。 -3Dシーンの中でPC端末のようなものを描画するには最適かもしれません。

    -
  • -
  • HTML要素を3D空間に合わせて配置する

    -

    この方法のメリットは全てのHTMLを使えます。 -HTMLは複数の要素を持てます。 -また、CSSでスタイルを整えられます。 -実際のテキストなのでユーザーが選択する事もできます。

    -
  • -
-

この記事では、HTML要素を3D空間に合わせて配置を取り上げます。

-

まずは簡単に始めてみましょう。 -いくつかのプリミティブで3Dシーンを作り、それぞれのプリミティブにラベルを付けます。 -レスポンシブの記事の例を使います。

-

ライティングの記事のように OrbitControls を追加します。

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 0, 0);
-controls.update();
-
-

ラベル要素を含むHTML要素を追加します。

-
<body>
--  <canvas id="c"></canvas>
-+  <div id="container">
-+    <canvas id="c"></canvas>
-+    <div id="labels"></div>
-+  </div>
-</body>
-
-

キャンバスと <div id="labels"> の両方を親コンテナ配下に入れて、CSSで重なるように設定できます。

-
#c {
--    width: 100%;
--    height: 100%;
-+    width: 100%;  /* let our container decide our size */
-+    height: 100%;
-    display: block;
-}
-+#container {
-+  position: relative;  /* makes this the origin of its children */
-+  width: 100%;
-+  height: 100%;
-+  overflow: hidden;
-+}
-+#labels {
-+  position: absolute;  /* let us position ourself inside the container */
-+  left: 0;             /* make our position the top left of the container */
-+  top: 0;
-+  color: white;
-+}
-
-

ラベル自体にもCSSを追加しましょう。

-
#labels>div {
-  position: absolute;  /* let us position them inside the container */
-  left: 0;             /* make their default position the top left of the container */
-  top: 0;
-  cursor: pointer;     /* change the cursor to a hand when over us */
-  font-size: large;
-  user-select: none;   /* don't let the text get selected */
-  text-shadow:         /* create a black outline */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-#labels>div:hover {
-  color: red;
-}
-
-

HTMLに多くのラベル要素を追加する必要はありません。 -立方体を生成する関数 makeInstance があります。 -この関数にラベル要素も追加してみましょう。

-
+const labelContainerElem = document.querySelector('#labels');
-
--function makeInstance(geometry, color, x) {
-+function makeInstance(geometry, color, x, name) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const elem = document.createElement('div');
-+  elem.textContent = name;
-+  labelContainerElem.appendChild(elem);
-
--  return cube;
-+  return {cube, elem};
-}
-
-

立方体ごとに1つずつコンテナに <div> を追加しています。 -ラベルのために cubeelem の両方を持つオブジェクトを返します。

-

この関数を呼び出すには、ラベル名も指定する必要があります。

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
-+  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-];
-
-

あとはレンダリング時にラベル要素を配置します。

-
const tempV = new THREE.Vector3();
-
-...
-
--cubes.forEach((cube, ndx) => {
-+cubes.forEach((cubeInfo, ndx) => {
-+  const {cube, elem} = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-+  // get the position of the center of the cube
-+  cube.updateWorldMatrix(true, false);
-+  cube.getWorldPosition(tempV);
-+
-+  // get the normalized screen coordinate of that position
-+  // x and y will be in the -1 to +1 range with x = -1 being
-+  // on the left and y = -1 being on the bottom
-+  tempV.project(camera);
-+
-+  // convert the normalized position to CSS coordinates
-+  const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-+  const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-+
-+  // move the elem to that position
-+  elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-});
-
-

そして、ラベルを対応するオブジェクトに合わせて位置を指定します。

-

- -

-

動かしてみると対処したい問題がいくつか出ると思います。

-

1つの問題は、オブジェクトを回転させると全てのラベルが重なってしまいます。

-
- -

もう1つの問題は、オブジェクトが錐台の外に出るようにズームアウトしても、ラベルが消えずに表示されたままです。

-

オブジェクトが重なる問題の解決策はピッキング記事のピッキングコードを使います。 -画面上のオブジェクトの位置を入力し、RayCaster にどのオブジェクトが交差していたか教えてもらいます。 -オブジェクトが最初のものでなければ前面に表示されません。

-
const tempV = new THREE.Vector3();
-+const raycaster = new THREE.Raycaster();
-
-...
-
-cubes.forEach((cubeInfo, ndx) => {
-  const {cube, elem} = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-  // get the position of the center of the cube
-  cube.updateWorldMatrix(true, false);
-  cube.getWorldPosition(tempV);
-
-  // get the normalized screen coordinate of that position
-  // x and y will be in the -1 to +1 range with x = -1 being
-  // on the left and y = -1 being on the bottom
-  tempV.project(camera);
-
-+  // ask the raycaster for all the objects that intersect
-+  // from the eye toward this object's position
-+  raycaster.setFromCamera(tempV, camera);
-+  const intersectedObjects = raycaster.intersectObjects(scene.children);
-+  // We're visible if the first intersection is this object.
-+  const show = intersectedObjects.length && cube === intersectedObjects[0].object;
-+
-+  if (!show) {
-+    // hide the label
-+    elem.style.display = 'none';
-+  } else {
-+    // un-hide the label
-+    elem.style.display = '';
-
-    // convert the normalized position to CSS coordinates
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // move the elem to that position
-    elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-+  }
-});
-
-

これで重なり問題に対応しました。

-

以下は tempV.z をチェックし、オブジェクトの原点が錐台の外にあるかをチェックします。

-
-  if (!show) {
-+  if (!show || Math.abs(tempV.z) > 1) {
-    // hide the label
-    elem.style.display = 'none';
-
-

正規化された座標には計算した z の値が含まれており、カメラの錐台の near は-1、far は+1の値になります。

-

- -

-

錐台のチェックではオブジェクトの原点をチェックしているだけなので、上記の解決策では失敗します。特に大きなオブジェクトの場合などです。 -オブジェクトの原点は錐台の外にあるかもしれませんが、オブジェクトの半分は錐台の中にあるかもしれません。

-

正しい解決策は、オブジェクト自体が錐台に入っているか確認する事でしょう。 -ただし、残念ながらチェックの動作が遅いです。 -3つの立方体の場合は問題ないですが、オブジェクトがたくさんある場合は問題になるかもしれません。

-

Three.jsには、球体オブジェクトが錐台内にあるかチェックする関数がいくつか用意されています。

-
// at init time
-const frustum = new THREE.Frustum();
-const viewProjection = new THREE.Matrix4();
-
-...
-
-// before checking
-camera.updateMatrix();
-camera.updateMatrixWorld();
-camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
-
-...
-
-// then for each mesh
-someMesh.updateMatrix();
-someMesh.updateMatrixWorld();
-
-viewProjection.multiplyMatrices(
-    camera.projectionMatrix, camera.matrixWorldInverse);
-frustum.setFromProjectionMatrix(viewProjection);
-const inFrustum = frustum.contains(someMesh));
-
-

現在の重なりの解決策にも同様の問題があります。 -ピッキングが遅いです。 -ピッキングの記事で取り上げたように、GPUベースのピッキングを使う事もできますがコストがかからない訳ではありません。 -どの解決策を選択するかはニーズによります。

-

もう1つの問題はラベルの表示順序です。 -コードを変更してラベルを長くなると

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
--  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
--  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-+  makeInstance(geometry, 0x44aa88,  0, 'Aqua Colored Box'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Purple Colored Box'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Gold Colored Box'),
-];
-
-

折り返さないようにCSSで設定します。

-
#labels>div {
-+  white-space: nowrap;
-
-

そうすると次のような問題が発生します。

-
- -

上記では紫のボックスは奥にありますが、紫のボックスのラベルはアクアのボックスの前にあります。

-

これは各要素の zIndex を設定して修正できます。 -投影された位置の z は-1(手前)〜+1(奥)の値を持ちます。 -zIndex は整数である必要があります。 -逆方向の意味で zIndex の値が大きい方が手前にある事を意味します。 -以下のコードで動作するはずです。

-
// convert the normalized position to CSS coordinates
-const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-// move the elem to that position
-elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-+// set the zIndex for sorting
-+elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-
-

zIndexを正しく動作させるには、値を分散させるために大きな数値を選ぶ必要があります。 -そうしないと多くの値が同じ値になってしまいます。 -ラベルがページの他の部分と重ならないように、ラベルのコンテナの z-index を設定し、新しいスタッキングコンテキストを作成します。

-
#labels {
-  position: absolute;  /* let us position ourself inside the container */
-+  z-index: 0;          /* make a new stacking context so children don't sort with rest of page */
-  left: 0;             /* make our position the top left of the container */
-  top: 0;
-  color: white;
-  z-index: 0;
-}
-
-

これでラベルは常に正しい順序で表示されます。

-

- -

-

もう1つの問題を確認ために、もう1つの例をやってみましょう。 -Googleマップのような地球儀を描いて、国名のラベルを貼ってみましょう。

-

国境を含むこのデータを見つけました。 -このデータはCC-BY-SAライセンスです。

-

データを読み込んで、国の概要と国名、その位置を含むJSONデータを生成するためのコードを書いてみました。

-
- -

JSONデータは以下のような配列です。

-
[
-  {
-    "name": "Algeria",
-    "min": [
-      -8.667223,
-      18.976387
-    ],
-    "max": [
-      11.986475,
-      37.091385
-    ],
-    "area": 238174,
-    "lat": 28.163,
-    "lon": 2.632,
-    "population": {
-      "2005": 32854159
-    }
-  },
-  ...
-
-

min、max、lat、lon、これは全て緯度と経度です。

-

ロードしてみましょう。 -このコードは多くのオブジェクトを最適化のコードの流用ですが、オブジェクトをたくさん描画しているわけではないので要求されたレンダリングと同じ解決策を使います。

-

まずは球体を作り、アウトラインテクスチャを使います。

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

ローダー関数を作ってJSONファイルをロードしてみましょう。

-
async function loadJSON(url) {
-  const req = await fetch(url);
-  return req.json();
-}
-
-

そして、その関数を呼び出します。

-
let countryInfos;
-async function loadCountryData() {
-  countryInfos = await loadJSON('resources/data/world/country-info.json');
-     ...
-  }
-  requestRenderIfNotRequested();
-}
-loadCountryData();
-
-

では、そのデータを使ってラベルを生成して配置してみましょう。

-

多くのオブジェクトを最適化の記事ではヘルパーオブジェクトの小さなシーングラフを設定し、地球儀上の緯度と経度の位置を簡単に計算できるようにしました。 -仕組みの説明はその記事を参照して下さい。

-
const lonFudge = Math.PI * 1.5;
-const latFudge = Math.PI;
-// these helpers will make it easy to position the boxes
-// We can rotate the lon helper on its Y axis to the longitude
-const lonHelper = new THREE.Object3D();
-// We rotate the latHelper on its X axis to the latitude
-const latHelper = new THREE.Object3D();
-lonHelper.add(latHelper);
-// The position helper moves the object to the edge of the sphere
-const positionHelper = new THREE.Object3D();
-positionHelper.position.z = 1;
-latHelper.add(positionHelper);
-
-

これを使い、各ラベルの位置を計算します。

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const {lat, lon, name} = countryInfo;
-
-  // adjust the helpers to point to the latitude and longitude
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // get the position of the lat/lon
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-  // add an element for each country
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-
-

上記のコードは、立方体のラベルを作成するために書いたコードに非常に似てます。 -これで配列 countryInfos ができました。 -国ごとのlabel要素に elem プロパティを追加し、位置を表す position を追加しました。

-

立方体の場合と同じく、ラベルの位置とレンダリング時間を更新します。

-
const tempV = new THREE.Vector3();
-
-function updateLabels() {
-  // exit if we have not yet loaded the JSON file
-  if (!countryInfos) {
-    return;
-  }
-
-  for (const countryInfo of countryInfos) {
-    const {position, elem} = countryInfo;
-
-    // get the normalized screen coordinate of that position
-    // x and y will be in the -1 to +1 range with x = -1 being
-    // on the left and y = -1 being on the bottom
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // convert the normalized position to CSS coordinates
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // move the elem to that position
-    elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-    // set the zIndex for sorting
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

上記のコードは、前の立方体のコードと実質的に似ています。 -唯一の大きな違いは、初期化時にラベルの位置を事前に計算しました。 -地球儀が動かないため可能です。カメラだけが動きます。

-

最後にループ処理するrender関数の中で updateLabels を呼び出します。

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  controls.update();
-
-+  updateLabels();
-
-  renderer.render(scene, camera);
-}
-
-

そして、これが結果です。

-

- -

-

ラベルが多すぎる!

-

問題は2つあります。

-
    -
  1. 地球儀の背面の国のラベルも表示されてる

    -
  2. -
  3. ラベルが多すぎる

    -
  4. -
-

問題1では球体以外に交わるものがないので、上記で説明したように RayCaster を使う事はできません。 -代わりにできるのは特定の国が離れているか確認する事です。 -これはラベルの位置が球体の周囲にあるために動作します。 -実際には単位球体を使っており、半径1.0の球体です。 -つまり、位置は単位方向になっており計算が比較的簡単になります。

-
const tempV = new THREE.Vector3();
-+const cameraToPoint = new THREE.Vector3();
-+const cameraPosition = new THREE.Vector3();
-+const normalMatrix = new THREE.Matrix3();
-
-function updateLabels() {
-  // exit if we have not yet loaded the JSON file
-  if (!countryInfos) {
-    return;
-  }
-
-+  const minVisibleDot = 0.2;
-+  // get a matrix that represents a relative orientation of the camera
-+  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-+  // get the camera's position
-+  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-    const {position, elem} = countryInfo;
-
-+    // Orient the position based on the camera's orientation.
-+    // Since the sphere is at the origin and the sphere is a unit sphere
-+    // this gives us a camera relative direction vector for the position.
-+    tempV.copy(position);
-+    tempV.applyMatrix3(normalMatrix);
-+
-+    // compute the direction to this position from the camera
-+    cameraToPoint.copy(position);
-+    cameraToPoint.applyMatrix4(camera.matrixWorldInverse).normalize();
-+
-+    // get the dot product of camera relative direction to this position
-+    // on the globe with the direction from the camera to that point.
-+    // 1 = facing directly towards the camera
-+    // 0 = exactly on tangent of the sphere from the camera
-+    // < 0 = facing away
-+    const dot = tempV.dot(cameraToPoint);
-+
-+    // if the orientation is not facing us hide it.
-+    if (dot < minVisibleDot) {
-+      elem.style.display = 'none';
-+      continue;
-+    }
-+
-+    // restore the element to its default display style
-+    elem.style.display = '';
-
-    // get the normalized screen coordinate of that position
-    // x and y will be in the -1 to +1 range with x = -1 being
-    // on the left and y = -1 being on the bottom
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // convert the normalized position to CSS coordinates
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // move the elem to that position
-    countryInfo.elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-    // set the zIndex for sorting
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

上記では位置を方向として使用し、カメラに対して相対的にその方向を取得しています。 -カメラから地球儀上のその位置までのカメラの相対的な方向を取得し、内積 を取得します。 -内積はベクトル間の角度のコサインを返します。 -これで -1 〜 +1までの値を取得できます。 --1はラベルがカメラに向いており、0はラベルがカメラから見て球体の端にあって、0より大きいものは背面にあります。 -その値を使用してラベル要素の表示・非表示をします。

-
-
-
-
-
- -

上記の図では、カメラからその位置までのラベルの向きの内積を表しています。 -方向を回転させるとカメラに直接向いている時は、内積は-1.0になります。 -カメラに相対する球体の接線上にある時は0.0になります。 -別の言い方をすれば、2つのベクトルがお互いに90度垂直な時は0になります。

-

問題2はラベルが多すぎて、どのラベルを表示するか決める方法が必要です。 -1つの方法は大きな国のラベルのみを表示します。 -読込中のデータには、国がカバーする領域の最小値と最大値が含まれています。 -そこから面積を計算し、その面積を使い表示するか決められます。

-

初期化時に面積を計算してみましょう。

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const {lat, lon, min, max, name} = countryInfo;
-
-  // adjust the helpers to point to the latitude and longitude
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // get the position of the lat/lon
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-+  // compute the area for each country
-+  const width = max[0] - min[0];
-+  const height = max[1] - min[1];
-+  const area = width * height;
-+  countryInfo.area = area;
-
-  // add an element for each country
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-}
-
-

レンダリング時にその領域を使い、ラベルを表示するか決めましょう。

-
+const large = 20 * 20;
-const maxVisibleDot = 0.2;
-// get a matrix that represents a relative orientation of the camera
-normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-// get the camera's position
-camera.getWorldPosition(cameraPosition);
-for (const countryInfo of countryInfos) {
--  const {position, elem} = countryInfo;
-+  const {position, elem, area} = countryInfo;
-+  // large enough?
-+  if (area < large) {
-+    elem.style.display = 'none';
-+    continue;
-+  }
-
-  ...
-
-

私にはこの設定のための良い値が何か分からないです。 -値を操作できるようにGUIを追加します。

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-
+const settings = {
-+  minArea: 20,
-+  maxVisibleDot: -0.2,
-+};
-+const gui = new GUI({width: 300});
-+gui.add(settings, 'minArea', 0, 50).onChange(requestRenderIfNotRequested);
-+gui.add(settings, 'maxVisibleDot', -1, 1, 0.01).onChange(requestRenderIfNotRequested);
-
-function updateLabels() {
-  if (!countryInfos) {
-    return;
-  }
-
--  const large = 20 * 20;
--  const maxVisibleDot = -0.2;
-+  const large = settings.minArea * settings.minArea;
-  // get a matrix that represents a relative orientation of the camera
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // get the camera's position
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-
-    ...
-
-    // if the orientation is not facing us hide it.
--    if (dot > maxVisibleDot) {
-+    if (dot > settings.maxVisibleDot) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-

その結果が以下です。

-

- -

-

回転させて地球儀の背面にいったラベルが消えるようになりました。 -minVisibleDot を調整してカットオフの変化を見る事ができます。 -また、minArea の値を調整して大きな国や小さな国を表示したりもできます。

-

このコード修正を通して、Googleマップにどれだけの労力が投入されているのかを実感しました。 -Googleマップの開発者は、どのラベルを表示するかを決定しなければなりません。 -色んな基準を使っているのは間違いないですね。 -例えば、あなたの現在地、デフォルトの言語設定、アカウントを持っている場合はアカウントの設定、人口や人気度を使用している可能性、ビューの中央にある国を優先している可能性など。 -考える事はたくさんあります。

-

これらの例がHTML要素を3Dに配置する方法について、あなたにいくつかのアイデアを与えられたと思います。 -変更したい事がいくつかあります。

-

次は国を選んでハイライトするようにしてみましょう。

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/backgrounds.html b/manual/ja/backgrounds.html deleted file mode 100644 index 0e6edccd22aca3..00000000000000 --- a/manual/ja/backgrounds.html +++ /dev/null @@ -1,248 +0,0 @@ - - - の背景とスカイボックス - - - - - - - - - - - - - -
-
-

の背景とスカイボックス

-
-
-
-

このサイトのほとんどの記事では、背景に無地の色を使っています。

-

静的な背景として追加するには、CSSを設定するだけで簡単にできます。 -Three.jsのレスポンシブデザインの記事を例にすると、変更が必要なのは2箇所だけです。

-

キャンバスにCSSを追加して背景を画像に設定する必要があります。

-
<style>
-body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-+    background: url(resources/images/daikanyama.jpg) no-repeat center center;
-+    background-size: cover;
-}
-</style>
-
-

そして、何も描画していない場所が透明になるように WebGLRendereralpha を指定します。

-
function main() {
-  const canvas = document.querySelector('#c');
--  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const renderer = new THREE.WebGLRenderer({
-+    antialias: true,
-+    canvas,
-+    alpha: true,
-+  });
-
-

これで背景を設定できました。

-

- -

-

背景にポストプロセス効果を与えたい場合は、Three.jsを使い背景を描画する必要があります。

-

THREE.jsで簡単にできます。シーンの背景をテクスチャに設定すれば良いのです。

-
const loader = new THREE.TextureLoader();
-const bgTexture = loader.load('resources/images/daikanyama.jpg');
-bgTexture.colorSpace = THREE.SRGBColorSpace;
-scene.background = bgTexture;
-
-

このようになります。

-

- -

-

背景画像がありますが、画面に合わせて引き伸ばされています。

-

この問題はテクスチャの repeatoffset プロパティを設定して画像の一部だけを表示する事で解決できます。

-
function render(time) {
-
-   ...
-
-+  // Set the repeat and offset properties of the background texture
-+  // to keep the image's aspect correct.
-+  // Note the image may not have loaded yet.
-+  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
-+  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
-+  const aspect = imageAspect / canvasAspect;
-+
-+  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
-+  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
-+
-+  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
-+  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

今度はThree.jsで背景を描画してます。 -CSSの時と比べて目に見える違いはありませんが、ポストプロセス効果を使うと背景にも影響が出て違いがわかります。

-

- -

-

もちろん、静的な背景は通常は3Dシーンに求めるものではありません。 -その代わりに何らかの スカイボックス が欲しいです。 -スカイボックスとは空の絵が描かれたキューブの事です。 -キューブの中にカメラを入れると背景に空があるように見えます。

-

スカイボックスを実装する最も一般的な方法は、キューブを作りテクスチャを適用して内側から描画する事です。 -キューブの各面に地平線の画像のようなテクスチャ(テクスチャ座標を使用)を貼り付けます。 -また、スカイボックスの代わりに天球やスカイドームを使う事もよくあります。 -それらでの実装は自分で調べればわかると思います。 -キューブや球体を作りテクスチャを適用し、THREE.BackSide としてマークを付けます。 -そして、外側ではなく内側にレンダリングし、直接シーンに入れるか、上記のようにするか、2つのシーンを作るか、スカイボックス/球体/ドームを描くための特別なシーンと -他の全てのものを描画するために使用します。 -描画には通常の PerspectiveCamera を使います。OrthographicCamera は必要ないです。

-

もう1つの解決策は キューブマップ を使用する事です。 -キューブマップは、キューブの側面である6つの側面を持つ特殊な種類のテクスチャです。 -標準的なテクスチャ座標を使用するのではなく、中心から外側に向けた方向を使用し、どこで色を取得するかを決定します。

-

カリフォルニア州マウンテンビューにあるコンピュータ歴史博物館のキューブマップの画像6枚をご紹介します。

-
- - - -
-
- - - -
- -

CubeTextureLoader を使用してキューブマップ画像を読み込み、シーンの背景として使用します。

-
{
-  const loader = new THREE.CubeTextureLoader();
-  const texture = loader.load([
-    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
-  ]);
-  scene.background = texture;
-}
-
-

レンダリング時には、repeatやoffsetプロパティでテクスチャを調整する必要はありません。

-
function render(time) {
-
-   ...
-
--  // Set the repeat and offset properties of the background texture
--  // to keep the image's aspect correct.
--  // Note the image may not have loaded yet.
--  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
--  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
--  const aspect = imageAspect / canvasAspect;
--
--  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
--  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
--
--  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
--  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

カメラを回転できるようにコントロールを追加してみましょう。

-
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 3;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

これを試してみて下さい。 -ドラッグしてカメラを回転させ、キューブマップが周囲を取り囲んでいるのを見てみましょう。

-

- -

-

もう1つの方法は正距円筒図を使用する事です。 -360カメラで撮るとこんな感じの写真になります。

-

このサイトで見つけたのがこちらです。

-
- -

たいして変わらないですね。 -まず、正距円筒図をテクスチャとして読み込み、読み込み後のコールバックで WebGLCubeRenderTarget.fromEquirectangularTexture を呼び出して、正距円筒図テクスチャからキューブマップを生成します。

-
{
--  const loader = new THREE.CubeTextureLoader();
--  const texture = loader.load([
--    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
--  ]);
--  scene.background = texture;
-+  const loader = new THREE.TextureLoader();
-+  const texture = loader.load(
-+    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
-+    () => {
-+      texture.mapping = THREE.EquirectangularReflectionMapping;
-+      texture.colorSpace = THREE.SRGBColorSpace;
-+      scene.background = texture;
-+    });
-}
-
-

そして、これが全てです。

-

- -

-

テクスチャを読み込み時に行うのではなく、あらかじめ等角画像をキューブマップに変換しておく事ともできます。こんなサイトもあります

- -
-
-
- - - - - - - - diff --git a/manual/ja/billboards.html b/manual/ja/billboards.html deleted file mode 100644 index b41ed3d48d3740..00000000000000 --- a/manual/ja/billboards.html +++ /dev/null @@ -1,282 +0,0 @@ - - - のビルボード - - - - - - - - - - - - - -
-
-

のビルボード

-
-
-
-

前回のページでは CanvasTextureを使ってラベルとバッジを作りました。バッジなどが常にカメラの方向を向いて文字が読める状態になっているという効果が欲しい時があります(訳註:ビルボード効果と言います)。Three.jsはSpriteSpriteMaterial を使ってビルボード効果を実現できます。

-

In a previous article we used a CanvasTexture -to make labels / badges on characters. Sometimes we'd like to make labels or -other things that always face the camera. Three.js provides the Sprite and -SpriteMaterial to make this happen.

-

この記事からサンプルを拝借してSpriteSpriteMaterialを使ってみましょう。

-
function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // because our canvas is likely not a power of 2
-  // in both dimensions set the filtering appropriately.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-
--  const labelMaterial = new THREE.MeshBasicMaterial({
-+  const labelMaterial = new THREE.SpriteMaterial({
-    map: texture,
--    side: THREE.DoubleSide,
-    transparent: true,
-  });
-
-  const root = new THREE.Object3D();
-  root.position.x = x;
-
-  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-  root.add(body);
-  body.position.y = bodyHeight / 2;
-
-  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-  root.add(head);
-  head.position.y = bodyHeight + headRadius * 1.1;
-
--  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  const label = new THREE.Sprite(labelMaterial);
-  root.add(label);
-  label.position.y = bodyHeight * 4 / 5;
-  label.position.z = bodyRadiusTop * 1.01;
-
-

はい、常にラベルがカメラの方を向くようになりました。

-

- -

-

しかし角度によってはラベルがオブジェクトに食い込んでしまうことがあります。

-
- -

ラベルの位置を動かしましょう。

-
+// if units are meters then 0.01 here makes size
-+// of the label into centimeters.
-+const labelBaseScale = 0.01;
-const label = new THREE.Sprite(labelMaterial);
-root.add(label);
--label.position.y = bodyHeight * 4 / 5;
--label.position.z = bodyRadiusTop * 1.01;
-+label.position.y = head.position.y + headRadius + size * labelBaseScale;
-
--// if units are meters then 0.01 here makes size
--// of the label into centimeters.
--const labelBaseScale = 0.01;
-label.scale.x = canvas.width  * labelBaseScale;
-label.scale.y = canvas.height * labelBaseScale;
-
-

- -

-

ビルボード効果を使ってファケード(訳註:ハリボテのようなもの)を作ることもできます。

-

つまり3Dオブジェクトは重いので3Dオブジェクトを描画する代わりに同じ絵を描いた板を用意するということです。

-

さっそくやってみます。たくさんの木があるシーンを作ってみます。1つの木はシリンダーとコーンでできています。

-

まずはファケードを使わずに単純に3Dオブジェクトを並べてみます。

-
const trunkRadius = .2;
-const trunkHeight = 1;
-const trunkRadialSegments = 12;
-const trunkGeometry = new THREE.CylinderGeometry(
-    trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments);
-
-const topRadius = trunkRadius * 4;
-const topHeight = trunkHeight * 2;
-const topSegments = 12;
-const topGeometry = new THREE.ConeGeometry(
-    topRadius, topHeight, topSegments);
-
-const trunkMaterial = new THREE.MeshPhongMaterial({color: 'brown'});
-const topMaterial = new THREE.MeshPhongMaterial({color: 'green'});
-
-

草の部分と幹の部分をそれぞれMeshで作り親オブジェクトObject3Dに加えます。

-
function makeTree(x, z) {
-  const root = new THREE.Object3D();
-  const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
-  trunk.position.y = trunkHeight / 2;
-  root.add(trunk);
-
-  const top = new THREE.Mesh(topGeometry, topMaterial);
-  top.position.y = trunkHeight + topHeight / 2;
-  root.add(top);
-
-  root.position.set(x, 0, z);
-  scene.add(root);
-
-  return root;
-}
-
-

たくさん作ってみましょう。

-
for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
-    makeTree(x, z);
-  }
-}
-
-

地面も一応作ります。

-
// add ground
-{
-  const size = 400;
-  const geometry = new THREE.PlaneGeometry(size, size);
-  const material = new THREE.MeshPhongMaterial({color: 'gray'});
-  const mesh = new THREE.Mesh(geometry, material);
-  mesh.rotation.x = Math.PI * -0.5;
-  scene.add(mesh);
-}
-
-

空の色は青にします。

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('white');
-+scene.background = new THREE.Color('lightblue');
-
-

はい、木がたくさんできました。

-

- -

-

121個の木があります。1つにつき12ポリゴンのコーンと48ポリゴンのシリンダーがあるので1つの木は60ポリゴンです。 -これが121個あるので7260ポリゴンです。このシンプルな木ならそれほど問題ありませんが、リアルな木を作ろうとしたら1つの木につき1000から3000のポリゴンがあるのが普通です。ということは121個表示するには36万3千ポリゴン必要です。木を表示するだけで動作が重くなるかもしれません。

-

そこでファケードを使ってポリゴン数を落とします。

-

ペイントソフトで描いた絵をPlaneにはってもいいのですがここは学んだことを使いましょう。

-

RenderTargetを使ってThree.js内で絵を描き、Planeに貼ってみます。 -この記事が参考になります。

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  camera.position.copy(boxCenter);
-  camera.position.z += distance;
-
-  // pick some near and far values for the frustum that
-  // will contain the box.
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-}
-
-function makeSpriteTexture(textureSize, obj) {
-  const rt = new THREE.WebGLRenderTarget(textureSize, textureSize);
-
-  const aspect = 1;  // because the render target is square
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-  scene.add(obj);
-
-  // compute the box that contains obj
-  const box = new THREE.Box3().setFromObject(obj);
-
-  const boxSize = box.getSize(new THREE.Vector3());
-  const boxCenter = box.getCenter(new THREE.Vector3());
-
-  // set the camera to frame the box
-  const fudge = 1.1;
-  const size = Math.max(...boxSize.toArray()) * fudge;
-  frameArea(size, size, boxCenter, camera);
-
-  renderer.autoClear = false;
-  renderer.setRenderTarget(rt);
-  renderer.render(scene, camera);
-  renderer.setRenderTarget(null);
-  renderer.autoClear = true;
-
-  scene.remove(obj);
-
-  return {
-    position: boxCenter.multiplyScalar(fudge),
-    scale: size,
-    texture: rt.texture,
-  };
-}
-
-

まずフィールドオブビュー(fov)を設定しています。カメラの視野範囲におさまる木をこの記事と同じ方法で計算しています。

-

さらにframeAreaを使っています。これは木を表示する最も近いカメラの位置を計算してカメラに設定しています。仮想的なスタジオで木の写真をとっているような状態です。

-

レンダーターゲットに木がおさまるようにサイズを1.1倍(fudge倍)しています。ここで注意が必要なのはカメラで撮影した木の映像がレンダーターゲットをはみ出したり逆に小さすぎたりする場合です。もちろんこうした状態は事前に精緻な計算をしておけば良いのですがここではfudgeで調整しています。

-

木の撮影ができたのでレンダーターゲットにレンダリングして元の3Dオブジェクトは消しておきます。

-

シーンにはライトだけがある状態です。

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('lightblue');
-
-

最後にテクスチャを作って位置とサイズを調整します。

-
// make billboard texture
-const tree = makeTree(0, 0);
-const facadeSize = 64;
-const treeSpriteInfo = makeSpriteTexture(facadeSize, tree);
-
-

これで重い3Dモデルの木の代わりにファケードを使った木ができました。

-
+function makeSprite(spriteInfo, x, z) {
-+  const {texture, offset, scale} = spriteInfo;
-+  const mat = new THREE.SpriteMaterial({
-+    map: texture,
-+    transparent: true,
-+  });
-+  const sprite = new THREE.Sprite(mat);
-+  scene.add(sprite);
-+  sprite.position.set(
-+      offset.x + x,
-+      offset.y,
-+      offset.z + z);
-+  sprite.scale.set(scale, scale, scale);
-+}
-
-for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
--    makeTree(x, z);
-+    makeSprite(treeSpriteInfo, x, z);
-  }
-}
-
-

背景も変えてみます。

-
scene.background = new THREE.Color('lightblue');
-
-

完成です。

-

- -

-

3Dモデルと違って近づくとハリボテであることがバレてしまいます。今回は64x64ピクセルで作りましたがもちろん高解像にすることもできます。しかしそれでも3Dモデルのように近づいてもエッジが綺麗というわけにはいかないので、通常はカメラが近づくことがない遠く離れた木や山に使います。

-

他にはカメラの向きを変えても同じように見える問題がありますが、これは8個のファケードを用意して別の角度から見たときに別のファケードが見えるようにすればいいでしょう。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/cameras.html b/manual/ja/cameras.html deleted file mode 100644 index 7ac3174586b1e6..00000000000000 --- a/manual/ja/cameras.html +++ /dev/null @@ -1,525 +0,0 @@ - - - のカメラ - - - - - - - - - - - - - -
-
-

のカメラ

-
-
-
-

この記事はThree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでいない場合、そこから始めると良いかもしれません。

-

three.jsでのカメラの話をしましょう。 -最初の記事でいくつか取り上げましたが、ここではもっと詳しく取り上げます。

-

PerspectiveCamera(透視投影カメラ) はthree.jsで最も一般的なカメラで、今までの記事で使ってきました。 -遠くのものが近くのものよりも小さく見える3Dビューを提供します。

-

PerspectiveCamera錐台 を定義します。 -錐台とは先端が切り取られたピラミッドのような3D形状の事です。 -つまり、cube(立方体)、cone(円錐体)、sphere(球体)、cylinder(円柱)、frustum(錐台)は全て異なる種類の固体名です。

-
-
cube
-
cone
-
sphere
-
cylinder
-
frustum
-
- -

私はこの事を何年も知らなかったです。 -どこかの本やページで 錐台 について書かれていると目が点になります。 -錐台が固体名と理解すると、それらの記述を急に理解できるようになりました 😅

-

PerspectiveCamera には4つのプロパティをもとに錐台が定義されています。 -near は錐台の正面がどこから始まるかを定義します。 -far は錐台が終了する場所です。 -fov は視野角で、カメラから near 単位で指定された視野角を得るために正しい高さが計算され、錐台の前面と背面の高さを定義します。 -aspect は錐台の前面と背面の幅です。 -錐台の幅は高さにaspectを掛けたものです。

-

-

前回の記事から地面となる平面、球体、立方体のあるシーンを利用し、カメラの設定を調整してみましょう。

-

nearfar の設定用に MinMaxGUIHelper を作成します。 -far が常に near よりも大きい値になるようにします。 -MinMaxGUIHelperは minmax のプロパティがあり、lil-guiで調整します。 -GUIで値を調整すると2つのプロパティに設定されます。

-
class MinMaxGUIHelper {
-  constructor(obj, minProp, maxProp, minDif) {
-    this.obj = obj;
-    this.minProp = minProp;
-    this.maxProp = maxProp;
-    this.minDif = minDif;
-  }
-  get min() {
-    return this.obj[this.minProp];
-  }
-  set min(v) {
-    this.obj[this.minProp] = v;
-    this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-  }
-  get max() {
-    return this.obj[this.maxProp];
-  }
-  set max(v) {
-    this.obj[this.maxProp] = v;
-    this.min = this.min;  // this will call the min setter
-  }
-}
-
-

これでGUIを以下のように設定できます。

-
function updateCamera() {
-  camera.updateProjectionMatrix();
-}
-
-const gui = new GUI();
-gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-

カメラ設定の変更時、カメラの updateProjectionMatrix 関数を呼び出す必要があります。 -updateCamera という関数を作り、それをlil-gui変更時に呼び出すようにします。

-

- -

-

値を調整すると動作が確認できます。 -aspect を調整したい場合は、新しいウィンドウでサンプルを開いてからウィンドウサイズを変更して下さい。

-

それでもまだ少し見づらいので、2つのカメラを持つサンプルに変えます。 -1つ目のカメラは上記で見たシーンを表示し、2つ目のカメラは1つ目のカメラが描画してるシーンを見ている別のカメラとし、そのカメラの錐台を表示します。

-

そのためにthree.jsのシザー関数を利用します。 -シザー機能を使い、カメラを2台並べて2つのシーンを描画するように変更してみましょう。

-

まず、HTMLとCSSを使って2つの並んでるDOM要素を定義してみましょう。 -両方のカメラが簡単に独自の OrbitControls を持てるようにします。

-
<body>
-  <canvas id="c"></canvas>
-+  <div class="split">
-+     <div id="view1" tabindex="1"></div>
-+     <div id="view2" tabindex="2"></div>
-+  </div>
-</body>
-
-

このview1とview2をキャンバスの上に重ねて表示させます。

-
.split {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-}
-.split>div {
-  width: 100%;
-  height: 100%;
-}
-
-

次に CameraHelper を追加します。 -CameraHelperCamera の錐台を描画します。

-
const cameraHelper = new THREE.CameraHelper(camera);
-
-...
-
-scene.add(cameraHelper);
-
-

view1とview2のDOM要素をquerySelectorしましょう。

-
const view1Elem = document.querySelector('#view1');
-const view2Elem = document.querySelector('#view2');
-
-

既存の OrbitControls をview1にのみ反応するようにします。

-
-const controls = new OrbitControls(camera, canvas);
-+const controls = new OrbitControls(camera, view1Elem);
-
-

2つ目の PerspectiveCameraOrbitControls を作ってみましょう。 -2つ目の OrbitControls は2つ目のカメラに関連付けし、view2から入力を取得します。

-
const camera2 = new THREE.PerspectiveCamera(
-  60,  // fov
-  2,   // aspect
-  0.1, // near
-  500, // far
-);
-camera2.position.set(40, 10, 30);
-camera2.lookAt(0, 5, 0);
-
-const controls2 = new OrbitControls(camera2, view2Elem);
-controls2.target.set(0, 5, 0);
-controls2.update();
-
-

最後にキャンバスの一部だけをレンダリングするために、シザー機能を使い各カメラの視点からシーンをレンダリングします。

-

ここにDOM要素を渡すと、キャンバスに重なる矩形を計算する関数があります。 -その矩形にシザーとビューポートを設定し、アスペクト比を返します。

-
function setScissorForElement(elem) {
-  const canvasRect = canvas.getBoundingClientRect();
-  const elemRect = elem.getBoundingClientRect();
-
-  // compute a canvas relative rectangle
-  const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
-  const left = Math.max(0, elemRect.left - canvasRect.left);
-  const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
-  const top = Math.max(0, elemRect.top - canvasRect.top);
-
-  const width = Math.min(canvasRect.width, right - left);
-  const height = Math.min(canvasRect.height, bottom - top);
-
-  // setup the scissor to only render to that part of the canvas
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  // return the aspect
-  return width / height;
-}
-
-

この関数を使って render 関数でシーンを2回描画できます。

-
  function render() {
-
--    if (resizeRendererToDisplaySize(renderer)) {
--      const canvas = renderer.domElement;
--      camera.aspect = canvas.clientWidth / canvas.clientHeight;
--      camera.updateProjectionMatrix();
--    }
-
-+    resizeRendererToDisplaySize(renderer);
-+
-+    // turn on the scissor
-+    renderer.setScissorTest(true);
-+
-+    // render the original view
-+    {
-+      const aspect = setScissorForElement(view1Elem);
-+
-+      // adjust the camera for this aspect
-+      camera.aspect = aspect;
-+      camera.updateProjectionMatrix();
-+      cameraHelper.update();
-+
-+      // don't draw the camera helper in the original view
-+      cameraHelper.visible = false;
-+
-+      scene.background.set(0x000000);
-+
-+      // render
-+      renderer.render(scene, camera);
-+    }
-+
-+    // render from the 2nd camera
-+    {
-+      const aspect = setScissorForElement(view2Elem);
-+
-+      // adjust the camera for this aspect
-+      camera2.aspect = aspect;
-+      camera2.updateProjectionMatrix();
-+
-+      // draw the camera helper in the 2nd view
-+      cameraHelper.visible = true;
-+
-+      scene.background.set(0x000040);
-+
-+      renderer.render(scene, camera2);
-+    }
-
--    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-

上記のコードはview1とview2を区別するために、view2をレンダリング時のシーンの背景色を紺色にしています。

-

また、render 関数内で全て更新しているため、updateCamera のコードを削除できます。

-
-function updateCamera() {
--  camera.updateProjectionMatrix();
--}
-
-const gui = new GUI();
--gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-+gui.add(camera, 'fov', 1, 180);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
--gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
--gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
-+gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-
-

片方のviewを使い、もう片方の錐台を見るれるようになりました。

-

- -

-

左側はオリジナルのビュー、右側はカメラの錐台を表示するビューがあります。 -マウスで nearfarfov を調整してカメラを動かすと、右側に表示されている錐台の内側だけが左側のシーンに表示されています。

-

near を20くらいに調整すると、錐台に入らずオブジェクトの正面が消えます。 -far を35以下に調整すると、錐台に入らず地上の平面が消えていきます。

-

ここで疑問が湧いてきました。 -near を0.0000000001に far を10000000000000に設定し、全てを見えるようにできないでしょうか? -なぜなら、GPUは何かが前後にあるかを判断する精度が高いからです。 -その精度は nearfar の間に分散しています。 -さらに悪い事にデフォルトではカメラの近くの精度は細かく、カメラから遠い精度は粗くなっています。 -単位の値は near から始まり、far に近づくにつれて徐々に拡大していきます。

-

上記のサンプルから始めて、20個の球体を1列に挿入するコードに変更してみましょう。

-
{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const numSpheres = 20;
-  for (let i = 0; i < numSpheres; ++i) {
-    const sphereMat = new THREE.MeshPhongMaterial();
-    sphereMat.color.setHSL(i * .73, 1, 0.5);
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, i * sphereRadius * -2.2);
-    scene.add(mesh);
-  }
-}
-
-

near を0.00001に設定してみましょう。

-
const fov = 45;
-const aspect = 2;  // the canvas default
--const near = 0.1;
-+const near = 0.00001;
-const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

値の編集時に0.00001を許容するようにGUIコードを微調整します。

-
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-
-

何が起こると思いますか?

-

- -

-

これはGPUがどのピクセルが前後にあるか判断する精度が不足してる時に Zファイティング が発生する例です。

-

あなたのマシンでは問題が表示されない可能性がありますが、私のマシンでは以下のように表示されます。

-
- -

1つ目の解決策はどのピクセルが前後にあるかを計算するために、three.jsの別メソッドを使用します。 -これは WebGLRenderer の作成時に logarithmicDepthBuffer を有効にします。

-
-const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  antialias: true,
-+  canvas,
-+  logarithmicDepthBuffer: true,
-+});
-
-

これで上手く動くかもしれません。

-

- -

-

これで問題が解決しない場合、この解決策が使えない理由の1つに遭遇した事になります。 -その理由は、特定のGPUのみをサポートしているためです。 -2018年9月現在、ほとんどのデスクトップがこの解決策をサポートしていますが、モバイルデバイスはほとんどサポートしていません。

-

この解決策を選択しないもう1つの理由は、標準的な解決策よりも大幅に遅くなる可能性があります。

-

この解決策は解像度に制限があります。 -near をさらに小さくしたり far をさらに大きくしたりすると最終的に同じ問題にぶつかります。

-

nearfar の設定は、常にユースケースに合った値を選択して下さい。 -near はカメラからできるだけ離れた所に置き、オブジェクトが消えないようにしましょう。 -far はカメラからできるだけ近い所に置き、オブジェクトが消えないようにしましょう。

-

もしまつげを見れるぐらい誰かの顔をクローズアップし、背景には50キロ離れた山までの道のりを見る巨大なシーンを描画したい場合、他の創造的な解決策を見つける必要があるでしょう。 -この解決策は後にしましょう。 -とりあえず自分のニーズに合わせて nearfar は適切な値を選択しましょう。

-

2番目に一般的なカメラは OrthographicCamera(平行投影カメラ) です。 -錐台を指定するのではなく、leftrighttopbottomnearfar の設定でボックスを指定します。 -ボックスを投影しているので遠近感はありません。

-

上記のview1とview2のサンプルを変更し、最初のビューで OrthographicCamera を使うようにしましょう。

-

最初に OrthographicCamera を設定します。

-
const left = -1;
-const right = 1;
-const top = 1;
-const bottom = -1;
-const near = 5;
-const far = 50;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 0.2;
-
-

leftbottom を-1、righttop を1にしました。 -これで箱の幅が2、高さが2になりますが、描画している矩形のアスペクト比で lefttop を調整します。 -zoom プロパティでカメラで実際に表示される値を簡単に調整できます。

-

GUIに zoom の設定を追加してみましょう。

-
const gui = new GUI();
-+gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
-
-

listen 呼び出しはlil-guiに変更を監視するようにします。 -これは OrbitControls がズームも制御できるからです。 -例えばマウスのスクロールホイールは OrbitControls でズームします。

-

最後に左側をレンダリングする部分を変更して OrthographicCamera を更新します。

-
{
-  const aspect = setScissorForElement(view1Elem);
-
-  // update the camera for this aspect
--  camera.aspect = aspect;
-+  camera.left   = -aspect;
-+  camera.right  =  aspect;
-  camera.updateProjectionMatrix();
-  cameraHelper.update();
-
-  // don't draw the camera helper in the original view
-  cameraHelper.visible = false;
-
-  scene.background.set(0x000000);
-  renderer.render(scene, camera);
-}
-
-

これで OrthographicCamera が動作しているのが見れるようになりました。

-

- -

-

three.jsで2次元のものを描画する場合には、OrthographicCamera が最もよく使われます。 -カメラの表示台数を決める必要があります。 -例えば、1ピクセルのキャンバスをカメラの1単位と一致させたい場合、次のような事ができます。

-

原点を中心に置き、1ピクセル = three.jsの1単位とするには次のようにします。

-
camera.left = -canvas.width / 2;
-camera.right = canvas.width / 2;
-camera.top = canvas.height / 2;
-camera.bottom = -canvas.height / 2;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

原点を2Dキャンバスのように左上に配置したい場合は、次のようにします。

-
camera.left = 0;
-camera.right = canvas.width;
-camera.top = 0;
-camera.bottom = canvas.height;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

この場合、左上の角は2Dキャンバスのように0, 0になります。

-

やってみましょう!まずはカメラの設定をします。

-
const left = 0;
-const right = 300;  // default canvas size
-const top = 0;
-const bottom = 150;  // default canvas size
-const near = -1;
-const far = 1;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 1;
-
-

続いて、6枚のテクスチャをロードし、6枚の平面を作ってみましょう。 -各平面は THREE.Object3D を親にし、平面の中心を左上にして簡単にオフセットできるようにします。

-
const loader = new THREE.TextureLoader();
-const textures = [
-  loader.load('resources/images/flower-1.jpg'),
-  loader.load('resources/images/flower-2.jpg'),
-  loader.load('resources/images/flower-3.jpg'),
-  loader.load('resources/images/flower-4.jpg'),
-  loader.load('resources/images/flower-5.jpg'),
-  loader.load('resources/images/flower-6.jpg'),
-];
-const planeSize = 256;
-const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planes = textures.map((texture) => {
-  const planePivot = new THREE.Object3D();
-  scene.add(planePivot);
-  texture.magFilter = THREE.NearestFilter;
-  const planeMat = new THREE.MeshBasicMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  planePivot.add(mesh);
-  // move plane so top left corner is origin
-  mesh.position.set(planeSize / 2, planeSize / 2, 0);
-  return planePivot;
-});
-
-

キャンバスサイズの変更時、カメラを更新する必要があります。

-
function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    camera.right = canvas.width;
-    camera.bottom = canvas.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

planesTHREE.Mesh の配列であり、各平面に1つずつあります。 -これらを時間に応じて移動させてみましょう。

-
function render(time) {
-  time *= 0.001;  // convert to seconds;
-
-  ...
-
-  const distAcross = Math.max(20, canvas.width - planeSize);
-  const distDown = Math.max(20, canvas.height - planeSize);
-
-  // total distance to move across and back
-  const xRange = distAcross * 2;
-  const yRange = distDown * 2;
-  const speed = 180;
-
-  planes.forEach((plane, ndx) => {
-    // compute a unique time for each plane
-    const t = time * speed + ndx * 300;
-
-    // get a value between 0 and range
-    const xt = t % xRange;
-    const yt = t % yRange;
-
-    // set our position going forward if 0 to half of range
-    // and backward if half of range to range
-    const x = xt < distAcross ? xt : xRange - xt;
-    const y = yt < distDown   ? yt : yRange - yt;
-
-    plane.position.set(x, y, 0);
-  });
-
-  renderer.render(scene, camera);
-
-

2Dキャンバスのようにピクセル計算を使い、画像がキャンバスの縁からピクセルのように跳ね返っているのが分かります。

-

- -

-

OrthographicCamera のもう1つの一般的な用途は3Dモデリングツールやゲームエンジンで、上、下、左、右、正面、背面のビューを描画する場合です。

-
- -

上記のスクリーンショットでは右上のビューが透視投影図、左上のビューが平行投影図です。

-

それがカメラの基本です。 -カメラを動かすための一般的な方法は別の記事で紹介します。 -とりあえずについてのページに移りましょう。

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/canvas-textures.html b/manual/ja/canvas-textures.html deleted file mode 100644 index 4aa9ebe26129c3..00000000000000 --- a/manual/ja/canvas-textures.html +++ /dev/null @@ -1,411 +0,0 @@ - - - のキャンバステクスチャ - - - - - - - - - - - - - -
-
-

のキャンバステクスチャ

-
-
-
-

この記事はThree.jsのテクスチャからの続きです。 -まだ読んでない人はそちらから先に読んでみるといいかもしれません。

-

前回のテクスチャの記事ではテクスチャは画像ファイルを使っていました。 -実行時にテクスチャを生成したい場合もあります。 -これを行う方法の1つは CanvasTexture を使用する事です。

-

キャンバステクスチャは <canvas> を入力として受け取ります。 -2D canvas APIでキャンバスに描画する方法を知らない場合、MDNに良いチュートリアルがあります

-

簡単なキャンバスのプログラムを作ってみましょう。 -ランダムな場所にランダムな色で点を描画します。

-
const ctx = document.createElement('canvas').getContext('2d');
-document.body.appendChild(ctx.canvas);
-ctx.canvas.width = 256;
-ctx.canvas.height = 256;
-ctx.fillStyle = '#FFF';
-ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-
-function randInt(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min | 0;
-}
-
-function drawRandomDot() {
-  ctx.fillStyle = `#${randInt(0x1000000).toString(16).padStart(6, '0')}`;
-  ctx.beginPath();
-
-  const x = randInt(256);
-  const y = randInt(256);
-  const radius = randInt(10, 64);
-  ctx.arc(x, y, radius, 0, Math.PI * 2);
-  ctx.fill();
-}
-
-function render() {
-  drawRandomDot();
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

結構簡単ですね。

-

- -

-

これをテクスチャとして使ってみましょう。 -まずは前回の記事の立方体のテクスチャにしてみます。 -画像を読込するコードを削除します。 -代わりにキャンバスを作成し CanvasTexture を作成してキャンバスに渡します。

-
const cubes = [];  // just an array we can use to rotate the cubes
--const loader = new THREE.TextureLoader();
--
-+const ctx = document.createElement('canvas').getContext('2d');
-+ctx.canvas.width = 256;
-+ctx.canvas.height = 256;
-+ctx.fillStyle = '#FFF';
-+ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-+const texture = new THREE.CanvasTexture(ctx.canvas);
-
-const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg'),
-+  map: texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-cubes.push(cube);  // add to our list of cubes to rotate
-
-

描画のループ処理でランダムな点を描画するコードを呼び出します。

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  drawRandomDot();
-+  texture.needsUpdate = true;
-
-  cubes.forEach((cube, ndx) => {
-    const speed = .2 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

唯一の余計な事は CanvasTextureneedsUpdate プロパティを設定し、Three.jsにキャンバスの最新のコンテンツでテクスチャを更新する事です。

-

これでキャンバスのテクスチャキューブができました。

-

- -

-

注意点としてThree.jsを使ってキャンバスに描画する場合、 -この記事 で説明している RenderTarget を使った方が良いでしょう。

-

キャンバステクスチャの一般的な使用例は、シーンにテキストを提供する事です。 -例えばキャラクターのバッジに名前を入れたい場合、キャンバステクスチャを使いバッジのテクスチャを作成します。

-

3人のキャラクターがいるシーンを作り、それぞれにバッジやラベルを付けてみましょう。

-

上記の例から立方体に関連する全てのコードを削除してみましょう。 -背景を白にして、ライトを2つ追加してみましょう。

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-+
-+function addLight(position) {
-+  const color = 0xFFFFFF;
-+  const intensity = 1;
-+  const light = new THREE.DirectionalLight(color, intensity);
-+  light.position.set(...position);
-+  scene.add(light);
-+  scene.add(light.target);
-+}
-+addLight([-3, 1, 1]);
-+addLight([ 2, 1, .5]);
-
-

2Dキャンバスを使い、ラベルを作るコードを作ってみましょう。

-
+function makeLabelCanvas(size, name) {
-+  const borderSize = 2;
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  const font =  `${size}px bold sans-serif`;
-+  ctx.font = font;
-+  // measure how long the name will be
-+  const doubleBorderSize = borderSize * 2;
-+  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const height = size + doubleBorderSize;
-+  ctx.canvas.width = width;
-+  ctx.canvas.height = height;
-+
-+  // need to set font again after resizing canvas
-+  ctx.font = font;
-+  ctx.textBaseline = 'top';
-+
-+  ctx.fillStyle = 'blue';
-+  ctx.fillRect(0, 0, width, height);
-+  ctx.fillStyle = 'white';
-+  ctx.fillText(name, borderSize, borderSize);
-+
-+  return ctx.canvas;
-+}
-
-

続いて体はシリンダー、頭はスフィア、ラベルはプレーンを使い簡単なキャラクターを作ります。

-

まずは共有のジオメトリを作ってみましょう。

-
+const bodyRadiusTop = .4;
-+const bodyRadiusBottom = .2;
-+const bodyHeight = 2;
-+const bodyRadialSegments = 6;
-+const bodyGeometry = new THREE.CylinderGeometry(
-+    bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-+
-+const headRadius = bodyRadiusTop * 0.8;
-+const headLonSegments = 12;
-+const headLatSegments = 5;
-+const headGeometry = new THREE.SphereGeometry(
-+    headRadius, headLonSegments, headLatSegments);
-+
-+const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-

では、これらのパーツからキャラクターを作る機能を作ってみましょう。

-
+function makePerson(x, size, name, color) {
-+  const canvas = makeLabelCanvas(size, name);
-+  const texture = new THREE.CanvasTexture(canvas);
-+  // because our canvas is likely not a power of 2
-+  // in both dimensions set the filtering appropriately.
-+  texture.minFilter = THREE.LinearFilter;
-+  texture.wrapS = THREE.ClampToEdgeWrapping;
-+  texture.wrapT = THREE.ClampToEdgeWrapping;
-+
-+  const labelMaterial = new THREE.MeshBasicMaterial({
-+    map: texture,
-+    side: THREE.DoubleSide,
-+    transparent: true,
-+  });
-+  const bodyMaterial = new THREE.MeshPhongMaterial({
-+    color,
-+    flatShading: true,
-+  });
-+
-+  const root = new THREE.Object3D();
-+  root.position.x = x;
-+
-+  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-+  root.add(body);
-+  body.position.y = bodyHeight / 2;
-+
-+  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-+  root.add(head);
-+  head.position.y = bodyHeight + headRadius * 1.1;
-+
-+  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  root.add(label);
-+  label.position.y = bodyHeight * 4 / 5;
-+  label.position.z = bodyRadiusTop * 1.01;
-+
-+  // if units are meters then 0.01 here makes size
-+  // of the label into centimeters.
-+  const labelBaseScale = 0.01;
-+  label.scale.x = canvas.width  * labelBaseScale;
-+  label.scale.y = canvas.height * labelBaseScale;
-+
-+  scene.add(root);
-+  return root;
-+}
-
-

上記のようにルートの Object3D に体、頭、ラベルを配置して位置を調整しています。 -これでキャラクターを移動させたい場合、ルートオブジェクトを移動します。 -体の高さは2です。 -1が1メートルに等しい場合、上記のコードはラベルをcm単位で作成してます。 -背の高さがcmのサイズなのでテキストに合うような幅が必要です。

-

あとはラベルでキャラクターを作ればいいです。

-
+makePerson(-3, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 32, 'Green Machine', 'green');
-+makePerson(+3, 32, 'Red Menace', 'red');
-
-

残作業はカメラを動かせるように OrbitControls を追加します。

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 50;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.set(0, 2, 5);
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 2, 0);
-+controls.update();
-
-

そして、簡単なラベルを取得します。

-

- -

-

気になる点がいくつかあります。

-
    -
  • 拡大するとラベルがかなり低解像度になる
  • -
-

簡単な解決策はありません。 -もっと複雑なフォントの描画テクニックがありますが、私は解決策を知りません。 -また、フォントデータをダウンロードするので時間がかかります。

-

解決策の1つはラベルの解像度を上げる事です。 -渡されたサイズを現在の2倍に設定し、labelBaseScale を現在の半分に設定してみて下さい。

-
    -
  • 名前が長いほどラベルが長くなります
  • -
-

これを修正したければ代わりに固定サイズのラベルを貼り、テキストを押しつぶします。

-

これはとても簡単です。基本となる幅を渡し、幅に合わせてテキストを拡大縮小します。

-
-function makeLabelCanvas(size, name) {
-+function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
-  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${size}px bold sans-serif`;
-  ctx.font = font;
-  // measure how long the name will be
-+  const textWidth = ctx.measureText(name).width;
-
-  const doubleBorderSize = borderSize * 2;
--  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const width = baseWidth + doubleBorderSize;
-  const height = size + doubleBorderSize;
-  ctx.canvas.width = width;
-  ctx.canvas.height = height;
-
-  // need to set font again after resizing canvas
-  ctx.font = font;
--  ctx.textBaseline = 'top';
-+  ctx.textBaseline = 'middle';
-+  ctx.textAlign = 'center';
-
-  ctx.fillStyle = 'blue';
-  ctx.fillRect(0, 0, width, height);
-
-+  // scale to fit but don't stretch
-+  const scaleFactor = Math.min(1, baseWidth / textWidth);
-+  ctx.translate(width / 2, height / 2);
-+  ctx.scale(scaleFactor, 1);
-  ctx.fillStyle = 'white';
-  ctx.fillText(name, borderSize, borderSize);
-
-  return ctx.canvas;
-}
-
-

次にラベルの幅を渡します。

-
-function makePerson(x, size, name, color) {
--  const canvas = makeLabelCanvas(size, name);
-+function makePerson(x, labelWidth, size, name, color) {
-+  const canvas = makeLabelCanvas(labelWidth, size, name);
-
-...
-
-}
-
--makePerson(-3, 32, 'Purple People Eater', 'purple');
--makePerson(-0, 32, 'Green Machine', 'green');
--makePerson(+3, 32, 'Red Menace', 'red');
-+makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 150, 32, 'Green Machine', 'green');
-+makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-

テキストが中央揃えのラベルを取得し、それに合わせて拡大縮小されています。

-

- -

-

上記ではそれぞれのテクスチャに新しいキャンバスを使用しました。 -テクスチャごとにキャンバスを使うかはあなた次第です。 -頻繁に更新する必要がある場合は、テクスチャごとに1つのキャンバスを使用するのがベストな選択かもしれません。

-

めったに更新されない場合は、Three.jsで強制的にテクスチャを使用し、1つのキャンバスを複数のテクスチャに使用できます。

-
+const ctx = document.createElement('canvas').getContext('2d');
-
-function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
--  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${size}px bold sans-serif`;
-
-  ...
-
-}
-
-+const forceTextureInitialization = function() {
-+  const material = new THREE.MeshBasicMaterial();
-+  const geometry = new THREE.PlaneGeometry();
-+  const scene = new THREE.Scene();
-+  scene.add(new THREE.Mesh(geometry, material));
-+  const camera = new THREE.Camera();
-+
-+  return function forceTextureInitialization(texture) {
-+    material.map = texture;
-+    renderer.render(scene, camera);
-+  };
-+}();
-
-function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // because our canvas is likely not a power of 2
-  // in both dimensions set the filtering appropriately.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-+  forceTextureInitialization(texture);
-
-  ...
-
-

- -

-

もう1つの問題はラベルが常にカメラに向いているとは限らない事です。 -ラベルをバッジにしているなら、それは良い事なのかもしれません。 -3Dゲームでプレイヤーの上に名前を置くためにラベルを使用している場合は、ラベルが常にカメラの方を向くようにしたいかもしれません。 -その方法はビルボードの記事で取り上げます。

-

特にラベルの場合はもう1つの解決策はHTMLを使う事です。 -この記事のラベルは他のオブジェクトで隠したい場合には良いですが、HTMLラベルは常に上にあります。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/cleanup.html b/manual/ja/cleanup.html deleted file mode 100644 index a33a034b832147..00000000000000 --- a/manual/ja/cleanup.html +++ /dev/null @@ -1,42 +0,0 @@ - - - Cleanup - - - - - - - - - - - - - -
-
-

Cleanup

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/custom-buffergeometry.html b/manual/ja/custom-buffergeometry.html deleted file mode 100644 index f2e79cc218f657..00000000000000 --- a/manual/ja/custom-buffergeometry.html +++ /dev/null @@ -1,388 +0,0 @@ - - - のカスタムバッファジオメトリ - - - - - - - - - - - - - -
-
-

のカスタムバッファジオメトリ

-
-
-
-

BufferGeometryは全てのジオメトリを表現する方法です。 -BufferGeometryはBufferAttributeを使います。1つのBufferAttributeはジオメトリを作るための1種類のデータに対応しています。vertexの位置情報を格納するためのBufferAttribute、color情報を格納するためのBufferAttribute、normal情報を格納するためのBufferAttributeがそれぞれあります。

-
- -

上の図ではposition, normal, color, uvそれぞれのattribute情報を格納したBufferAttributeを表しています。これらは並列な配列です。並列な配列というのはN番目にあるデータはN番目のvertexに対応しており、それがattributeの数だけあるという意味です。図ではindex=4のattributeがハイライトされています。

-
- -

上の図のハイライトされたvertexには、このvertexに接する全ての面に異なるnormalが必要です。normalとはどの方向を向いているかの情報です。 -この図ではnormalは角の頂点の周りの矢印で示されており、その頂点に接する全ての面には異なる方向を指すnormalが必要です。

-

同様に面ごとに違うUVも必要です。 -UVはテクスチャのどの部分に頂点位置が対応しているか指定するテクスチャ座標です。 -緑の面はFテクスチャの右上に対応するUV、青い面は左上に対応するUV、赤の面は左下に対応したUVが必要な事が分かります。

-

単一のvertexはこれらの情報の合成として表現されます。 -頂点が異なる部分を必要とする場合、それは異なる頂点でなければなりません。

-

簡単な例としてBufferGeometryを使って立方体を作ってみましょう。立方体を例にするのはvertexがfaceによって共有されているように見えて実は共有されていないからです。この例ではまずすべてのvertexの情報をリストアップして並列の配列に変換してBufferAttributeを作り、最後にBufferGeometryを作ります。

-

立方体に必要な情報をすべてリストアップします。Geometryでは1つのvertexを複数のfaceで共有できましたが今回は共有できないことに注意してください。つまり1つの立方体を作るために36個のvertexが必要になります。1つの面につき2つの三角形、1つの三角形につき3つのvertex、これが6面あるので36個のvertexが必要になる計算です。

-
const vertices = [
-  // front
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], },
-  // right
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], },
-  // back
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], },
-  // left
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], },
-  // top
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], },
-  // bottom
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], },
-];
-
-

次にこれを3つの並列な配列に変換します。 -(訳註:並列な配列parallel arraysとは例えば頂点を指定する配列と色を指定する配列があり1つの頂点をレンダリングするために2つの配列の同じインデックスの要素を指定するような使われ方をする配列のことです。次の例ではpositions, normals, uvsの3つの配列が並列の配列として使われています)

-
const positions = [];
-const normals = [];
-const uvs = [];
-for (const vertex of vertices) {
-  positions.push(...vertex.pos);
-  normals.push(...vertex.norm);
-  uvs.push(...vertex.uv);
-}
-
-

最後にそれぞれの配列に対してBufferAttributeを作りBufferGeometryに指定します。

-
  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-
-

名前の付け方に注意してください。three.jsで決められている名前以外を指定することはできません(カスタムシェーダーを使用する場合は別です)。position, normal, uvはthree.jsで決められている名前です。ここでは指定していませんがcolorも指定可能です。

-

上の例ではpositions, normals, uvsの3つのJavaScriptのネイティブ配列を作りました。次にFloat32Array型のTypedArraysに変換します。BufferAttributeはネイティブ配列ではなくTypedArrayである必要があります。さらにそれぞれのBufferAttributeに対して「1つのvertexに対していくつの要素が必要か」を指定する必要があります。例えばpositionやnormalsは3次元なので1つのvertexつき3つの要素を必要とします。UVはテクスチャ上の2次元の点なので2つの要素を必要とします。

-

- -

-

かなり大量のデータです。この配列からvertexを選ぶときにはインデックスを使います。1つの三角形は3つのvertexで構成されていて2つの三角形が1つのfaceを作っています。これが6枚で1つの立方体を構成しています。1つのfaceを構成する2つの三角形を作っているvertexは2つが同じデータを持っています。position, normal, UVすべて同じです。そこで重複しているデータを1つ消して1つにして、そのデータを別のインデックスで指定します。

-

ではまず重複したデータを1つにします。

-
const vertices = [
-  // front
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], }, // 2
--
--  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
--  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], }, // 3
-  // right
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], }, // 4
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], }, // 5
--
--  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
--  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], }, // 6
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], }, // 7
-  // back
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], }, // 8
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], }, // 9
--
--  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
--  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], }, // 10
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], }, // 11
-  // left
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], }, // 12
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], }, // 13
--
--  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], }, // 14
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], }, // 15
-  // top
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], }, // 16
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], }, // 17
--
--  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
--  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], }, // 18
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], }, // 19
-  // bottom
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], }, // 20
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], }, // 21
--
--  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
-];
-
-

はい、24個になりました。これに対して36個のインデックスを指定して36個のvertexを作ります。BufferGeometry.setIndexにより36個のインデックスを使って12個の三角形を作ります。

-
geometry.setAttribute(
-    'position',
-    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
-    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-+geometry.setIndex([
-+   0,  1,  2,   2,  1,  3,  // front
-+   4,  5,  6,   6,  5,  7,  // right
-+   8,  9, 10,  10,  9, 11,  // back
-+  12, 13, 14,  14, 13, 15,  // left
-+  16, 17, 18,  18, 17, 19,  // top
-+  20, 21, 22,  22, 21, 23,  // bottom
-+]);
-
-

- -

-

Geometryと同じようにBufferGeometrycomputeVertexNormalsメソッドを持っています。これは特に指定がない場合に自動的にnormalを計算するメソッドです。ただしGeometryの場合と違いvertexがfaceによって共有されていないためにcomputeVertexNormalsの結果も少し違います。

-
-
-
-
-
- -

シリンダーでcomputeVertexNormalsの違いを比較してみましょう。よく見ると左のシリンダーには縫い目が見えると思います。これはvertexを共有することができないためにUVも異なるためです。ちょっとしたことですが、気になるときは自分でnormalを指定すれば良いだけです。

-

ネイティブの配列を使う代わりにTypedArraysを使うこともできます。TypedArrayは最初に配列の大きさを指定する必要があるため少し面倒です。ネイティブの配列はpushで追加してlengthで配列の長さを確認することができます。TypedArrayにはpushメソッドがないのであらかじめ用意した配列に注意しながら要素を入れていく必要があります。

-

この例では最初に大きなデータを使っているので配列の長さを意識することはそれほど大変ではありません。

-
-const positions = [];
--const normals = [];
--const uvs = [];
-+const numVertices = vertices.length;
-+const positionNumComponents = 3;
-+const normalNumComponents = 3;
-+const uvNumComponents = 2;
-+const positions = new Float32Array(numVertices * positionNumComponents);
-+const normals = new Float32Array(numVertices * normalNumComponents);
-+const uvs = new Float32Array(numVertices * uvNumComponents);
-+let posNdx = 0;
-+let nrmNdx = 0;
-+let uvNdx = 0;
-for (const vertex of vertices) {
--  positions.push(...vertex.pos);
--  normals.push(...vertex.norm);
--  uvs.push(...vertex.uv);
-+  positions.set(vertex.pos, posNdx);
-+  normals.set(vertex.norm, nrmNdx);
-+  uvs.set(vertex.uv, uvNdx);
-+  posNdx += positionNumComponents;
-+  nrmNdx += normalNumComponents;
-+  uvNdx += uvNumComponents;
-}
-
-geometry.setAttribute(
-    'position',
--    new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-+    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
--    new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-+    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
--    new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-+    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-geometry.setIndex([
-   0,  1,  2,   2,  1,  3,  // front
-   4,  5,  6,   6,  5,  7,  // right
-   8,  9, 10,  10,  9, 11,  // back
-  12, 13, 14,  14, 13, 15,  // left
-  16, 17, 18,  18, 17, 19,  // top
-  20, 21, 22,  22, 21, 23,  // bottom
-]);
-
-

- -

-

TypedArrayはプログラムが走っている状態でvertexの編集をしたいときに便利です。

-

良い例が思いつかないのでとりあえずメッシュの四角形が出たり入ったりする球体を作ってみます。

-

球体の位置とindexを生成するコードです。四角形の中でvertexを共有していますが四角形と四角形でvertexを共有することはありません。共有してしまうと1つの四角形が出たり入ったりするたびに隣の四角形が移動してしまいます。今回は別々に移動させたいのでそうしています。

-

面倒なので3つのObject3D階層を用意して球体のvertexを計算します。くわしくはたくさんのオブジェクトを最適化するこの記事をご覧ください。

-
function makeSpherePositions(segmentsAround, segmentsDown) {
-  const numVertices = segmentsAround * segmentsDown * 6;
-  const numComponents = 3;
-  const positions = new Float32Array(numVertices * numComponents);
-  const indices = [];
-
-  const longHelper = new THREE.Object3D();
-  const latHelper = new THREE.Object3D();
-  const pointHelper = new THREE.Object3D();
-  longHelper.add(latHelper);
-  latHelper.add(pointHelper);
-  pointHelper.position.z = 1;
-  const temp = new THREE.Vector3();
-
-  function getPoint(lat, long) {
-    latHelper.rotation.x = lat;
-    longHelper.rotation.y = long;
-    longHelper.updateMatrixWorld(true);
-    return pointHelper.getWorldPosition(temp).toArray();
-  }
-
-  let posNdx = 0;
-  let ndx = 0;
-  for (let down = 0; down < segmentsDown; ++down) {
-    const v0 = down / segmentsDown;
-    const v1 = (down + 1) / segmentsDown;
-    const lat0 = (v0 - 0.5) * Math.PI;
-    const lat1 = (v1 - 0.5) * Math.PI;
-
-    for (let across = 0; across < segmentsAround; ++across) {
-      const u0 = across / segmentsAround;
-      const u1 = (across + 1) / segmentsAround;
-      const long0 = u0 * Math.PI * 2;
-      const long1 = u1 * Math.PI * 2;
-
-      positions.set(getPoint(lat0, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat0, long1), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long1), posNdx);  posNdx += numComponents;
-
-      indices.push(
-        ndx, ndx + 1, ndx + 2,
-        ndx + 2, ndx + 1, ndx + 3,
-      );
-      ndx += 4;
-    }
-  }
-  return {positions, indices};
-}
-
-

こんな感じです。

-
const segmentsAround = 24;
-const segmentsDown = 16;
-const {positions, indices} = makeSpherePositions(segmentsAround, segmentsDown);
-
-

returnされているpositionは単位球(半径が1の球体)なのでそのままこのデータをnormalに使えます。

-
const normals = positions.slice();
-
-

attributeも設定しましょう。

-
const geometry = new THREE.BufferGeometry();
-const positionNumComponents = 3;
-const normalNumComponents = 3;
-
-+const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents);
-+positionAttribute.setUsage(THREE.DynamicDrawUsage);
-geometry.setAttribute(
-    'position',
-+    positionAttribute);
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setIndex(indices);
-
-

position attributeに対する参照を保存しています。dynamicに指定しているところも注意が必要です。これはTHREE.jsに「これからこのattributeは変更が加えられる」ことを教えます。renderループではpositionを毎度アップデートします。

-
const temp = new THREE.Vector3();
-
-...
-
-for (let i = 0; i < positions.length; i += 3) {
-  const quad = (i / 12 | 0);
-  const ringId = quad / segmentsAround | 0;
-  const ringQuadId = quad % segmentsAround;
-  const ringU = ringQuadId / segmentsAround;
-  const angle = ringU * Math.PI * 2;
-  temp.fromArray(normals, i);
-  temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5));
-  temp.toArray(positions, i);
-}
-positionAttribute.needsUpdate = true;
-
-

最後にpositionAttribute.needsUpdateを設定してTHREE.jsに変更が必要であることを伝えます。

-

- -

-

BufferGeometryを作ってBufferAttributeをアップデートする方法を紹介しました。

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/debugging-glsl.html b/manual/ja/debugging-glsl.html deleted file mode 100644 index c06028299876c4..00000000000000 --- a/manual/ja/debugging-glsl.html +++ /dev/null @@ -1,94 +0,0 @@ - - - でのGLSLデバッグ - - - - - - - - - - - - - -
-
-

でのGLSLデバッグ

-
-
-
-

このサイトではJavaScriptについては教えてないと同様にGLSLについても教えていません。 -それは本当に大きなトピックです。GLSLを学びたいのであればこれらの記事から始めてみて下さい。

-

すでにGLSLを知っている場合はデバッグのヒントをいくつか紹介します。

-

新しくGLSLシェーダーを作成し何も表示されない場合、一般的に最初にするのはフラグメントシェーダーでソリッドカラーに変更する事です。例えばシェーダーの一番下を以下のようにします。

-
void main() {
-
-  ...
-
-  gl_FragColor = vec4(1, 0, 0, 1);  // red
-}
-
-

描画しようとしたオブジェクトが表示されれば、その問題がフラグメントシェーダーに関係している事がわかります。良くないテクスチャ、初期化がないuniform変数、間違った値を持つuniform変数の可能性がありますが、私には見るべきポイントがあります。

-

いくつかをテストするために入力値を描画してみようと思います。 -例えばフラグメントシェーダーで法線を使用している場合は次のように追加します。

-
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
-
-

法線は-1から+1までなので、0.5を掛けて0.5を足すと0.0から1.0までの値が得られて色で判別できて便利です。

-

動作すると知ってるコード変更をいくつか試してみて下さい。正常な通常の描画がどのように見えるか目に見えてわかるようになります。 -通常に見えない箇所があれば、どこを見て直せば良いかのヒントがあります。 -フラグメントシェーダーで法線を操作している場合、その操作の結果を描画するために同じテクニックが使えます。

-
- -

テクスチャを使用している場合も同様に、テクスチャ座標で以下のように描画できます。

-
gl_FragColor = vec4(fract(vUv), 0, 1);
-
-

fract は0から1の範囲外のテクスチャ座標を使用している場合に使用します。 -これは texture.repeat が1よりも大きい値に設定されている場合によく見られます。

-
- -

フラグメントシェーダーの全ての値に対して同様の事ができます。 -その範囲を把握し、0.0から1.0にスケーリングし gl_FragColor に設定するコードを追加します。

-

テクスチャを確認するには CanvasTextureDataTexture が動作するもので試してみて下さい。

-

逆に言えば gl_FragColor を赤に設定しても何も表示されない場合、問題は頂点シェーダーに関連したものにあるかもしれません。 -一部の行列が間違っていたり、attributesが間違ったデータを持っていたり、設定が間違っていたりする事があります。

-

私ならまず行列を見ます。renderer.renderer.render(scene, camera) の呼出直後にブレークポイントを設定し、インスペクタで展開を始めるかもしれません。 -カメラのワールド座標とプロジェクション座標は NaN でいっぱいではないのか? -シーンを展開し children を見てみるとワールド座標が妥当に見えるか( NaN がない)、各行列の最後の4つの値がシーンにとって妥当に見えるかを確認します。 -シーンが50 x 50 x 50 x 50の単位であるはずが、いくつかの行列が552352623.123の場合は明らかに何かが間違っている事がわかります。

-
- -

フラグメントシェーダーの時と同様に、頂点シェーダーの値をフラグメントシェーダーに渡すと頂点シェーダーから値を描画する事もできます。 -両方のシェーダーでvaryingを宣言し、正しい値なのかわからない値を渡します。 -実際にシェーダーが法線を使っている場合、値が0.0から1.0になるように vNormal を値に設定し法線を表示するようにします。 -描画結果を見て予想通りか確認します。

-

もう一つの良い点はよりシンプルなシェーダーを使う事です。 -MeshBasicMaterial でデータを描画できますか? -可能であれば試してみて期待通りに表示される事を確認して下さい。

-

期待通りでない場合、ジオメトリをビジュアライズできる最もシンプルな頂点シェーダーは何でしょうか? -通常は次のようなシンプルなものです。

-
gl_Position = projection * modelView * vec4(position.xyz, 1);
-
-

それが動作する場合は一度に少しずつ変更を追加していきます。

-

もう一つの方法はShader Editor extension for Chromeを使うか、他のブラウザでは同様なものを使う事です。 -他のシェーダーがどのように動作してるか見る良い方法です。また、上記で記載してきたフラグメントシェーダーの変更を行うとライブで結果確認できるので良いです。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/debugging-javascript.html b/manual/ja/debugging-javascript.html deleted file mode 100644 index 23394930d3f80b..00000000000000 --- a/manual/ja/debugging-javascript.html +++ /dev/null @@ -1,396 +0,0 @@ - - - でのJavaScriptデバッグ - - - - - - - - - - - - - -
-
-

でのJavaScriptデバッグ

-
-
-
-

この記事のほとんどはTHREE.jsのデバッグと言うより、一般的なJavaScriptのデバッグの内容です。THREE.js初心者にはJavaScript初心者も多いので、この記事を読んで困った時に簡単に解決できるようになると良いと思います。

-

デバッグは大きなトピックであり、この記事で全てをカバーできませんが、JavaScriptに慣れていない場合はいくつかのヒントを得られると思います。デバッグに関しては、時間をかけて学ぶ事を強くお勧めします。デバッグはあなたの学習を大いに助けてくれます。

-

ブラウザの開発者ツールを学ぶ

-

全てのブラウザには開発者ツールがあります。 -Chrome, -Firefox, -Safari, -Edge.

-

Chromeでは アイコンをクリックし、その他のツール -> デベロッパーツールを選択すると開発者ツールが表示されます。そこにはキーボードのショートカットも表示されています。

-
- -

Firefoxでは アイコンをクリックし、"ウェブ開発"から"開発者ツール"を選択します。

-
- -

Safariでは詳細設定メニューから開発メニューを有効にする必要があります。

-
- -

次に開発メニューで"Webインスペクタの表示/接続"を選択します。

-
- -

Chromeを使ってAndroidやタブレットでChrome上で実行されているウェブページをデバッグする事もできます。 -同様にSafariではiPhoneやiPadでSafari上で実行されているウェブページをPCでデバッグする事ができます

-

私はChromeを一番よく知ってるのでChromeを例にしますが、ほとんどのブラウザは似たような機能を持っているため、全てのブラウザで簡単に同じ機能を適用できるはずです。

-

キャッシュをオフにする

-

ブラウザはダウンロードしたデータを再利用します。これはウェブサイトを2回目に訪れた際、サイトを表示するために必要な多くのファイルは再びダウンロードされず、ユーザーにとって素晴らしい事です。

-

一方でこれはウェブ開発に悪い影響を与える可能性があります。PC上でファイルを変更しリロードしても、前回ダウンロードしたバージョンを使用しているため変更内容が表示されません。

-

ウェブ開発中の解決策の1つは、キャッシュをオフにする事です。これによりブラウザは常に最新バージョンのファイルを取得する事ができます。

-

最初にデベロッパーツールのSettingsメニューを選択します。

-
- -

次に "Disable Cache (while DevTools is open)" を選択します。

-
- -

JavaScriptコンソールを使用する

-

全てのdevtoolsの中には console があります。ここには警告やエラーメッセージが表示されます。

-

メッセージを読みましょう!!

-

一般的にはメッセージは1つか2つしかありません。

-
- -

もし他のメッセージがあればメッセージを読みましょう。例えば

-
- -

"three"を"threee"とスペルミスしました。

-

以下のように console.log であなた自身がconsoleに情報を表示する事もできます。

-
console.log(someObject.position.x, someObject.position.y, someObject.position.z);
-
-

さらにクールな事にオブジェクトのログを記録したり検査する事ができます。例えばgLTFの記事からルートシーンのオブジェクトをログに表示できます。

-
  {
-    const gltfLoader = new GLTFLoader();
-    gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-      const root = gltf.scene;
-      scene.add(root);
-+      console.log(root);
-
-

そしてそのオブジェクトをJavaScriptコンソールで展開できます。

-
- -

スタックトレースを含む赤色メッセージを表示する場合は console.error を使う事ができます。

-

データを画面に表示させる

-

もう1つの分かりやすい方法は <div><pre> を追加しデータを入れる事です。

-

最も分かりやすい方法はいくつかのHTML要素を作成する事です。

-
<canvas id="c"></canvas>
-+<div id="debug">
-+  <div>x:<span id="x"></span></div>
-+  <div>y:<span id="y"></span></div>
-+  <div>z:<span id="z"></span></div>
-+</div>
-
-

キャンバスの上に残るようにスタイルを整えます(キャンバスがページを埋めていると仮定します)。

-
<style>
-#debug {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-  padding: 1em;
-  background: rgba(0, 0, 0, 0.8);
-  color: white;
-  font-family: monospace;
-}
-</style>
-
-

そして要素を探して内容を設定します。

-
// at init time
-const xElem = document.querySelector('#x');
-const yElem = document.querySelector('#y');
-const zElem = document.querySelector('#z');
-
-// at render or update time
-xElem.textContent = someObject.position.x.toFixed(3);
-yElem.textContent = someObject.position.y.toFixed(3);
-zElem.textContent = someObject.position.z.toFixed(3);
-
-

これはリアルタイムな値を見る時はとても便利です。

-

- -

-

または画面にデータを貼り付けるのにクリアロガーを作成する方法もあります。私はその言葉を作っただけですが、私が手がけたゲームの多くはこの解決法を使っています。 -このアイデアは1フレーム分だけメッセージを表示するバッファを持つ事です。 -データを表示したいコードのどの部分でも、フレームごとにバッファにデータを追加する関数を呼び出します。これは上記のデータのピースごとに要素を作成するよりもはるかに少ない作業です。

-

例えば上記のHTMLを以下のように変更してみましょう。

-
<canvas id="c"></canvas>
-<div id="debug">
-  <pre></pre>
-</div>
-
-

このクリアバックバッファを管理するための簡単なクラスを作ってみましょう。

-
class ClearingLogger {
-  constructor(elem) {
-    this.elem = elem;
-    this.lines = [];
-  }
-  log(...args) {
-    this.lines.push([...args].join(' '));
-  }
-  render() {
-    this.elem.textContent = this.lines.join('\n');
-    this.lines = [];
-  }
-}
-
-

次にマウスをクリックするたびに2秒間のランダムな方向に移動するメッシュを作成する簡単な例を作ってみましょう。レスポンシブデザインの記事から例を紹介します。

-

マウスをクリックするたびに新しい Mesh を追加するコードは以下の通りです。

-
const geometry = new THREE.SphereGeometry();
-const material = new THREE.MeshBasicMaterial({color: 'red'});
-
-const things = [];
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min;
-}
-
-function createThing() {
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  things.push({
-    mesh,
-    timer: 2,
-    velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
-  });
-}
-
-canvas.addEventListener('click', createThing);
-
-

このコードは作成したメッシュを移動させログに記録し、タイマーが切れたら削除します。

-
const logger = new ClearingLogger(document.querySelector('#debug pre'));
-
-let then = 0;
-function render(now) {
-  now *= 0.001;  // convert to seconds
-  const deltaTime = now - then;
-  then = now;
-
-  ...
-
-  logger.log('fps:', (1 / deltaTime).toFixed(1));
-  logger.log('num things:', things.length);
-  for (let i = 0; i < things.length;) {
-    const thing = things[i];
-    const mesh = thing.mesh;
-    const pos = mesh.position;
-    logger.log(
-        'timer:', thing.timer.toFixed(3),
-        'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
-    thing.timer -= deltaTime;
-    if (thing.timer <= 0) {
-      // remove this thing. Note we don't advance `i`
-      things.splice(i, 1);
-      scene.remove(mesh);
-    } else {
-      mesh.position.addScaledVector(thing.velocity, deltaTime);
-      ++i;
-    }
-  }
-
-  renderer.render(scene, camera);
-  logger.render();
-
-  requestAnimationFrame(render);
-}
-
-

以下のサンプルでマウスをクリックして下さい。

-

- -

-

クエリパラメーター

-

もう1つ覚えておきたいのは、ウェブページにはクエリパラメーターやアンカーを介してデータを渡す事ができます。検索とハッシュと呼ばれる事があります。

-
https://domain/path/?query#anchor
-

これを使用しオプション機能やパラメーターを渡す事ができます。

-

先ほどの例では次のようにしています。デバッグ機能はURLに ?debug=true を指定した場合にのみ表示されます。

-

まず、クエリストリングを解析するコードが必要です。

-
/**
-  * Returns the query parameters as a key/value object.
-  * Example: If the query parameters are
-  *
-  *    abc=123&def=456&name=gman
-  *
-  * Then `getQuery()` will return an object like
-  *
-  *    {
-  *      abc: '123',
-  *      def: '456',
-  *      name: 'gman',
-  *    }
-  */
-function getQuery() {
-  return Object.fromEntries(new URLSearchParams(window.location.search).entries());
-}
-
-

そうすると、debug要素をデフォルトでは表示しないようにする事ができるかもしれません。

-
<canvas id="c"></canvas>
-+<div id="debug" style="display: none;">
-  <pre></pre>
-</div>
-
-

このコードをみると ?debug=true が渡された場合のみデバッグ情報を表示するのが分かります。

-
const query = getQuery();
-const debug = query.debug === 'true';
-const logger = debug
-   ? new ClearingLogger(document.querySelector('#debug pre'))
-   : new DummyLogger();
-if (debug) {
-  document.querySelector('#debug').style.display = '';
-}
-
-

?debug=true の場合は何も渡さないように DummyLogger を作りました。

-
class DummyLogger {
-  log() {}
-  render() {}
-}
-
-

以下のURLを使用して確認する事ができます。

-

debug-js-params.html

-

上記にはデバッグ情報はありません。

-

debug-js-params.html?debug=true

-

こちらにはデバッグ情報があります。

-

複数のパラメーターは somepage.html?someparam=somevalue&someotherparam=someothervalue のように'&'で区切る事で渡せます。 -このようなパラメータを使用するとあらゆる種類のオプションを渡す事ができます。 -speed=0.01 のようにアプリの速度を遅くしてわかりやすくしたり、showHelpers=true のように他のレッスンで見られる照明や影、カメラの錐台を表示するヘルパーを追加してもいいかもしれません。

-

デバッガの使い方を学ぶ

-

どのブラウザにもデバッガがあり、プログラムを1行ごとに一時停止し全ての変数を検査する事ができます。

-

デバッガの使い方を教えるのはあまりにも大きなトピックなので、ここではいくつかのリンクを紹介します。

- -

デバッガなどで NaN がないかチェックする

-

NaN は Not A Numberの略です。これは数学的に意味のない事をした場合、JavaScript が値として代入するものです。

-

簡単な例としては

-
- -

何か開発中に画面に何も表示されない事がよくあるので、私は NaN が表示されたらその場所からすぐにいくつかの値を確認します。

-

例として最初にgLTFファイルの読込の記事でパスを作り始めた時に2次元曲線を作るSplineCurveクラスを使って曲線を作ってみました。

-

そのカーブを利用してこのように車を動かしました。

-
curve.getPointAt(zeroToOnePointOnCurve, car.position);
-
-

内部的には curve.getPointAt は第2引数に渡されたオブジェクトに対して set 関数を呼び出します。この場合、第2引数は car.position であり、これは Vector3 です。Vector3set 関数はx, y, zの3つの引数を必要としますが、SplineCurve は2次元曲線なので、xとyだけを指定して car.position.set を呼び出します。

-

その結果、car.position.set はxにx、yにy、zに undefined をセットします。

-

デバッガで matrixWorld を見てみると NaN 値が表示されています。

-
- -

行列を見ると NaN が含まれており、positionrotationscale または他の関数に悪い影響を与えるデータがあるのが見えます。これらの悪いデータから逆算すると問題を追跡するのは簡単です。

-

NaN の上には Infinity もありますが、これはどこかに数学のバグがあるような気がします。

-

コードの中を見て!

-

THREE.jsはオープンソースです。コードの中を見る事を恐れないで下さい! -githubで内部コードを見れます。 -また、デバッガの関数を踏み込んで内部を見る事もできます。その際には three.min.js でなく three.js を見るようにして下さい。three.min.js は最小化・圧縮されたバージョンなので、ダウンロードする際のサイズが小さくなっています。three.js はサイズは大きいですが、デバッグしやすいバージョンです。私はよく three.js に切り替えて、コードのステップスルーを行い、何が起こっているのかを確認しています。

-

requestAnimationFrame はrender関数の一番下へ

-

以下のパターンはよく見かけます。

-
function render() {
-   requestAnimationFrame(render);
-
-   // -- do stuff --
-
-   renderer.render(scene, camera);
-}
-requestAnimationFrame(render);
-
-

以下のように requestAnimationFrame を一番下に置く事をお勧めします。

-
function render() {
-   // -- do stuff --
-
-   renderer.render(scene, camera);
-
-   requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

最大の理由はエラーが発生した場合にコードが停止する事です。 -requestAnimationFrame を先頭に置くと、既に別のフレームを要求しているためにエラーが発生してもコードを実行し続けます。 -IMOを無視するよりも、それらのエラーを見つける方が良いでしょう。これらのエラーは何かが期待したように表示されない原因になりやすいのですが、コードが停止しない限り、気がつかないかもしれません。

-

単位をチェックして下さい!

-

角度やラジアンを使う時の例を知っておく必要があります。 -残念ながらTHREE.jsではどこでも同じ単位を使用している訳ではありません。 -すぐに思いつくのだとカメラの視野は度単位です。それ以外の角度は全てラジアン単位です。

-

もう1つ注目したいのは、世界単位のサイズです。最近の3Dアプリでは好きな単位を選べるようになっています。あるアプリでは1単位=1cmを選択する事があります。もう1つのアプリでは1台=1フィートを選ぶかもしれません。特定のアプリケーションでは必要なユニットを選択する事ができます。three.jsでは1単位=1メートルを想定しています。 -これは測定器を使用して照明効果を計算する物理ベースのレンダリングなどで重要です。 -スマホがどこにあるか、VRコントローラーがどこにあるかなど、現実世界の単位を扱う必要があるARやVRにとっても重要です。

-

スタックオーバーフローのための 最小で完全で検証可能なサンプルコード の作成

-

THREE.jsの質問をする場合、MCVE(Minimal<最小>、Complete<完全>、Verifiable<検証可能>、Example<サンプル>の略)のコードを提供する事が求められます。

-

最小の部分が重要です。gLTF読込の記事の最後のサンプルコードでパスの動きに問題があったとしましょう。そのサンプルには多くのパーツがあり、リストアップすると

-
    -
  1. HTMLの集まり
  2. -
  3. いくつかのCSS
  4. -
  5. ライティング
  6. -
  7. -
  8. 影を操作するためのlil-guiコード
  9. -
  10. GLTFファイルの読込コード
  11. -
  12. キャンバスのリサイズコード
  13. -
  14. パスに沿って車を移動させるコード
  15. -
-

このコードはかなり大きいです。もし質問がパスの後に続く部分だけであれば、THREE.jsの <canvas><script> タグだけで済むので、ほとんどのHTMLを削除する事ができます。また、CSSとリサイズのコードを削除する事ができます。GLTFのコードもパスだけを気にしているので削除できます。MeshBasicMaterial を使用するとライトとシャドウも削除する事ができます。lil-guiのコードも確実に削除できます。 -このコードはテクスチャ付きの地面を作ります。GridHelper を使った方が簡単です。 -最終的にもし質問したい事がパス上での移動についてなら、ロードされた車モデルの代わりにパス上にキューブを使用する事ができます。

-

以上の事を考慮したミニマムなサンプルコードを紹介します。271行から135行に縮小しました。パスを単純化する事でさらに縮小する事も考られます。3,4点のパスは、21点のパスと同じように動作するかもしれません。

-

- -

-

OrbitController を残してるのはカメラを動かして何が起こっているのかを把握するのに便利だからですが、問題によってはこれも削除できるかもしれません。

-

MCVEを作る上で一番良い点は、自分自身で解決する事が多いという事です。不要なものを取り除いて可能な限り小さなサンプルコードを作って問題を再現する事で、バグにたどり着く事が多いからです。

-

その上でStack Overflowで自分のコードを見てもらうのは、回答者の時間を尊重する事になります。最小限のサンプルを作る事で、誰かがあなたを助ける事がはるかに簡単になります。また、その過程で以下を学ぶ事ができます。

-

Stack Overflowに質問を投稿する際、コードをスニペットにする事が重要です。 -もちろん、MCVEを試すためにJSFiddleやCodepen、または同様のサイトを使用する事は歓迎しますが、実際にStack Overflowに質問を投稿するようになったら、質問自体に問題を再現するためのコードを記述する必要があります。 -スニペットを作る事でその条件を満たしています。

-

また、このサイト上の全てのライブサンプルはスニペットとして実行されるべきである事に注意して下さい。HTML、CSS、JavaScriptの部分をスニペットエディタのそれぞれの部分にコピーするだけです。ただし、自分の問題に関係のない部分を削除し、必要最低限のコードにするのを忘れないようにして下さい。

-

これらに従えば、あなたの問題は助けを得る可能性がはるかに高くなります。

-

MeshBasicMaterial を使用する

-

MeshBasicMaterial はライトを使用しないので、何かが表示されない理由を取り除く1つの方法です。もしオブジェクトが MeshBasicMaterial を使用して表示されない場合は、コードの他の部分ではなくマテリアルやライトに問題がある可能性が高い事がわかります。

-

カメラの nearfar の設定を確認する

-

PerspectiveCamera には nearfar の設定があり、それはカメラの記事 で説明しています。 -オブジェクトを含む空間に合わせて設定されている事を確認して下さい。 -例えば near = 0.001、far = 1000000のような大きな値に一時的に設定する事もできます。 -奥行き解像度の問題が発生する可能性がありますが、少なくともカメラの前にあるオブジェクトを見る事ができるようになります。

-

カメラの前にシーンがある事を確認する

-

時にはカメラの前になく何も出てこない事もあります。カメラを制御できない場合は OrbitController のようなカメラコントロールを追加してみて下さい。 -あるいはこの記事で紹介されているコードを使ってシーンをフレーミングしてみて下さい。 -このコードはシーンの一部のサイズを見つけ、カメラを移動して nearfar の設定を調整し、それが見えるようにします。

-

カメラの前に何かを置く

-

これは全てに失敗した場合は、動作するものから始めてゆっくりと何かを追加していくという方法です。何もない画面が表示された場合は、直接カメラの前に何かを置いてみて下さい。 -球体や箱を作り MeshBasicMaterialのようなシンプルなマテリアルを与えて、それを画面上に表示できるようにします。 -その後、少しずつ追加してテストを開始します。最終的にはバグを再現するか、途中で発見するかのどちらかになります。

-
-

以上、JavaScriptのデバッグのヒントでした。GLSLをデバッグするためのいくつかのヒントも見てみましょう。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/fog.html b/manual/ja/fog.html deleted file mode 100644 index 2d9180f59d37d6..00000000000000 --- a/manual/ja/fog.html +++ /dev/null @@ -1,265 +0,0 @@ - - - のフォグ - - - - - - - - - - - - - -
-
-

のフォグ

-
-
-
-

この記事はThree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでいない場合、そこから始めると良いかもしれません。 -カメラの記事を読んでない方は、まずはこの記事を読んでみて下さい。

-

一般的には3Dエンジンでのフォグ(霧)は、カメラからの距離によって特定の色にフェードアウトする方法です。 -three.jsでは Fog または FogExp2 オブジェクトを作成し、シーンにfog プロパティを設定してフォグを追加します。

-

Fog はカメラからの距離を表す nearfar があります。 -near よりも近いものはフォグの影響を受けません。 -far より遠いものはフォグの影響を受けます。 -nearfar の中間部分では、マテリアルの色からフォグの色にグラデーションします。

-

また、カメラからの距離で急激にグラデーションする FogExp2 もあります。

-

どちらのタイプのフォグも使用するにはフォグを作成してシーンに割り当てます。

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;  // white
-  const near = 10;
-  const far = 100;
-  scene.fog = new THREE.Fog(color, near, far);
-}
-
-

FogExp2 の場合は次のようなコードになります。

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;
-  const density = 0.1;
-  scene.fog = new THREE.FogExp2(color, density);
-}
-
-

FogExp2 は現実表現に近いですが、Fog の方が一般的によく使われています。 -Fogは適用する場所を選択できるので、ある距離まではクリアなシーンを表示し、その距離を過ぎるとフェードアウトした色にできます。

-
-
-
-
THREE.Fog
-
-
-
-
THREE.FogExp2
-
-
- -

ここで注意すべき点は、フォグは レンダリングされる ものに適用される事です。 -以下はオブジェクトの色の各ピクセルの計算の一部です。 -つまり、シーンを特定の色にフェードさせたい場合、フォグ 背景色を同じ色に設定します。 -背景色は scene.background プロパティで設定します。 -背景色は THREE.Color で指定します。例えば

-
scene.background = new THREE.Color('#F00');  // red
-
-
-
-
-
fog blue, background red
-
-
-
-
fog blue, background blue
-
-
- -

以下はフォグを追加した例です。 -シーンにフォグを追加し背景色を設定します。

-
const scene = new THREE.Scene();
-
-+{
-+  const near = 1;
-+  const far = 2;
-+  const color = 'lightblue';
-+  scene.fog = new THREE.Fog(color, near, far);
-+  scene.background = new THREE.Color(color);
-+}
-
-

以下の例ではカメラの near は 0.1、far は 5です。 -カメラは z = 2 にあります。 -立方体は1の大きさで z = 0 です。 -つまり、フォグを near = 1far = 2 と設定し、立方体の中心付近でフェードアウトしています。

-

- -

-

フォグを調整するインターフェースを追加してみましょう。 -ここでもlil-guiを使用します。 -lil-guiはオブジェクトとプロパティを受け取り、インタフェースを自動生成します。 -これでフォグの nearfar プロパティを簡単に操作できます。 -しかし、 nearfar より大きい場合は無効になります。 -lil-guiで nearfar を操作するヘルパーを作ってみましょう。

-
// We use this class to pass to lil-gui
-// so when it manipulates near or far
-// near is never > far and far is never < near
-class FogGUIHelper {
-  constructor(fog) {
-    this.fog = fog;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-}
-
-

次のコードを追加します。

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-+
-+  const fogGUIHelper = new FogGUIHelper(scene.fog);
-+  gui.add(fogGUIHelper, 'near', near, far).listen();
-+  gui.add(fogGUIHelper, 'far', near, far).listen();
-}
-
-

nearfar のパラメーターは、フォグを調整する最小値と最大値を設定します。 -これはカメラ設定時にセットします。

-

最後の2行の .listen() をlil-guiに変更し listen するようにします。 -これで nearfar の変更時、lil-guiが他のプロパティのUIを更新してくれます。

-

フォグの色を変更できますが、上記で述べたようにフォグの色と背景色を同期させる必要があります。 -lil-gui操作時に両方の色を変更する virtual プロパティをヘルパーに追加してみましょう。

-

lil-guiでは4つの方法で色を操作できます。

-
    -
  1. CSSの6桁の16進数(例: #112233)

    -
  2. -
  3. 色相、彩度、値、オブジェクト (例: {h: 60, s: 1, v: })

    -
  4. -
  5. RGB (例: [255, 128, 64])

    -
  6. -
  7. RGBA(例:[127, 200, 75, 0.3]

    -
  8. -
-

lil-guiが単一の値を操作するので、16進数を使うのが一番簡単です。 -幸運な事に THREE.ColorgetHexString を使用でき、文字列を簡単に取得できます。

-
// We use this class to pass to lil-gui
-// so when it manipulates near or far
-// near is never > far and far is never < near
-+// Also when lil-gui manipulates color we'll
-+// update both the fog and background colors.
-class FogGUIHelper {
-*  constructor(fog, backgroundColor) {
-    this.fog = fog;
-+    this.backgroundColor = backgroundColor;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-+  get color() {
-+    return `#${this.fog.color.getHexString()}`;
-+  }
-+  set color(hexString) {
-+    this.fog.color.set(hexString);
-+    this.backgroundColor.set(hexString);
-+  }
-}
-
-

gui.addColor を呼び出し、ヘルパーのvirtualプロパティにcolorのlil-guiを追加します。

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-
-*  const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
-  gui.add(fogGUIHelper, 'near', near, far).listen();
-  gui.add(fogGUIHelper, 'far', near, far).listen();
-+  gui.addColor(fogGUIHelper, 'color');
-}
-
-

- -

-

near を1.9、far を2.0にすると以下のようになりました。 -曇っていない状態と完全に曇っている状態との中間では、シャープなグラデーションします。 -near = 1.1、far = 2.9 とすると、カメラから 2 離れて回転する立方体で最も滑らかになります。

-

最後に、マテリアルでレンダリングされたオブジェクトがフォグの影響を受けるか判断するために、マテリアルにはboolean型のfogプロパティがあります。 -そのマテリアルを使用してる場合は、フォグの影響を受けます。 -ほとんどのマテリアルのデフォルトは true です。 -フォグを消去する理由は、運転席やコックピットからの視点で3Dの車のシミュレーターを作っている時を想像して下さい。 -車内から見ると、車内の全てのものはフォグを外しておきたいと思うでしょう。

-

フォグの良い例としては、家の外に濃いフォグが出ている場合が挙げられます。 -例えば、フォグが2m先(near = 2)から始まり、4m先(far = 4)でフォグがあるとします。 -部屋の長さは2メートル以上、家の長さは4メートル以上で、家の中にフォグがかからないように設定が必要です。 -設定しない場合に家の中に立っている時に部屋の奥の壁の外を見ると、フォグの中にいるように見えてしまいます。

-
-
-
-
fog: true, all
-
-
- -

部屋の奥の壁と天井にフォグがかかっています。 -家のマテリアルのフォグをオフにすると、この問題が解決できます。

-
-
-
-
fog: true, only outside materials
-
-
- -

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/fundamentals.html b/manual/ja/fundamentals.html deleted file mode 100644 index 3dc8eeea5e3dce..00000000000000 --- a/manual/ja/fundamentals.html +++ /dev/null @@ -1,319 +0,0 @@ - - - の基礎知識 - - - - - - - - - - - - - -
-
-

の基礎知識

-
-
-
-

これはthree.jsの最初の連載記事です。 -Three.js は、できるだけ簡単にWebページ上に3Dコンテンツを表示する3Dライブラリです。

-

Three.jsはWebGLと混同される事がよくあります。 -常にではないですが、ほとんどの場合three.jsはWebGLを使用して3Dを描画するためです。 -WebGLはポイントやライン、三角形のみを描画する非常に低レベルのシステムです。 -three.jsを使わない場合、WebGLで何か便利な事を行うには通常かなりのコードが必要です。 -もしWebGLを直接書く場合、シーンやライト、シャドウやマテリアル、テクスチャや3D数学をあなた自身で制御する必要があります。

-

これらのチュートリアルはJavaScriptを知っている事を前提としており、ほとんどの部分でES6スタイルを使用します。 -あなたがすでに知っている事が期待される簡潔なリストはこちらをご覧下さい。 -three.jsがサポートするほとんどのブラウザは自動更新されるため、ほとんどのユーザーはこのコードを実行できます。 -古いブラウザーで実行したい場合は、Babel のようなトランスパイラーを調べて下さい。 -もちろん、本当に古いブラウザを実行しているユーザーはthree.jsを実行できないマシンを持っている可能性があります。

-

ほとんどのプログラミング言語を学ぶ時、最初にする事は "Hello World!" を表示する事です。 -3Dで最初に行う最も一般的な事の1つは、3Dキューブを作成する事です。 -それでは "Hello Cube!" から始めましょう。

-

最初に必要なのは <canvas> タグです。

-
<body>
-  <canvas id="c"></canvas>
-</body>
-
-

Three.jsはcanvasに描画するため、canvasをthree.jsに渡す必要があります。

-
<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  ...
-</script>
-
-

scriptタグに type="module" を含めることが重要です。 -これにより import キーワードを使用してthree.jsを読み込む事ができます。 -three.jsを読み込む方法は他にもありますが、r106の時点ではモジュールを使用する事をお勧めします。 -モジュールには、必要な他のモジュールを簡単にインポートできるという利点があります。 -これにより、依存している追加のスクリプトを手動で読み込む必要がなくなります。

-

ここにいくつかの難解な事があります。 -もしcanvasをthree.jsに渡さない場合、canvasをdocumentに追加する必要があります。 -canvasを追加する場所は、ユースケースに応じて変わる可能性があります。 -また、コードを変更する必要があるため、canvasをthree.jsに渡す事は少し柔軟性があると感じます。 -canvasをどこにでも配置でき、コードを見つける事ができます。 -canvasをdocumentに挿入するコードがあるかのように、ユースケースが変更された場合、そのコードを変更する必要があります。

-

canvasを検索した後、WebGLRenderer を作成します。 -rendererは提供された全てのデータを取得し、canvasにレンダリングします。

-

今はWebGLを使用して3Dをcanvasにレンダリングする WebGLRenderer があります。

-

次はカメラが必要です。

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

fovfield of view の略です。この場合、垂直方向に75度を表します。 -three.jsのほとんどの角度はラジアン単位ですが、いくつかの理由でパースペクティブカメラは角度を設定します。

-

aspect はcanvasの表示アスペクトです。 -別の記事で詳細を説明しますが、デフォルト値はcanvasは300x150ピクセルで、アスペクトは300/150、または2になります。 -nearfar は、レンダリングされるカメラの前のスペースを表します。 -その範囲の前またはその範囲の後はクリップされます(描画されません)。

-

これらの4つの設定は "錐台" を定義します。 -錐台 は、先端が切り取られたピラミッドのような3D形状の名前です。 -つまり、"錐台" という言葉は、球、立方体、角柱、錐台のような別の3D形状と考えて下さい。

-

-

近距離および遠距離の平面の高さは、視野によって決まります。 -両方の平面の幅は、視野とアスペクトによって決まります。

-

定義された錐台内のすべてが描画されます。錐台外は何も描画しません。

-

カメラはデフォルトで、Yを上にして-Z軸を見下ろします。 -立方体を原点に配置するので、カメラを原点から少し後ろに動かし、何かを見えるようにする必要があります。

-
camera.position.z = 2;
-
-

以下が私たちが目指しているものです。

-

-

上の図では、カメラが z = 2 にある事がわかります。 --Z軸を見下ろしています。 -錐台は、カメラの正面から0.1単位で開始し、カメラの正面の5単位に移動します。 -この図では見下ろしているため、視野はアスペクトの影響を受けます。 -canvasは高さの2倍の幅であるため、ビュー全体で視野は垂直方向の視野である指定された75度よりもはるかに広くなります。

-

次は Scene を作成します。 -three.jsの Scene は、シーングラフのフォームのルートです。 -three.jsで描画するものはすべてシーンに追加する必要があります。 -Sceneの仕組みの詳細は、今後の記事で説明します。

-
const scene = new THREE.Scene();
-
-

次はボックスのデータが含まれている BoxGeometry を作成します。 -Three.jsで表示するほとんど全てのものには、3Dオブジェクトを構成する頂点を定義するジオメトリが必要です。

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-

基本的なマテリアルを作成し、色を設定します。 -色は標準のCSSスタイルの6桁の16進数の色値を使用して指定できます。

-
const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
-
-

次に Mesh を作成します。 MeshGeometry (オブジェクトの形状)と Material (オブジェクトの描画方法、光沢または平坦、適用する色、適用するテクステャなど)を組み合わせます。 -シーン内のオブジェクトの位置、方向、スケールと同様です。

-
const cube = new THREE.Mesh(geometry, material);
-
-

最後にメッシュをシーンに追加します。

-
scene.add(cube);
-
-

次にレンダラーの描画関数にシーンとカメラに渡し、シーンをレンダリングします。

-
renderer.render(scene, camera);
-
-

これが実際の例です。

-

- -

-

私たちの視点からは、これを3Dキューブと言うのは少し難しいです。Z軸がマイナス値で奥にあり、1つの面しか見ていません。

-

回転アニメーションさせて、3Dキューブで描画されている事を明らかにします。アニメーションさせるには requestAnimationFrame を使用しループ処理内で描画します。

-

これがループです。

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cube.rotation.x = time;
-  cube.rotation.y = time;
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

requestAnimationFrame は、何かをアニメーションさせたい時に使います。 -これに呼び出される関数を渡します。今回渡す関数は render です。 -関数を呼び出し、表示に関連する何かを更新するとブラウザがページを再描画します。 -私たちの場合、three.jsの renderer.render 関数を呼び出しシーンを描画します。 -requestAnimationFrame は、ページがロードされて渡した関数が呼ばれるまで少し時間がかかります。その時間はミリ秒単位です。 -秒に変換する方が簡単に扱えるため、ここではミリ秒を秒に変換します。

-

次にキューブのXとY回転に現在の時間を設定します。 -回転は ラジアン 単位です。 -円の中に2πのラジアンがあります。キューブは1秒間に約6.28ごと各軸で1回転します。

-

シーンをレンダリングし、別のアニメーションフレームをループし続けます。 -ループの外側で requestAnimationFrame を1回呼び出してループを開始します。

-

- -

-

少し良くなりましたが、まだ3Dには見えません。3Dに見えるようにいくつか光源を追加します。つまり、ライトを追加しましょう。 -three.jsには 今後の記事 で紹介する多くの種類のライトがあります。 -とりあえずディレクショナルライトを作成しましょう。

-
{
-  const color = 0xFFFFFF;
-  const intensity = 3;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(-1, 2, 4);
-  scene.add(light);
-}
-
-

ディレクショナルライトは位置とターゲットを持っています。どちらもデフォルト値は 0, 0, 0 です。 -今回はライトの位置を -1、2、4 に設定しているため、カメラの後ろの少し左上側にあります。 -ターゲットはまだ 0, 0, 0 なので原点に向かって輝きます。

-

また、マテリアルを変更する必要があります。MeshBasicMaterial はライトの影響を受けません。ライトの影響をうける MeshPhongMaterial に変更してみましょう。

-
-const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
-+const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
-
-

そして、ここで動作しています。

-

- -

-

これでかなり3Dに見えるようになりました。

-

楽しんでみるために、さらに2つのキューブを追加しましょう。

-

各キューブに同じジオメトリを使用しますが、キューブごとに異なるカラーが適用できるため、異なるマテリアルを作成します。

-

最初に、指定した色で新しいマテリアルを作成する関数を作ります。 -次に、指定したジオメトリをシーンに追加し、X位置を設定したメッシュを作成します。

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-

次に、異なる色とX位置を指定した Mesh インスタンスを配列に保存する関数を3回呼び出します。

-
const cubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

最後に、描画関数の中でで3つのキューブすべてを回転します。 -それぞれにわずかに異なる回転を計算し適用します。

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  ...
-
-

それがここにあります。

-

- -

-

上記のトップダウン図と比較すると、期待通りである事がわかります。 -X = -2 および X = +2の場合、キューブは部分的に錐台の外側にあります。 -錐台の外側は何だか誇張して歪んでおり、キャンバスの向こう側はとても極端です。

-

この短いイントロが学習を始めるのに役立つ事を願っています。 -次は複数の状況に適応できるようにレスポンシブサイトでのコードもカバーします

-
-

es6モジュール、three.js、およびフォルダー構造

-

バージョンr106以降でthree.jsを使用する好ましい方法は -es6モジュールです。

-

-es6モジュールはスクリプトのロードに import を使う事ができます。 -また、HTMLのインラインに <script type="module"> タグが使えます。 -両方とも以下に例を示します。 -

-
<script type="module">
-import * as THREE from 'three';
-
-...
-
-</script>
-
-

-パスは絶対パス、または相対パスでなければなりません。 -相対パスは常に ./ または ../ から始まり、 -<img><a> など他のタグと異なります。 -

-

-同じスクリプトへの参照は、絶対パスである限り一度だけロードされます。 -three.jsの場合、すべてのexamplesを正しいフォルダ階層に入れる必要があります。 -

-
someFolder
- |
- ├-build
- | |
- | +-three.module.js
- |
- +-examples
-   |
-   +-jsm
-     |
-     +-controls
-     | |
-     | +-OrbitControls.js
-     | +-TrackballControls.js
-     | +-...
-     |
-     +-loaders
-     | |
-     | +-GLTFLoader.js
-     | +-...
-     |
-     ...
-
-

-このフォルダー構造が必要な理由は、 OrbitControls.js のようなexamplesのスクリプトには相対パスがハードコーディングされてるからです。 -

-
import * as THREE from '../../../build/three.module.js';
-
-

-同じフォルダ構造を使用すると、importしたthreeとexampleライブラリは両方とも同じthree.module.jsを参照します。 -

-
import * as THREE from './someFolder/build/three.module.js';
-import {OrbitControls} from './someFolder/addons/controls/OrbitControls.js';
-
-

これにはCDNを使用する場合も含まれます。 three.modules.js のパスが /build/three.modules.js のようになってる事を確認して下さい。例えば

-
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@<version>/build/three.module.js';
-import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/three@<version>/addons/controls/OrbitControls.js';
-
-
- -
-
-
- - - - - - - - diff --git a/manual/ja/game.html b/manual/ja/game.html deleted file mode 100644 index 26ed2f5d00b2da..00000000000000 --- a/manual/ja/game.html +++ /dev/null @@ -1,42 +0,0 @@ - - - Making a Game - - - - - - - - - - - - - -
-
-

Making a Game

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/indexed-textures.html b/manual/ja/indexed-textures.html deleted file mode 100644 index b60f50974fb769..00000000000000 --- a/manual/ja/indexed-textures.html +++ /dev/null @@ -1,593 +0,0 @@ - - - 圧縮テクスチャのピッキングとカラー - - - - - - - - - - - - - -
-
-

圧縮テクスチャのピッキングとカラー

-
-
-
-

この記事はThree.jsでHTML要素を3Dに揃えるの続きです。 -まだ読んでいない人はそちらから読んでみて下さい。

-

Three.jsを使う時には、クリエイティブな解決策を考えなければならない事もあります。 -これが素晴らしい解決策かわかりませんが、共有して何か解決策の提案があるか見てみようと思いました。

-

前回の記事では3Dの地球儀の周りに国名を表示しました。 -ユーザーに国を選択させて、その国の選択内容を表示させるにはどうすれば良いでしょうか?

-

最初に思いつくのは国ごとにジオメトリを生成する事です。 -以前取り上げたピッキングを使った解決策があります。 -国ごとに3Dジオメトリを作ります。 -ユーザーが国のメッシュをクリックすると、どの国がクリックされたのか分かります。

-

この解決策を確認するために前回の記事のアウトライン生成に使った同じデータを使用し、全ての国の3Dメッシュを生成してみました。 -その結果、15.5MBのバイナリGLTF(.glb)ファイルができました。 -15.5MBをダウンロードさせるのは、私にはやりすぎのように思えます。

-

データを圧縮する方法はたくさんあります。 -1つ目はアウトラインの解像度を下げるアルゴリズムを適用する事です。 -その解決策を追求する時間を割いていませんでした。 -アメリカの国境にとっては大勝利でしょうね。 -カナダの国境はおそらくもっと少ないです。

-

別の解決策としては、実際のデータ圧縮だけを使用する方法もあります。 -例えばファイルを圧縮すると11MBになりました。 -30%減ですが、間違いなく物足りないです。

-

全てのデータを32ビットのfloat値ではなく、16ビットの範囲内の値として格納できます。 -もしくはdraco compressionのようなものを使う事もできるし、それだけで充分かもしれません。 -私は確認してないですが、ぜひご自身で確認して結果がどうなったか教えて下さい😅

-

私の場合はピッキングの記事の最後に取り上げたGPUピッキングの解決策について考えてみました。 -この解決策では、メッシュのIDを表すユニークなカラーで全てのメッシュを描画しました。 -全てのメッシュを描画し、クリックしてカラーを確認しました。

-

そこからインスピレーションを得て、国の配列の中でそれぞれの国のカラーがインデックス番号になり、国の地図を事前に生成できました。 -そうすれば、GPUピッキング技術と似たように使う事ができます。 -この圧縮テクスチャ(インデックステクスチャ)を使って地球儀を画面外に描画します。 -ユーザーがクリックしたピクセルのカラーを見ると国のIDが分かります。

-

そこでこのようなテクスチャを生成するコードを書いてみました。

-
- -

注:このテクスチャを生成するために使用されたデータはこのウェブサイトからのものでCC-BY-SAライセンスです。

-

たったの217KBになり、国のメッシュの14MBよりずっと良いです。 -解像度を下げる事もできそうですが、今の所は217KBで充分だと思います。

-

これを使い国をピッキングしてみましょう。

-

GPUピッキング例からコードを取得すると、ピッキングシーンが必要です。

-
const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

そして、ピッキングシーンに圧縮ステクスチャの地球儀の追加が必要です。

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-+  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-+  indexTexture.minFilter = THREE.NearestFilter;
-+  indexTexture.magFilter = THREE.NearestFilter;
-+
-+  const pickingMaterial = new THREE.MeshBasicMaterial({map: indexTexture});
-+  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

前に使った GPUPickingHelper クラスをコピーしましょう。 -少し変更しました。

-
class GPUPickHelper {
-  constructor() {
-    // create a 1x1 pixel render target
-    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-    this.pixelBuffer = new Uint8Array(4);
--    this.pickedObject = null;
--    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera) {
-    const {pickingTexture, pixelBuffer} = this;
-
-    // set the view offset to represent just a single pixel under the mouse
-    const pixelRatio = renderer.getPixelRatio();
-    camera.setViewOffset(
-        renderer.getContext().drawingBufferWidth,   // full width
-        renderer.getContext().drawingBufferHeight,  // full top
-        cssPosition.x * pixelRatio | 0,             // rect x
-        cssPosition.y * pixelRatio | 0,             // rect y
-        1,                                          // rect width
-        1,                                          // rect height
-    );
-    // render the scene
-    renderer.setRenderTarget(pickingTexture);
-    renderer.render(scene, camera);
-    renderer.setRenderTarget(null);
-    // clear the view offset so rendering returns to normal
-    camera.clearViewOffset();
-    //read the pixel
-    renderer.readRenderTargetPixels(
-        pickingTexture,
-        0,   // x
-        0,   // y
-        1,   // width
-        1,   // height
-        pixelBuffer);
-
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2] <<  0);
-+
-+    return id;
--    const id =
--        (pixelBuffer[0] << 16) |
--        (pixelBuffer[1] <<  8) |
--        (pixelBuffer[2]      );
--    const intersectedObject = idToObject[id];
--    if (intersectedObject) {
--      // pick the first object. It's the closest one
--      this.pickedObject = intersectedObject;
--      // save its color
--      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
--      // set its emissive color to flashing red/yellow
--      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
--    }
-  }
-}
-
-

これで国を選択できるようになりました。

-
const pickHelper = new GPUPickHelper();
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // exit if we have not loaded the data yet
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    // we clicked a country. Toggle its 'selected' property
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    // if we're selecting this country and modifiers are not
-    // pressed unselect everything else.
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-  } else if (numCountriesSelected) {
-    // the ocean or sky was clicked
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-}
-
-canvas.addEventListener('pointerup', pickCountry);
-
-

上記のコードでは、国の配列に selected プロパティを設定/解除しています。 -Shiftctrlcmd を押すと複数の国を選択できます。

-

残作業は選択した国を表示させるだけです。 -ラベルを更新してみましょう。

-
function updateLabels() {
-  // exit if we have not loaded the data yet
-  if (!countryInfos) {
-    return;
-  }
-
-  const large = settings.minArea * settings.minArea;
-  // get a matrix that represents a relative orientation of the camera
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // get the camera's position
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
--    const {position, elem, area} = countryInfo;
--    // large enough?
--    if (area < large) {
-+    const {position, elem, area, selected} = countryInfo;
-+    const largeEnough = area >= large;
-+    const show = selected || (numCountriesSelected === 0 && largeEnough);
-+    if (!show) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-    ...
-
-

これで国を選択できるようになります。

-

- -

-

地域に基づいて国を表示しますが、1つをクリックすると1つだけラベルが表示されます。

-

国を選択する合理的な解決策のように思えますが、選択された国を強調表示するにはどうでしょうか?

-

パレットグラフィックス からインスピレーションを得る事ができます。

-

パレットグラフィックスインデックスカラーはAtari 800、Amiga、ファミコン、スーパーファミコン、IBMの古いPCなどの古いシステムで使われていました。 -ビットマップをRGBAカラー8ビット、1ピクセル32バイト以上で格納するのではなく、ビットマップを8ビット以下の値で格納していました。 -各ピクセルの値はパレットへのインデックスです。 -そのため例えば画像内の値が3であれば "color 3を表示する" という事になります。 -color 3が何色かは "パレット" と呼ばれる別の場所で定義されています。

-

JavaScriptでは次のようなコードにできます。

-
const face7x7PixelImageData = [
-  0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 2, 0, 2, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 3, 3, 3, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  0, 1, 1, 1, 1, 1, 1,
-];
-
-const palette = [
-  [255, 255, 255],  // white
-  [  0,   0,   0],  // black
-  [  0, 255, 255],  // cyan
-  [255,   0,   0],  // red
-];
-
-

画像データの各ピクセルがパレットへのインデックスとなります。 -上記のパレットを使い、画像データを解釈すると次のような画像が得られます。

-
- -

この場合、上記のテクスチャは国ごとに異なるIDを持っています。 -そこでパレットのテクスチャを通して同じテクスチャを使い、それぞれの国のカラーを出せば良いのです。 -パレットの質感を変える事でそれぞれの国を彩る事ができます。 -例えばパレットテクスチャ全体を黒に設定し、パレット内のある国のエントリーを別のカラーにするとその国だけを強調表示できます。

-

パレット化されたインデックスグラフィックスを行うにはカスタムシェーダーコードが必要です。 -three.jsでデフォルトのシェーダーを変更してみましょう。 -そうすれば、必要に応じてライティングなどの機能も使えます。

-

アニメーションする多くのオブジェクトを最適化の記事で解説したように、 -マテリアルの onBeforeCompile プロパティに関数を追加するとデフォルトのシェーダーを変更できます。

-

デフォルトのフラグメントシェーダーはコンパイル前は以下のようになっています。

-
#include <common>
-#include <color_pars_fragment>
-#include <uv_pars_fragment>
-#include <map_pars_fragment>
-#include <alphamap_pars_fragment>
-#include <aomap_pars_fragment>
-#include <lightmap_pars_fragment>
-#include <envmap_pars_fragment>
-#include <fog_pars_fragment>
-#include <specularmap_pars_fragment>
-#include <logdepthbuf_pars_fragment>
-#include <clipping_planes_pars_fragment>
-void main() {
-    #include <clipping_planes_fragment>
-    vec4 diffuseColor = vec4( diffuse, opacity );
-    #include <logdepthbuf_fragment>
-    #include <map_fragment>
-    #include <color_fragment>
-    #include <alphamap_fragment>
-    #include <alphatest_fragment>
-    #include <specularmap_fragment>
-    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
-    #ifdef USE_LIGHTMAP
-        reflectedLight.indirectDiffuse += texture2D( lightMap, vLightMapUv ).xyz * lightMapIntensity;
-    #else
-        reflectedLight.indirectDiffuse += vec3( 1.0 );
-    #endif
-    #include <aomap_fragment>
-    reflectedLight.indirectDiffuse *= diffuseColor.rgb;
-    vec3 outgoingLight = reflectedLight.indirectDiffuse;
-    #include <envmap_fragment>
-    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
-    #include <premultiplied_alpha_fragment>
-    #include <tonemapping_fragment>
-    #include <colorspace_fragment>
-    #include <fog_fragment>
-}
-
-

これらのスニペットを全て調べてみるとthree.jsはベースマテリアルのカラーを管理するために diffuseColor という変数が使用されています。 -これは <color_fragment> スニペット に設定されているので修正できるはずです。

-

シェーダーで diffuseColor は既にアウトラインテクスチャのカラーになっているはずなので、パレットテクスチャからカラーを探して最終的な結果にそれらをミックスします。

-

前にやったように検索文字列と置換文字列の配列を作り、Material.onBeforeCompile でシェーダーに適用します。

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-  indexTexture.minFilter = THREE.NearestFilter;
-  indexTexture.magFilter = THREE.NearestFilter;
-
-  const pickingMaterial = new THREE.MeshBasicMaterial({map: indexTexture});
-  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-+  const fragmentShaderReplacements = [
-+    {
-+      from: '#include <common>',
-+      to: `
-+        #include <common>
-+        uniform sampler2D indexTexture;
-+        uniform sampler2D paletteTexture;
-+        uniform float paletteTextureWidth;
-+      `,
-+    },
-+    {
-+      from: '#include <color_fragment>',
-+      to: `
-+        #include <color_fragment>
-+        {
-+          vec4 indexColor = texture2D(indexTexture, vUv);
-+          float index = indexColor.r * 255.0 + indexColor.g * 255.0 * 256.0;
-+          vec2 paletteUV = vec2((index + 0.5) / paletteTextureWidth, 0.5);
-+          vec4 paletteColor = texture2D(paletteTexture, paletteUV);
-+          // diffuseColor.rgb += paletteColor.rgb;   // white outlines
-+          diffuseColor.rgb = paletteColor.rgb - diffuseColor.rgb;  // black outlines
-+        }
-+      `,
-+    },
-+  ];
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-+  material.onBeforeCompile = function(shader) {
-+    fragmentShaderReplacements.forEach((rep) => {
-+      shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-+    });
-+  };
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

上記のように indexTexturepaletteTexturepaletteTextureWidth の3つのユニフォームを追加します。 -indexTexture からカラーを取得してインデックスに変換します。 -vUv はthree.jsで提供されているテクスチャ座標です。 -そのインデックスを使い、パレットテクスチャからカラーを取り出します。 -その結果を現在の diffuseColor とミックスします。 -diffuseColor は黒と白のアウトラインテクスチャなので、2色を加えると白のアウトラインになります。 -現在の拡散色(ディフューズカラー)を引くと黒いアウトラインになります。

-

レンダリング前にパレットテクスチャと3つのユニフォームを設定する必要があります。

-

パレットテクスチャは、国ごとに1色 + 海のための1色を保持するのに十分な幅が必要です(id = 0)。 -240の国があります。 -国のリストがロードされるまで待ち、正確な数字を得るか、それを調べる事ができます。 -少し大きめの数字を選んでも、あまり害はないので512を選びましょう。

-

パレットテクスチャを作成するコードは以下の通りです。

-
const maxNumCountries = 512;
-const paletteTextureWidth = maxNumCountries;
-const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 4);
-const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight);
-paletteTexture.minFilter = THREE.NearestFilter;
-paletteTexture.magFilter = THREE.NearestFilter;
-
-

DataTexture はテクスチャの生データを与える事ができます。 -今回はは512のRGBAカラーを4バイトずつ与え、それぞれのバイトが赤、緑、青で0〜255の値を使用します。

-

ランダムなカラーで塗りつぶしましょう!

-
for (let i = 1; i < palette.length; ++i) {
-  palette[i] = Math.random() * 256;
-}
-// set the ocean color (index #0)
-palette.set([100, 200, 255, 255], 0);
-paletteTexture.needsUpdate = true;
-
-

パレットテクスチャを palette 配列の内容で更新したい時は、常に paletteTexture.needsUpdatetrue にする必要があります。

-

これはマテリアルのユニフォームに設定する必要があります。

-
const geometry = new THREE.SphereGeometry(1, 64, 32);
-const material = new THREE.MeshBasicMaterial({map: texture});
-material.onBeforeCompile = function(shader) {
-  fragmentShaderReplacements.forEach((rep) => {
-    shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-  });
-+  shader.uniforms.paletteTexture = {value: paletteTexture};
-+  shader.uniforms.indexTexture = {value: indexTexture};
-+  shader.uniforms.paletteTextureWidth = {value: paletteTextureWidth};
-};
-scene.add(new THREE.Mesh(geometry, material));
-
-

ランダムなカラーがついた国を手に入れる事ができました。

-

- -

-

インデックスとパレットテクスチャの動作が確認できたので、パレットを操作してハイライトにしてみましょう。

-

まず、three.jsスタイルカラーを渡してパレットのテクスチャに入れる値を与える関数を作ってみましょう。

-
const tempColor = new THREE.Color();
-function get255BasedColor(color) {
-  tempColor.set(color);
-  const base = tempColor.toArray().map(v => v * 255);
-  base.push(255); // alpha
-  return base;
-}
-
-

このように color = get255BasedColor('red') を呼び出すと [255, 0, 0] のような配列が返されます。

-

次はそれを使って、いくつかのカラーを作ってパレットを埋めていきましょう。

-
const selectedColor = get255BasedColor('red');
-const unselectedColor = get255BasedColor('#444');
-const oceanColor = get255BasedColor('rgb(100,200,255)');
-resetPalette();
-
-function setPaletteColor(index, color) {
-  palette.set(color, index * 4);
-}
-
-function resetPalette() {
-  // make all colors the unselected color
-  for (let i = 1; i < maxNumCountries; ++i) {
-    setPaletteColor(i, unselectedColor);
-  }
-
-  // set the ocean color (index #0)
-  setPaletteColor(0, oceanColor);
-  paletteTexture.needsUpdate = true;
-}
-
-

これらの関数を使い、国が選択された時にパレットを更新してみましょう。

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // exit if we have not loaded the data yet
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-+    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-+    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-+  resetPalette();
-}
-
-

1つ以上の国を強調する事ができるようにする必要があります。

-

- -

-

これで動作しました!

-

ちょっとした事ですが、選択状態を変えないと地球儀を回せないです。 -国を選択してから地球儀を回転させると選択範囲が変わります。

-

修正してみましょう。 -思いつく限りでは2つの事が確認できます。 -クリックしてから手放すまでにどれだけの時間が経過したか。 -もう1つはユーザーが実際にマウスを動かしたかどうかです。 -時間が短かったり、マウスを動かさなかった場合はクリックだったのではないでしょうか。 -そうでなければ、地球を引っ張っていこうとしていたのでしょう。

-
+const maxClickTimeMs = 200;
-+const maxMoveDeltaSq = 5 * 5;
-+const startPosition = {};
-+let startTimeMs;
-+
-+function recordStartTimeAndPosition(event) {
-+  startTimeMs = performance.now();
-+  const pos = getCanvasRelativePosition(event);
-+  startPosition.x = pos.x;
-+  startPosition.y = pos.y;
-+}
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // exit if we have not loaded the data yet
-  if (!countryInfos) {
-    return;
-  }
-
-+  // if it's been a moment since the user started
-+  // then assume it was a drag action, not a select action
-+  const clickTimeMs = performance.now() - startTimeMs;
-+  if (clickTimeMs > maxClickTimeMs) {
-+    return;
-+  }
-+
-+  // if they moved assume it was a drag action
-+  const position = getCanvasRelativePosition(event);
-+  const moveDeltaSq = (startPosition.x - position.x) ** 2 +
-+                      (startPosition.y - position.y) ** 2;
-+  if (moveDeltaSq > maxMoveDeltaSq) {
-+    return;
-+  }
-
--  const position = {x: event.clientX, y: event.clientY};
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-  resetPalette();
-}
-
-+canvas.addEventListener('pointerdown', recordStartTimeAndPosition);
-canvas.addEventListener('pointerup', pickCountry);
-
-

これらの変更を加えると私にはそれが機能しているように見えます

-

- -

-

私はUXの専門家ではないので、もっと良い解決策があれば教えて下さい。

-

インデックスグラフィックスがどのように役立つのか、また、three.jsが作るシェーダーを変更してシンプルな機能を追加する方法が少しでも理解してもらえたと思います。 -シェーダーが書かれている言語のGLSLの使い方は、この記事で扱うには内容が大きすぎます。 -ポストプロセスの記事にGLSLのリンクがあるので確認してみて下さい。

- -
-
-
- - - - - - - - diff --git a/manual/ja/lights.html b/manual/ja/lights.html deleted file mode 100644 index e5d9f9a2219ffc..00000000000000 --- a/manual/ja/lights.html +++ /dev/null @@ -1,445 +0,0 @@ - - - のライト - - - - - - - - - - - - - -
-
-

のライト

-
-
-
-

この記事はThree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでいない場合は、Three.jsの基礎知識やセットアップから始めると良いと思います。 -前回の記事はテクスチャでした。

-

今回はthree.jsの色々な種類のライトの使い方を確認していきます。

-

前回のサンプルコードからカメラの設定を修正しましょう。 -視野角(fov)を45度にし、遠平面(far)を100、カメラを原点からY座標に10、Z座標を20にします。

-
*const fov = 45;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-*const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-+camera.position.set(0, 10, 20);
-
-

次に OrbitControls を追加します。 -OrbitControls は、カメラをある点を中心に軌道を回転できます。 -OrbitControls はthree.jsのオプション機能なので、importする必要があります。

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-

これでOrbitControlsを利用できます。 -OrbitControls にカメラと入力イベントを取得するDOM要素を渡します。

-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 5, 0);
-controls.update();
-
-

controls.targetのY座標を5にして controls.update を呼び出します。

-

次はライトアップするオブジェクトを作ってみましょう。 -まずは地上となる平面を作ります。 -この平面に2 x 2ピクセルの小さなチェッカーボードのテクスチャを適用します。

-
- -
- -

最初にテクスチャを読み込み、何回テクスチャのリピートを繰り返すかを設定し、フィルターはニアレスト(nearest)にします。 -テクスチャは2 x 2ピクセルのチェッカーボードです。 -テクスチャのリピートは平面の半分の大きさにし、チェッカーボードの1つのチェック部分は1にします。

-
const planeSize = 40;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
-texture.colorSpace = THREE.SRGBColorSpace;
-const repeats = planeSize / 2;
-texture.repeat.set(repeats, repeats);
-
-

平面のジオメトリとマテリアルを作り、それを元にシーンに追加するメッシュを作ります。 -平面のデフォルトは縦向きなので横向きになるように回転します。

-
const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planeMat = new THREE.MeshPhongMaterial({
-  map: texture,
-  side: THREE.DoubleSide,
-});
-const mesh = new THREE.Mesh(planeGeo, planeMat);
-mesh.rotation.x = Math.PI * -.5;
-scene.add(mesh);
-
-

キューブと球体を追加し、平面を含めて3つのオブジェクトをライティングします。

-
{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-  const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

ライトアップするシーンができたのでライトを追加しましょう!

-

AmbientLight(環境光源)

-

最初に AmbientLight を作りましょう。

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.AmbientLight(color, intensity);
-scene.add(light);
-
-

ライトのパラメーターを調整できるようにします。 -今回もlil-guiを使います。 -lil-guiで色を調整するにはヘルパーが必要です。 -プロパティをlil-guiにCSSの16進数の形で表示します(例: #FF8844)。 -ヘルパーは名前付きプロパティから色を取得し、16進数の文字列に変換してlil-guiに渡します。lil-guiがヘルパーのプロパティを設定し、結果をライトの色に戻します。

-

これがヘルパーです。

-
class ColorGUIHelper {
-  constructor(object, prop) {
-    this.object = object;
-    this.prop = prop;
-  }
-  get value() {
-    return '#' + this.object[this.prop].getHexString();
-  }
-  set value(hexString) {
-    this.object[this.prop].set(hexString);
-  }
-}
-
-

lil-guiの設定は以下の通りです。

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

これで以下のような結果になります。

-

- -

-

シーンをクリックしてドラッグして、カメラを軌道に乗せます。

-

環境光源だけでは正しくライティング表現できてません。キューブと球体に陰影がなく形状が平面に見えます。 -以下のように AmbientLight はマテリアルの色とライトの色、ライトの強度(intensity)を掛けてます。

-
color = materialColor * light.color * light.intensity;
-

それだけで方向性がないです。 -この環境光源は100%均一でシーン内の全ての色を変える以外はライティングとしてはあまり役に立ちません。 -環境光源は暗すぎない暗さを作る事ができます。

-

HemisphereLight(半球光源)

-

コードを HemisphereLight に切り替えてみましょう。 -HemisphereLight は空と地面の色を取得し、その2色とマテリアルの色を掛け合わせます。

-

これが新しいコードです。

-
-const color = 0xFFFFFF;
-+const skyColor = 0xB1E1FF;  // light blue
-+const groundColor = 0xB97A20;  // brownish orange
-const intensity = 1;
--const light = new THREE.AmbientLight(color, intensity);
-+const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
-scene.add(light);
-
-

lil-guiのコードを修正し、両方の色を編集してみましょう。

-
const gui = new GUI();
--gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-+gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('skyColor');
-+gui.addColor(new ColorGUIHelper(light, 'groundColor'), 'value').name('groundColor');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

これが結果です。

-

- -

-

まだ正しくライティング表現ができてなく、キューブと球体が平面に見えます。 -別のライトと組み合わせて使用される HemisphereLight は、空や地面の色に良い影響を与えます。 -この方法では他のライトと組み合わせて使うか、HemisphereLight を代わりに使うのがベストです。

-

DirectionalLight(平行光源)

-

コードを DirectionalLight に切り替えてみましょう。 -DirectionalLight は太陽を表すのによく使われます。

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.DirectionalLight(color, intensity);
-light.position.set(0, 10, 0);
-light.target.position.set(-5, 0, 0);
-scene.add(light);
-scene.add(light.target);
-
-

シーンに lightlight.target を追加する必要があります。 -three.jsの DirectionalLight はターゲットの方向にライティングします。

-

GUIに追加してlight.targetを動かせるようにしてみましょう。

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-gui.add(light.target.position, 'x', -10, 10);
-gui.add(light.target.position, 'z', -10, 10);
-gui.add(light.target.position, 'y', 0, 10);
-
-

- -

-

なんだか見づらいですね。 -Three.jsにはシーンに追加できるヘルパーオブジェクトがたくさんあり、シーンの見えない部分を視覚化するのに役立ちます。 -今回は DirectionalLightHelper を使い、ライトから平面までの線を描画します。 -lightをDirectionalLightHelperに渡してシーンに追加します。

-
const helper = new THREE.DirectionalLightHelper(light);
-scene.add(helper);
-
-

ライトの位置とターゲットの両方を設定できるようにしておきましょう。 -Vector3 が与えられた時に lil-gui を使い x, y, z プロパティを調整できる関数を作ります。

-
function makeXYZGUI(gui, vector3, name, onChangeFn) {
-  const folder = gui.addFolder(name);
-  folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
-  folder.add(vector3, 'y', 0, 10).onChange(onChangeFn);
-  folder.add(vector3, 'z', -10, 10).onChange(onChangeFn);
-  folder.open();
-}
-
-

変更時は常にヘルパーの update 関数を呼び出す必要があります。 -そのため、lil-guiが値を更新時に onChangeFn 関数を渡しています。

-

makeXYZGUI関数はlight.positionとlight.target.positionの両方に使えます。

-
+function updateLight() {
-+  light.target.updateMatrixWorld();
-+  helper.update();
-+}
-+updateLight();
-
-const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-+makeXYZGUI(gui, light.position, 'position', updateLight);
-+makeXYZGUI(gui, light.target.position, 'target', updateLight);
-
-

これでライトを動かす事ができるようになりました。

-

- -

-

カメラを軌道に乗せると見やすくなります。 -この平面は DirectionalLight を表しており、DirectionalLightが一方向からのライティングを計算します。 -光の出所はではなく、平面を無限に照らす平行光線です。

-

PointLight(点光源)

-

PointLight はある点から全方向に光を放つライトです。 -コード変更しましょう。

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.PointLight(color, intensity);
-light.position.set(0, 10, 0);
--light.target.position.set(-5, 0, 0);
-scene.add(light);
--scene.add(light.target);
-
-

PointLightHelper に切り替えます。

-
-const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.PointLightHelper(light);
-scene.add(helper);
-
-

light.targetがないので onChange 関数はもっとシンプルになります。

-
function updateLight() {
--  light.target.updateMatrixWorld();
-  helper.update();
-}
--updateLight();
-
-

PointLightHelper には点がない事に注意して下さい。 -小さなダイヤモンドのワイヤーフレームを描画します。 -簡単に望む任意の形状にできて、ライト自体にメッシュを追加します。

-

PointLightdistanceプロパティを持ちます。 -distance が0ならば PointLight は無限大に輝きます。 -distance が0よりも大きい場合、ライトに向かってライトの全強度を照らし、ライトから離れた distance では影響を受けないようにフェードアウトします。

-

distanceを調整できるようにGUIを設定してみましょう。

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 250, 1);
-+gui.add(light, 'distance', 0, 40).onChange(updateLight);
-
-makeXYZGUI(gui, light.position, 'position', updateLight);
--makeXYZGUI(gui, light.target.position, 'target', updateLight);
-
-

これを試してみて下さい。

-

- -

-

distance が > 0 の時にライトがフェードアウトしている事に注目して下さい。

-

SpotLight(集中光線)

-

集中光源は円錐体にライティングする時に効果的です。 -実際は2つの円錐体があります。外側と内側の円錐体です。 -内側と外側の円錐体の間では、ライトは強度のMAX値から0にフェードします。

-

SpotLight を使うには、平行光源と同じようにターゲットが必要です。 -ライトの円錐体がターゲットに向かって照らされます。

-

上記のヘルパーを使って DirectionalLight を修正します。

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.SpotLight(color, intensity);
-scene.add(light);
-scene.add(light.target);
-
--const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.SpotLightHelper(light);
-scene.add(helper);
-
-

集中光源の円錐体の角度は angleプロパティでラジアン単位で設定します。 -テクスチャ記事DegRadHelper を使い、度数でUIに表示します。

-
gui.add(new DegRadHelper(light, 'angle'), 'value', 0, 90).name('angle').onChange(updateLight);
-
-

内側の円錐はpenumbraプロパティを外側の円錐からの%として設定します。 -penumbra が1の時、ライトは円錐の中心から外側の円錐に向かってフェードしていきます。 -penumbra が5の時、ライトは外側の円錐体の中心から50%からフェードしていきます。

-
gui.add(light, 'penumbra', 0, 1, 0.01);
-
-

- -

-

デフォルトの penumbra が0の場合、集中光源は非常にシャープなエッジを持っていますが、1 に向けて penumbra を調整するとエッジがぼやけます。

-

集中光源の円錐体が見えにくいかもしれません。 -その理由は地面にあります。 -距離を5くらいまで縮めると、円錐体の端が開いているのが見えてきます。

-

RectAreaLight(矩形光源)

-

もう1種類のライトに RectAreaLight があります。 -これはまさにその名の通り、長い蛍光灯のような長方形のエリアのライトや天井にある曇り空のライトです。

-

RectAreaLightMeshStandardMaterialMeshPhysicalMaterial でしか動作しないので、全てのマテリアルを MeshStandardMaterial に変更しましょう。

-
  ...
-
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
--  const planeMat = new THREE.MeshPhongMaterial({
-+  const planeMat = new THREE.MeshStandardMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  mesh.rotation.x = Math.PI * -.5;
-  scene.add(mesh);
-}
-{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-- const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-+ const cubeMat = new THREE.MeshStandardMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
--  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-+ const sphereMat = new THREE.MeshStandardMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

RectAreaLight を使用するには、three.jsから追加のimportが必要です。 -ライトを可視化するために RectAreaLightHelper をimportします。

-
import * as THREE from 'three';
-+import {RectAreaLightUniformsLib} from 'three/addons/lights/RectAreaLightUniformsLib.js';
-+import {RectAreaLightHelper} from 'three/addons/helpers/RectAreaLightHelper.js';
-
-

RectAreaLightUniformsLib.init を呼び出します。

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  RectAreaLightUniformsLib.init();
-
-

RectAreaLightUniformsLibを忘れてもライトは動作しますが、見た目がおかしくなるので忘れないようにして下さい。

-

これでライトを作れました。

-
const color = 0xFFFFFF;
-*const intensity = 5;
-+const width = 12;
-+const height = 4;
-*const light = new THREE.RectAreaLight(color, intensity, width, height);
-light.position.set(0, 10, 0);
-+light.rotation.x = THREE.MathUtils.degToRad(-90);
-scene.add(light);
-
-*const helper = new RectAreaLightHelper(light);
-*light.add(helper);
-
-

注意すべき点は DirectionalLightSpotLight と異なり、RectAreaLight はターゲットを使いません。 -その回転を利用しているだけです。 -もう1つ気をつける事は、ヘルパーがライトの子である必要があります。 -他のヘルパーのようにシーンの子ではありません。

-

GUIも調整してみましょう。 -ライトを回転させて widthheight を調整できるようにします。

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 10, 0.01);
-gui.add(light, 'width', 0, 20);
-gui.add(light, 'height', 0, 20);
-gui.add(new DegRadHelper(light.rotation, 'x'), 'value', -180, 180).name('x rotation');
-gui.add(new DegRadHelper(light.rotation, 'y'), 'value', -180, 180).name('y rotation');
-gui.add(new DegRadHelper(light.rotation, 'z'), 'value', -180, 180).name('z rotation');
-
-makeXYZGUI(gui, light.position, 'position');
-
-

そして、これが結果です。

-

- -

- -

シーンにライトを追加するたびに、Three.jsのレンダリング速度が遅くなる事に注意して下さい。

-

次はカメラの扱い方についてです。

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/load-gltf.html b/manual/ja/load-gltf.html deleted file mode 100644 index 7dd15962a0d1ac..00000000000000 --- a/manual/ja/load-gltf.html +++ /dev/null @@ -1,642 +0,0 @@ - - - でGLFTファイルを読み込む - - - - - - - - - - - - - -
-
-

でGLFTファイルを読み込む

-
-
-
-

前回のレッスンはOBJファイルの読み込みでした。 -まだ読んでいない方は、まずそちらをチェックしてみて下さい。

-

前回の記事で指摘したように、OBJファイルフォーマットは非常に古くかなり単純です。 -OBJから読み込まれたデータはシーングラフを提供しないため、全て1つの大きなメッシュになります。 -OBJは3Dエディタ間でデータを渡す単純な方法として設計されました。

-

gLTFフォーマットはグラフィックを表示するために設計されたフォーマットです。 -3Dフォーマットは基本的に3~4種類に分けられます。

-
    -
  • 3Dエディタのフォーマット

    -

    これは1つのアプリ固有フォーマットです。.blend (Blender)、.max (3d Studio Max)、.mb、.ma (Maya) など。

    -
  • -
  • 交換フォーマット

    -

    これはOBJ、DAE(Collada)、FBXのようなフォーマットです。 -3Dエディタ間の情報交換をサポートするように設計されています。 -このフォーマットは通常は3Dエディタの内部でのみ使用される追加情報を持ち、必要以上に大きくなります。

    -
  • -
  • アプリのフォーマット

    -

    特定のアプリ、通常はゲームに特化したフォーマットです。

    -
  • -
  • 伝送フォーマット

    -

    gLTFは初めての伝送フォーマットかもしれません。 -VRMLも伝送フォーマットかもしれませんが、VRMLはかなり貧弱なフォーマットでした。

    -

    gLTFは他の全てのフォーマットではできない、以下の事ができるように設計されています。

    -
      -
    1. 伝送を小さくする

      -

      頂点のような大きなデータの多くがバイナリで保存されています。 -gLTFファイルのダウンロード時、ゼロ処理でGPUにアップロードできます。 -その機能は用意されています。 -VRML、OBJ、またはDAEファイルのように頂点がテキストで保存され、解析が必要である事とは対照的です。テキストの頂点位置はバイナリよりも3倍から5倍の大きさです。

      -
    2. -
    3. レンダリングの準備ができている

      -

      これもおそらく他のフォーマット(アプリのフォーマット以外)とは違います。 -glTFファイル内のデータはレンダリングされる事が目的で、編集される事は目的としていません。 -レンダリングに重要でないデータは削除されています。 -ポリゴンが三角形に変換されています。 -マテリアルにはどこでも動くようにサポートされた値を持っています。

      -
    4. -
    -
  • -
-

最低限の手間でglTFファイルをダウンロードし表示できるように、特別に設計されています。 -他のどのフォーマットもこれができなかったので、この設計は良い結果になると信じましょう。

-

私は何を見せれば良いのか迷っていました。 -ある程度のレベルではgLTFファイルの読み込みと表示は、OBJファイルよりも簡単です。 -OBJとは異なり、gLTFではマテリアルはフォーマットの直接的な部分です。 -少なくともglTFファイルを読み込む例を見せるべきで、私が遭遇した問題をレビューすると皆さんが良い情報を得られるかもしれないと思いました。

-

ネットで検索したらantonmoekさんの低ポリゴンのシティモデルを見つけました。 -運が良ければ良い例になるように思えました。

-
- -

OBJファイルの読み込みのコード例から始めて、OBJを読み込むコードを削除し、GLTFを読み込むコードに置き換えました。

-

以前のOBJコードは

-
const mtlLoader = new MTLLoader();
-mtlLoader.loadMtl('resources/models/windmill/windmill-fixed.mtl', (mtl) => {
-  mtl.preload();
-  mtl.materials.Material.side = THREE.DoubleSide;
-  objLoader.setMaterials(mtl);
-  objLoader.load('resources/models/windmill/windmill.obj', (event) => {
-    const root = event.detail.loaderRootNode;
-    scene.add(root);
-    ...
-  });
-});
-
-

新しいGLTFのコードは

-
{
-  const gltfLoader = new GLTFLoader();
-  const url = 'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf';
-  gltfLoader.load(url, (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-    ...
-  });
-
-

自動フレーミングのコードは以前のままです。

-

また OBJLoader を取り除き GLTFLoader を含める必要があります。

-
-import {LoaderSupport} from 'three/addons/loaders/LoaderSupport.js';
--import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
--import {MTLLoader} from 'three/addons/loaders/MTLLoader.js';
-+import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
-
-

実行すると以下になりました。

-

- -

-

魔法だ!テクスチャーも含めて上手くいっています。

-

次に走り回る車をアニメーションしたかったので、シーンに車が別のエンティティとして設定されているか、それが使用できるように設定されているか確認する必要があります。

-

JavaScriptコンソールにシーングラフをダンプするコードを書いてみました。

-

シーングラフを表示するコードです。

-
function dumpObject(obj, lines = [], isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

そして、シーンを読み込み直後に呼び出します。

-
const gltfLoader = new GLTFLoader();
-gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-  const root = gltf.scene;
-  scene.add(root);
-  console.log(dumpObject(root).join('\n'));
-
-

実行すると このようなリストが得られました。

-
OSG_Scene [Scene]
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    └─RootNode_(model_correction_matrix) [Object3D]
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        └─RootNode [Object3D]
-          │ ...
-          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-          │ ├─CAR_03_2 [Object3D]
-          │ │ └─CAR_03_2_World_ap_0 [Mesh]
-          │ ├─Car_04_1 [Object3D]
-          │ │ └─Car_04_1_World_ap_0 [Mesh]
-          │ ├─Car_04_2 [Object3D]
-          │ │ └─Car_04_2_World_ap_0 [Mesh]
-          │ ├─Car_04_3 [Object3D]
-          │ │ └─Car_04_3_World_ap_0 [Mesh]
-          │ ├─Car_04_4 [Object3D]
-          │ │ └─Car_04_4_World_ap_0 [Mesh]
-          │ ├─Car_08_4 [Object3D]
-          │ │ └─Car_08_4_World_ap8_0 [Mesh]
-          │ ├─Car_08_3 [Object3D]
-          │ │ └─Car_08_3_World_ap9_0 [Mesh]
-          │ ├─Car_04_1_2 [Object3D]
-          │ │ └─Car_04_1_2_World_ap_0 [Mesh]
-          │ ├─Car_08_2 [Object3D]
-          │ │ └─Car_08_2_World_ap11_0 [Mesh]
-          │ ├─CAR_03_1_2 [Object3D]
-          │ │ └─CAR_03_1_2_World_ap_0 [Mesh]
-          │ ├─CAR_03_2_2 [Object3D]
-          │ │ └─CAR_03_2_2_World_ap_0 [Mesh]
-          │ ├─Car_04_2_2 [Object3D]
-          │ │ └─Car_04_2_2_World_ap_0 [Mesh]
-          ...
-
-

この結果から全ての車が "Cars" という名前の親の下にある事がわかります。

-
*          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-
-

そこで簡単なテストとして、"Cars"ノードの全ての子をY軸の周りに回転させようと思いました。

-

シーンを読み込み後に"Cars"ノードを調べて結果を保存しました。

-
+let cars;
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-+    cars = root.getObjectByName('Cars');
-
-

render 関数で cars の全ての子の回転を設定します。

-
+function render(time) {
-+  time *= 0.001;  // convert to seconds
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (cars) {
-+    for (const car of cars.children) {
-+      car.rotation.y = time;
-+    }
-+  }
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

これが結果です。

-

- -

-

うーん、残念ながら子のオリジンが回転目的のために設定されておらず、アニメーション用に設計されてないようです。トラックの回転方向が間違っています。

-

3Dで何かする場合の重要なポイントは、事前に計画を立ててアセットを設計する必要があります。アセットを正しい場所に配置し、正しいスケールになるようにデザインします。

-

私は3DCGアーティストではなくBlenderもよく知らないので、ハックしてみます。 -それぞれの車で別の Object3D を親にします。 -次に Object3D オブジェクトを移動させて車を移動させます。 -個々に車のオリジンに Object3D を設定して向きを変えられるので、必要な位置に設定する事ができます。

-

シーングラフのリストを見返すと "Car_08", "CAR_03", "Car_04" の3種類しかないようです。上手くいけば3種類の調整で済みます。

-

コードを以下のように変更しました。 -それぞれの車でインスタンス作成した Object3D を親にし、その Object3D をシーンに追加します。 -車種ごとの設定で向きを固定し、車の親の Object3Dcars 配列を追加します。

-
-let cars;
-+const cars = [];
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
--    cars = root.getObjectByName('Cars');
-+    const loadedCars = root.getObjectByName('Cars');
-+    const fixes = [
-+      { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
-+      { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
-+      { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+    ];
-+
-+    root.updateMatrixWorld();
-+    for (const car of loadedCars.children.slice()) {
-+      const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-+      const obj = new THREE.Object3D();
-+      car.getWorldPosition(obj.position);
-+      car.position.set(0, 0, 0);
-+      car.rotation.set(...fix.rot);
-+      obj.add(car);
-+      scene.add(obj);
-+      cars.push(obj);
-+    }
-     ...
-
-

これで車の向きを修正しました。

-

- -

-

さあ、追い回してみましょう。

-

簡単なドライビングシステムを作るのはこの記事では無理がありますが、 -その代わりに入り組んだパスを1本にし、そのパスに車を乗せる事ができそうです。 -以下の画像はBlenderでパスを作っている途中です。

-
- -

Blenderからパスのデータを取り出す方法が必要でした。 -幸運な事にパスだけを選択し、"write nurbs"をチェックしてobjをエクスポートできました。

-
- -

OBJファイルを開くと頂点のリストを得る事ができました。

-
const controlPoints = [
-  [1.118281, 5.115846, -3.681386],
-  [3.948875, 5.115846, -3.641834],
-  [3.960072, 5.115846, -0.240352],
-  [3.985447, 5.115846, 4.585005],
-  [-3.793631, 5.115846, 4.585006],
-  [-3.826839, 5.115846, -14.736200],
-  [-14.542292, 5.115846, -14.765865],
-  [-14.520929, 5.115846, -3.627002],
-  [-5.452815, 5.115846, -3.634418],
-  [-5.467251, 5.115846, 4.549161],
-  [-13.266233, 5.115846, 4.567083],
-  [-13.250067, 5.115846, -13.499271],
-  [4.081842, 5.115846, -13.435463],
-  [4.125436, 5.115846, -5.334928],
-  [-14.521364, 5.115846, -5.239871],
-  [-14.510466, 5.115846, 5.486727],
-  [5.745666, 5.115846, 5.510492],
-  [5.787942, 5.115846, -14.728308],
-  [-5.423720, 5.115846, -14.761919],
-  [-5.373599, 5.115846, -3.704133],
-  [1.004861, 5.115846, -3.641834],
-];
-
-

THREE.jsにはいくつかの曲線クラスがあります。 -CatmullRomCurve3 が使えそうな気がしたので CatmullRomCurve3 を使ってみた。 -この曲線は頂点を通る滑らかな曲線を作ります。

-

実際にはこれらの頂点を直接入力すると次のような曲線が生成されます。

-
- -

しかし、もっと角をシャープにして欲しいです。 -いくつかの頂点を追加し計算すれば、望んだ角度が得られる気がします。 -各頂点のペアで2つのポイントの間の10%と90%の道を計算し、その結果を CatmullRomCurve3 に渡します。

-

このような曲線が得られます。

-
- -

曲線を作成するコードは以下の通りです。

-
let curve;
-let curveObject;
-{
-  const controlPoints = [
-    [1.118281, 5.115846, -3.681386],
-    [3.948875, 5.115846, -3.641834],
-    [3.960072, 5.115846, -0.240352],
-    [3.985447, 5.115846, 4.585005],
-    [-3.793631, 5.115846, 4.585006],
-    [-3.826839, 5.115846, -14.736200],
-    [-14.542292, 5.115846, -14.765865],
-    [-14.520929, 5.115846, -3.627002],
-    [-5.452815, 5.115846, -3.634418],
-    [-5.467251, 5.115846, 4.549161],
-    [-13.266233, 5.115846, 4.567083],
-    [-13.250067, 5.115846, -13.499271],
-    [4.081842, 5.115846, -13.435463],
-    [4.125436, 5.115846, -5.334928],
-    [-14.521364, 5.115846, -5.239871],
-    [-14.510466, 5.115846, 5.486727],
-    [5.745666, 5.115846, 5.510492],
-    [5.787942, 5.115846, -14.728308],
-    [-5.423720, 5.115846, -14.761919],
-    [-5.373599, 5.115846, -3.704133],
-    [1.004861, 5.115846, -3.641834],
-  ];
-  const p0 = new THREE.Vector3();
-  const p1 = new THREE.Vector3();
-  curve = new THREE.CatmullRomCurve3(
-    controlPoints.map((p, ndx) => {
-      p0.set(...p);
-      p1.set(...controlPoints[(ndx + 1) % controlPoints.length]);
-      return [
-        (new THREE.Vector3()).copy(p0),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.1),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.9),
-      ];
-    }).flat(),
-    true,
-  );
-  {
-    const points = curve.getPoints(250);
-    const geometry = new THREE.BufferGeometry().setFromPoints(points);
-    const material = new THREE.LineBasicMaterial({color: 0xff0000});
-    curveObject = new THREE.Line(geometry, material);
-    scene.add(curveObject);
-  }
-}
-
-

このコードの最初の部分は曲線を作ります。 -コードの2番目の部分は曲線から250頂点を生成し、その250頂点を結んで作られた線を表示するオブジェクトを作成します。

-

このサンプルを実行してもカーブが見えませんでした。 -見えるようにするために、深度テストを無視して最後にレンダリングするようにしました。

-
    curveObject = new THREE.Line(geometry, material);
-+    material.depthTest = false;
-+    curveObject.renderOrder = 1;
-
-

そして、カーブがあまりにも小さすぎる事に気がつきました。

-
- -

Blenderで階層を確認してみると、3DCGアーティストが全ての親となるノードをスケーリングしていました。

-
- -

リアルタイムの3Dアプリではスケーリングが悪です。 -リアルタイム3Dを行う際には、様々な問題が発生し不満が尽きません。 -3Dアプリ開発ではシーン全体を拡大縮小するのはとても簡単ですが、3DCGアーティストはこれを知らない事が多いです。 -もしあなたがリアルタイムの3Dアプリを作ろうと決めたら、3DCGアーティストには絶対に何もスケールしないようにお願いする事をお勧めします。 -スケールを変更する場合は、そのスケールを頂点に適用する方法を見つける必要があります。

-

スケールだけでなく、その親である Cars ノードによって回転されオフセットされます。 -これでは実行時にワールド座標での車の移動が困難になります。 -はっきり言うと、この場合はワールド座標で車を走らせたいのでこの問題が出てきます。 -月が地球を中心に回転しているようなローカル座標で操作される場合、これはあまり問題ではありません。

-

上記で書いたシーングラフをダンプする関数に戻り、各ノードの位置、回転、スケールをダンプしてみましょう。

-
+function dumpVec3(v3, precision = 3) {
-+  return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
-+}
-
-function dumpObject(obj, lines, isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-+  const dataPrefix = obj.children.length
-+     ? (isLast ? '  │ ' : '│ │ ')
-+     : (isLast ? '    ' : '│   ');
-+  lines.push(`${prefix}${dataPrefix}  pos: ${dumpVec3(obj.position)}`);
-+  lines.push(`${prefix}${dataPrefix}  rot: ${dumpVec3(obj.rotation)}`);
-+  lines.push(`${prefix}${dataPrefix}  scl: ${dumpVec3(obj.scale)}`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

それを実行した結果です。

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-        └─RootNode [Object3D]
-          │   pos: 0.000, 0.000, 0.000
-          │   rot: 0.000, 0.000, 0.000
-          │   scl: 1.000, 1.000, 1.000
-          ├─Cars [Object3D]
-*          │ │   pos: -369.069, -90.704, -920.159
-*          │ │   rot: 0.000, 0.000, 0.000
-*          │ │   scl: 1.000, 1.000, 1.000
-          │ ├─CAR_03_1 [Object3D]
-          │ │ │   pos: 22.131, 14.663, -475.071
-          │ │ │   rot: -3.142, 0.732, 3.142
-          │ │ │   scl: 1.500, 1.500, 1.500
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ │       pos: 0.000, 0.000, 0.000
-          │ │       rot: 0.000, 0.000, 0.000
-          │ │       scl: 1.000, 1.000, 1.000
-
-

これは元のシーンの Cars の回転とスケールが削除され、子に適用されています。 -この原因は、GLTFファイルを作成するために使用されたエクスポータが何か特別な作業をしたか、または3DCGアーティストが対応するblendファイルとは異なるバージョンのファイルをエクスポートした可能性が高いです。

-

この事から学ぶ教訓は、blendファイルをダウンロードして自分でエクスポートするべきという事です。 -エクスポートする前に主要なノードを全て検査し、変換を削除しておくべきでした。

-

Topにあるこれら全てのノードは以下の通りです。

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-
-

この階層構造はもったいないですね。

-

理想的にはシーンは位置、回転、スケールのない単一の"ルート"ノードで構成される事です。 -実行時にはそのルートから全ての子を取り出し、シーン自体を親にする事ができます。 -"Cars"のようなルートの子があるかもしれませんが、全ての車を見つけるのに役立ちます。理想的には平行移動、回転、スケールがないので、最小限の作業でシーンを車の親にする事ができます。

-

いずれにしても、カーブを表示するために使用しているオブジェクトを調整するのが一番手っ取り早いのですが、最善の方法ではないかもしれません。

-

結局はこんな感じですね。

-

最初にカーブの位置を調整し、上手くいきそうな値を見つけました。そして隠しました。

-
{
-  const points = curve.getPoints(250);
-  const geometry = new THREE.BufferGeometry().setFromPoints(points);
-  const material = new THREE.LineBasicMaterial({color: 0xff0000});
-  curveObject = new THREE.Line(geometry, material);
-+  curveObject.scale.set(100, 100, 100);
-+  curveObject.position.y = -621;
-+  curveObject.visible = false;
-  material.depthTest = false;
-  curveObject.renderOrder = 1;
-  scene.add(curveObject);
-}
-
-

それからカーブに沿って移動させるコードを書きました。 -それぞれの車で曲線に沿って0から1までの位置を選び curveObject を用いてワールド座標上の頂点を計算して変換します。 -次にカーブの少し下の方にある別の頂点を選びます。 -車の向きを lookAt で設定し、2点間の中間点に車を配置します。

-
// create 2 Vector3s we can use for path calculations
-const carPosition = new THREE.Vector3();
-const carTarget = new THREE.Vector3();
-
-function render(time) {
-  ...
-
--  for (const car of cars) {
--    car.rotation.y = time;
--  }
-
-+  {
-+    const pathTime = time * .01;
-+    const targetOffset = 0.01;
-+    cars.forEach((car, ndx) => {
-+      // a number between 0 and 1 to evenly space the cars
-+      const u = pathTime + ndx / cars.length;
-+
-+      // get the first point
-+      curve.getPointAt(u % 1, carPosition);
-+      carPosition.applyMatrix4(curveObject.matrixWorld);
-+
-+      // get a second point slightly further down the curve
-+      curve.getPointAt((u + targetOffset) % 1, carTarget);
-+      carTarget.applyMatrix4(curveObject.matrixWorld);
-+
-+      // put the car at the first point (temporarily)
-+      car.position.copy(carPosition);
-+      // point the car the second point
-+      car.lookAt(carTarget);
-+
-+      // put the car between the 2 points
-+      car.position.lerpVectors(carPosition, carTarget, 0.5);
-+    });
-+  }
-
-

そしてそれを実行すると、それぞれの車のオリジンの上に高さが一貫して設定されていなかったので、少しオフセットする必要がありました。

-
const loadedCars = root.getObjectByName('Cars');
-const fixes = [
--  { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
--  { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
--  { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_08', y: 0,  rot: [Math.PI * .5, 0, Math.PI * .5], },
-+  { prefix: 'CAR_03', y: 33, rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_04', y: 40, rot: [0, Math.PI, 0], },
-];
-
-root.updateMatrixWorld();
-for (const car of loadedCars.children.slice()) {
-  const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-  const obj = new THREE.Object3D();
-  car.getWorldPosition(obj.position);
--  car.position.set(0, 0, 0);
-+  car.position.set(0, fix.y, 0);
-  car.rotation.set(...fix.rot);
-  obj.add(car);
-  scene.add(obj);
-  cars.push(obj);
-}
-
-

その結果です。

-

- -

-

数分間の作業にしては悪くない結果です。

-

最後にやりたいのはシャドウをつける事です。

-

これを行うためにシャドウの記事にある DirectionalLight の例から全てのGUIコードを取得し、最新のコードに貼り付けました。

-

読み込み後に全てのオブジェクトにシャドウをオンにする必要があります。

-
{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
-+    root.traverse((obj) => {
-+      if (obj.castShadow !== undefined) {
-+        obj.castShadow = true;
-+        obj.receiveShadow = true;
-+      }
-+    });
-
-

シャドウヘルパーが機能していない理由を探るのに4時間近くを費やしました。 -シャドウを有効にするのを忘れていたのが原因でした。

-
renderer.shadowMap.enabled = true;
-
-

😭

-

そのあと、DirectionLight のシャドウカメラがシーン全体を覆うようになるまで値を調整しました。 -これらの設定は私が最終的にたどり着いたものです。

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-+  light.castShadow = true;
-*  light.position.set(-250, 800, -850);
-*  light.target.position.set(-550, 40, -450);
-
-+  light.shadow.bias = -0.004;
-+  light.shadow.mapSize.width = 2048;
-+  light.shadow.mapSize.height = 2048;
-
-  scene.add(light);
-  scene.add(light.target);
-+  const cam = light.shadow.camera;
-+  cam.near = 1;
-+  cam.far = 2000;
-+  cam.left = -1500;
-+  cam.right = 1500;
-+  cam.top = 1500;
-+  cam.bottom = -1500;
-...
-
-

また、背景色を水色に設定してみました。

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('black');
-+scene.background = new THREE.Color('#DEFEFF');
-
-

そして、シャドウをつけた結果です。

-

- -

-

このプロジェクトを説明する事で、シーングラフを使ってファイルを読込する際の問題点・解決事例をいくつか示せたと思います。

-

興味深いのはblendファイルとgltfファイルの場合、blendファイルにはいくつかのライトがありますが、シーンに読み込み後はライトがありません。 -GLTFファイルはただのJSONファイルなので簡単に中身を見れます。 -これは複数の配列から成り、配列内の各項目は他の場所にインデックスを付けて参照されます。 -拡張機能がありますが、ほとんど全ての3Dフォーマットの問題を指摘しています。全てのケースをカバーする事はできません。

-

もっとデータが欲しいというニーズは常にあります。 -例えば今回は手動で車のパスをエクスポートしました。 -理想的にはGLTFファイルに情報を格納する事ができますが、独自のエクスポーターを作成しエクスポートしたい方法でノードをマークするか、命名スキームなどを使用してデータを作成するために使用しているツールからアプリにデータを取得する必要があります。

-

その全ては読者の皆様の演習としてお任せします。

- -
-
-
- - - - - - - - diff --git a/manual/ja/load-obj.html b/manual/ja/load-obj.html deleted file mode 100644 index 7a14e6455a244d..00000000000000 --- a/manual/ja/load-obj.html +++ /dev/null @@ -1,575 +0,0 @@ - - - でOBJファイルを読み込む - - - - - - - - - - - - - -
-
-

でOBJファイルを読み込む

-
-
-
-

みんながthree.jsでやりたい事の1つに、3Dモデルをロードして表示があります。 -一般的な3DフォーマットであるOBJファイルを読み込んでみましょう。

-

ネットで検索しahedovさんのCC-BY-NC 3.0 風車3Dモデルを見つけました。

-
- -

blendファイルをダウンロードしBlenderで読み込んでOBJファイルを書き出してみました。

-
- -
-

注意:Blenderを使った事がない人は、Blenderは今まで使ってきた他のプログラムとは異なり驚くかもしれません。また、Blenderの基本的なUI操作を理解する時間が必要かもしれません。

-

一般的な3Dプログラムは、1000以上の機能を持つ巨大なモンスターである事も付け加えておきましょう。Blenderもその中の最も複雑なソフトウェアの1つです。 -私が1996年に3D Studio Maxを初めて知った時、600ページのマニュアルの70%を3週間ほど1日数時間かけて読み通しました。 -数年後にMayaを学んだ時には、3d Studio Maxで学んだ経験がMayaでも生かせました。 -もし本当に3Dソフトウェアを使って3Dアセットを構築したり、既存のものを修正したりできるようになりたいなら、自分のスケジュールと時間を確保していくつかのレッスンを受ける事をお勧めします。

-
-

いずれにしても、私は以下のExportオプションを使用しました。

-
- -

それでは表示してみましょう!

-

ライティングの記事 にあるディレクショナルライティングの例から始めて、半球ライティングの例と組み合わせて HemisphereLightDirectionalLight を1つ作る事にしました。その結果として HemisphereLight は1つ、DirectionalLight は1つになりました。 -また、ライトの調整に関連する全てのGUIを削除しました。シーンに追加していたキューブとスフィアも削除しました。

-

まず最初に OBJLoader のローダーをコードに含める必要があります。

-
import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
-
-

次にOBJファイルをロードするために OBJLoader のインスタンスを作成し、OBJファイルのURLを渡し、ロードされたモデルをシーンに追加するコールバックを渡します。

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-    scene.add(root);
-  });
-}
-
-

それを実行したらどうなりますか?

-

- -

-

これはやりたい事に近いですが、シーンにマテリアルとOBJファイルにマテリアルのパラメーターがなく、マテリアルのエラーが発生しています。

-

OBJローダーには名前とマテリアルのペアのオブジェクトを渡す事ができます。 -OBJファイルをロードした時に見つけたマテリアル名で、ローダーに設定されたマテリアルのマップ内で対応するマテリアルを探します。 -マテリアル名で一致するものが見つかった場合はそのマテリアルを使用します。 -見つからない場合はローダーのデフォルトマテリアルを使用します。

-

OBJファイルにはマテリアルを定義するMTLファイルが付属している事があります。 -今回はエクスポーターでMTLファイルも作成しました。 -MTL形式はプレーンなASCIIコードなので見やすいです。MTLファイルの中身を見てみると

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
-map_Bump windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
-map_Bump windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

5つのjpgテクスチャを参照しているマテリアルが2つありますが、テクスチャのファイルはどこにあるのでしょうか?

-
- -

存在するのはOBJファイルとMTLファイルだけです。

-

このモデルではテクスチャはダウンロードしたblendファイルに埋め込まれている事が判明しました。 -blenderで File->External Data->Unpack All Into Files を選択し、これらのファイルをエクスポートする事ができます。

-
- -

そして Write Files to Current Directory を選択します。

-
- -

これでテクスチャのファイルはblendファイルと同じフォルダ内の textures というサブフォルダに出力されます。

-
- -

これらのテクスチャをOBJファイルと同じフォルダにコピーしました。

-
- -

テクスチャを利用できるようになったのでMTLファイルをロードします。 -MTLLoader をimportする必要があります。

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {OBJLoader} from 'three/addons/loaders/OBJLoader.js';
-+import {MTLLoader} from 'three/addons/loaders/MTLLoader.js';
-
-

まず、MTLファイルをロードします。 -読込後にロードしたマテリアルを OBJLoaderに設定して、OBJLoader でOBJファイルをロードします。

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
-+    mtl.preload();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      scene.add(root);
-    });
-+  });
-}
-
-

それを試してみると...

-

- -

-

モデルを回転させると風車の布が消える事に注意して下さい。

-
- -

風車の羽根のマテリアルは両面に適用する必要があり、これはマテリアルの記事で説明しました。 -MTLファイルを簡単に修正する方法はありません。 -私の思いつきではこの問題を修正する3つの方法があります。

-
    -
  1. マテリアルの読込後、全てのマテリアルをループさせて両面を適用する

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.preload()
    -   for (const material of Object.values(mtl.materials)) {
    -     material.side = THREE.DoubleSide;
    -   }
    -   ...
    -

    この解決策は動作しますが、理想的には両面描画は片面描画よりも遅く、両面描画が必要なマテリアルだけを両面にしたいです。

    -
  2. -
  3. 特定のマテリアルを手動で設定する

    -

    MTLファイルを見ると2つのマテリアルがあります。 -1つは "winddmill" と呼び、もう1つは "Material" と呼びます。 -試行錯誤の結果、風車の羽根は "Material" というマテリアル名を使う事が分かりました。

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.perload();
    -   mtl.materials.Material.side = THREE.DoubleSide;
    -   ...
    -
  4. -
  5. MTLファイルには制限がある事に気付き、MTLファイルを使わず自前でマテリアルを作成する

    -
     objLoader.load('resources/models/windmill/windmill.obj', (root) => {
    -   const materials = {
    -     Material: new THREE.MeshPhongMaterial({...}),
    -     windmill: new THREE.MeshPhongMaterial({...}),
    -   };
    -   root.traverse(node => {
    -     const material = materials[node.material?.name];
    -     if (material) {
    -       node.material = material;
    -     }
    -   })
    -   scene.add(root);
    - });
    -
  6. -
-

どれを選ぶかはあなた次第です。 -1が1番簡単です。3が最も柔軟です。2はその中間で今回は2を選びます。

-

この変更で背面から見た時にはまだ風車の羽根に布が見えるはずですが、もう1つ問題があります。 -近くで拡大すると濃淡のむらがある事がわかります。

-
- -

これはどうしたんでしょう?

-

テクスチャを見てみると、ノーマルマップにはNORと書かれた2つのテクスチャがあります。 -これはノーマルマップのように見えます。 -ノーマルマップは一般的に紫色ですが、バンプマップは黒と白になっています。 -ノーマルマップはサーフェスの方向を表し、バンプマップはサーフェスの高さを表します。

-
- -

MTLLoaderのソースを見るとノーマルマップのキーワード norm を期待しているのでMTLファイルを編集してみましょう。

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
--map_Bump windmill_001_lopatky_NOR.jpg
-+norm windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
--map_Bump windmill_001_base_NOR.jpg
-+norm windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

これでロードするとノーマルマップとして扱うようになり、風車の羽根の裏が描画されるようになりました。

-

- -

-

別のファイルを読み込んでみましょう。

-

ネットで検索するとRoger Gerzner / GERIZ.3D Artで作られたCC-BY-NCの風車の3Dモデルを見つけました。

-
- -

これにはOBJファイルが既にありました。 -それをロードしてみましょう(ここでMTLローダーを削除した事に注意して下さい)

-
-  objLoader.load('resources/models/windmill/windmill.obj', ...
-+  objLoader.load('resources/models/windmill-2/windmill.obj', ...
-
-

- -

-

うーん、何も出てこない...。何が問題でしょうか? -モデルのサイズはどれくらいなんだろう?

-

Three.jsにモデルのサイズを確認してカメラを自動設定してみます。

-

まず最初にThree.jsに先ほど読み込んだシーンを含むボックスを計算し、そのサイズと中心座標を確認してみましょう。

-
objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-  scene.add(root);
-
-+  const box = new THREE.Box3().setFromObject(root);
-+  const boxSize = box.getSize(new THREE.Vector3()).length();
-+  const boxCenter = box.getCenter(new THREE.Vector3());
-+  console.log(boxSize);
-+  console.log(boxCenter);
-
-

JavaScriptコンソールを見ると

-
size 2123.6499788469982
-center p {x: -0.00006103515625, y: 770.0909731090069, z: -3.313507080078125}
-
-

現在カメラは near が0.1、far が100で約100ユニットしか表示されていません。 -地上は40ユニットしかなく、この風車のモデルは2000ユニットと非常に大きく、カメラとその全ての部分が錐台の外にあります。

-
- -

手動で修正することもできますが、シーンを自動でフレーム化する事もできます。

-

それを試してみましょう。 -先ほど計算したボックスを使いシーン全体を表示するためにカメラの設定を調整する事ができます。カメラをどこに置くかは 正解はない 事に注意して下さい。 -どの方向から見てもどの高さでも向き合う事ができるので何かを選ぶしかないですね。

-

カメラの記事で説明したようにカメラは錐台を定義します。 -視野 (fov) と nearfar の設定によって錐台が定義されます。 -カメラが現在持っている視野がどのようなものであっても、シーンが入っているボックスが画面外が永遠に伸びていると仮定して画面外の中に収まるように、カメラはどのくらい離れている必要があるのかを知りたいです。 -つまり near は0.00000001、far は無限大であるとすると near は0.00000001、far は無限大です。

-

ボックスの大きさと視野が分かっているので次のような三角形ができます。

-
- -

左側にカメラがあり、青い錐台が突き出しているのが分かります。 -風車が入っているボックスを計算してみました。 -ボックスが錐台の中に現れるように、カメラがボックスからどのくらい離れているかを計算する必要があります。

-

基本的な 直角三角形 の三角法とSOHCAHTOAを使用します。 -視野とボックスの大きさが分かっていれば 距離 を計算できます。

-
- -

この図に基づいて距離を計算する式は次のようになります。

-
distance = halfSizeToFitOnScreen / tangent(halfFovY)
-
-

コードに変換してみましょう。 -まずは 距離 を計算する関数を作り、ボックスの中心から 距離 単位でカメラを移動させてみましょう。 -次にカメラをボックスの 中心 に向けます。

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  // compute a unit vector that points in the direction the camera is now
-  // from the center of the box
-  const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-
-  // move the camera to a position distance units way from the center
-  // in whatever direction the camera was from the center already
-  camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
-
-  // pick some near and far values for the frustum that
-  // will contain the box.
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-
-  // point the camera to look at the center of the box
-  camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
-}
-
-

2つのサイズを引数に渡しています。 -boxSizesizeToFitOnScreen の事です。 -boxSize を渡し sizeToFitOnScreen として使用すれば、計算でボックスが錐台の中に完全に収まるようになります。 -上下に少し余分なスペースが欲しいので少し大きめのサイズにします。

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-    scene.add(root);
-+    // compute the box that contains all the stuff
-+    // from root and below
-+    const box = new THREE.Box3().setFromObject(root);
-+
-+    const boxSize = box.getSize(new THREE.Vector3()).length();
-+    const boxCenter = box.getCenter(new THREE.Vector3());
-+
-+    // set the camera to frame the box
-+    frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-+
-+    // update the Trackball controls to handle the new size
-+    controls.maxDistance = boxSize * 10;
-+    controls.target.copy(boxCenter);
-+    controls.update();
-  });
-}
-
-

上記の図のように boxSize * 1.2 を渡しボックスを錐台内に収める際にボックスの上下に20%のスペースを確保する事ができます。 -また OrbitControls を更新し、カメラがシーンの中心を周回するようにしました。

-

それを試してみると...

-

- -

-

これはほぼ動作してますね。 -カメラを回転させるためにマウスを使用し、風車が表示されるはずです。 -問題は風車が大きく、箱の中心が(0,770,0)くらいにあります。 -つまり、カメラをスタート地点(0, 10, 20)から中心から 距離 単位で移動させると、カメラは中心に対して相対的に風車の下をほぼ真下に移動しています。

-
- -

ボックスの中心からカメラのある方向に横に移動するように変更してみましょう。 -そのために必要なのはボックスからカメラまでのベクトルの y をゼロにする事です。 -ベクトルを正規化するとXZ平面に平行なベクトルになります。 -言い換えれば地面と平行になります。

-
-// compute a unit vector that points in the direction the camera is now
--// from the center of the box
--const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-+// compute a unit vector that points in the direction the camera is now
-+// in the xz plane from the center of the box
-+const direction = (new THREE.Vector3())
-+    .subVectors(camera.position, boxCenter)
-+    .multiply(new THREE.Vector3(1, 0, 1))
-+    .normalize();
-
-

風車の底を見ると小さな四角いものが見えます。それが地上面です。

-
- -

40 × 40ユニットしかないので風車に比べて小さすぎます。 -風車の大きさが2000ユニットを超えているので、地上面の大きさをもっとピッタリしたものに変えてみましょう。 -また、テクスチャのrepeatを調整する必要があります。 -チェッカーボードはズームインしない限り、見る事さえできないような細かいものになります。

-
-const planeSize = 40;
-+const planeSize = 4000;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
--const repeats = planeSize / 2;
-+const repeats = planeSize / 200;
-texture.repeat.set(repeats, repeats);
-
-

これで風車を見る事ができます。

-

- -

-

マテリアルを元に戻してみましょう。 -先ほどと同じようにテクスチャを参照しているMTLファイルがありますが、ファイルを見てみるとすぐに問題点が浮き上がります。

-
 $ ls -l windmill
- -rw-r--r--@ 1 gregg  staff       299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff    142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_diffuse.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 20  2009 windmill_normal.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_spec.tga
-
-

TARGA(.tga)ファイルが巨大です!

-

Three.jsにはTGAローダーがありますが、ほとんどのユースケースでそれを使うのは間違いです。 -ネット上で見つけたランダムな3Dファイルを閲覧できるようなビューアを作っているのであれば、TGAファイルを読み込んだ方がいいかもしれません。(*)

-

TGAファイルの問題点は、全てを上手く圧縮できない事です。 -TGAは非常に単純な圧縮しかサポートしておらず、上記を見てみると全てのファイルが同じサイズになる確率が非常に低いため、圧縮されていない事がわかります。

-

さらにそれぞれが12MB!

-

もしTGAのファイルを使った場合、風車を見るために36MBのファイルをダウンロードしなければならないでしょう。

-

TGAのもう1つの問題はブラウザ自体がTGAをサポートしていない事です。 -TGAの読み込みはJPGやPNGのようなサポートされているフォーマットの読込よりも遅くなる可能性が高いです。

-

私はthree.jsで3Dモデルを表示するためには、TGAをJPGに変換する事が最善の選択肢であると確信しています。 -中身を見るとそれぞれ3チャンネル、RGBでアルファチャンネルはありません。 -JPGはダウンロードするためにファイルをロス有り圧縮を行い、少ないサイズのファイルダウンロードを提供します。

-

ファイルを読み込むと2048 x 2048サイズになっていました。 -私には無駄に大きいサイズに思えましたが、もちろん使用ケースによります。 -1024 x 1024にしPhotoshopで50%の画質設定で保存してみました。 -ファイルリストを取得すると

-
 $ ls -l ../threejs.org/manual/examples/resources/models/windmill
- -rw-r--r--@ 1 gregg  staff     299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff  142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  259927 Nov  7 18:37 windmill_diffuse.jpg
- -rw-r--r--@ 1 gregg  staff   98013 Nov  7 18:38 windmill_normal.jpg
- -rw-r--r--@ 1 gregg  staff  191864 Nov  7 18:39 windmill_spec.jpg
-
-

36MEGから0.55MEGまで圧縮できました! -3DCGデザイナーなどのアーティストはこの圧縮に満足していないかもしれませんので、トレードオフについて相談するようにして下さい。

-

さてMTLファイルを使用するには、JPGファイルを参照するように編集する必要があります。 -TGAファイルの代わりにJPGファイルを使用します。 -幸いな事にこれは単純なテキストファイル編集のみで簡単です。

-
newmtl blinn1SG
-Ka 0.10 0.10 0.10
-
-Kd 0.00 0.00 0.00
-Ks 0.00 0.00 0.00
-Ke 0.00 0.00 0.00
-Ns 0.060000
-Ni 1.500000
-d 1.000000
-Tr 0.000000
-Tf 1.000000 1.000000 1.000000
-illum 2
--map_Kd windmill_diffuse.tga
-+map_Kd windmill_diffuse.jpg
-
--map_Ks windmill_spec.tga
-+map_Ks windmill_spec.jpg
-
--map_bump windmill_normal.tga
--bump windmill_normal.tga
-+map_bump windmill_normal.jpg
-+bump windmill_normal.jpg
-
-

MTLファイルが適度なサイズのテクスチャを指しているので、それをロードする必要があります。 -上記で行ったようにまずマテリアルをロードしてから OBJLoader に設定します。

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill_2/windmill-fixed.mtl', (mtl) => {
-+    const objLoader = new OBJLoader();
-+    mtl.preload();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      root.updateMatrixWorld();
-      scene.add(root);
-      // compute the box that contains all the stuff
-      // from root and below
-      const box = new THREE.Box3().setFromObject(root);
-
-      const boxSize = box.getSize(new THREE.Vector3()).length();
-      const boxCenter = box.getCenter(new THREE.Vector3());
-
-      // set the camera to frame the box
-      frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-
-      // update the Trackball controls to handle the new size
-      controls.maxDistance = boxSize * 10;
-      controls.target.copy(boxCenter);
-      controls.update();
-    });
-+  });
-}
-
-

実際にやってみる前にいくつかの問題にぶつかりました。

-

問題1: 3つの MTLLoader は、マテリアルのディフューズカラーにディフューズテクスチャマップを乗算したマテリアルを作成します。

-

これは便利な機能ですがMTLファイルの上記の行を見ると

-
Kd 0.00 0.00 0.00
-
-

ディフューズ色を0に設定します。 -テクスチャマップ * 0 = 黒です! -風車を作るのに使われたモデリングツールがディフューズテクスチャマップにディフューズカラーを掛けていなかった可能性があります。 -だからこそ、この風車を作った3DCGデザイナーなどのアーティストの3DCG Tool上では動作してました。

-

これを修正するには、次の行を修正する必要があります。

-
Kd 1.00 1.00 1.00
-
-

テクスチャ マップ * 1 = テクスチャマップです。

-

問題点その2:スペキュラカラーも黒である

-

Ks で始まる行はスペキュラカラーを指定します。 -風車を作るのに使われたモデリングソフトはスペキュラマップの色をスペキュラハイライトに使うという点でディフューズマップと似たような事をしていたのでしょう。 -Three.jsではスペキュラカラーをどの程度反射させるかの入力値は、スペキュラマップの赤チャンネルのみを使用しています。 -つまり、スペキュラカラーセットが必要です。

-

上記のようにMTLファイルを以下のように修正する事ができます。

-
-Ks 0.00 0.00 0.00
-+Ks 1.00 1.00 1.00
-
-

問題 #3: windmill_normal.jpg はバンプマップではなくノーマルマップです

-

上記のようにMTLファイルを編集する必要があります。

-
-map_bump windmill_normal.jpg
--bump windmill_normal.jpg
-+norm windmill_normal.jpg
-
-

それを考慮し試してみるとマテリアルが一杯になるはずです。

-

- -

-

モデルをロードするとこのような問題が発生することがよくあります。 -よくある問題には以下のようなものがあります。

-
    -
  • サイズを把握する必要がある

    -

    上記のようにカメラにシーンをフレーミングしようとさせましたが、それは必ずしも適切な事ではありません。 -一般的に最も適切なのは自分でモデルを作るか、モデルをダウンロードし、3Dソフトでロードしてそのスケールを見て必要に応じて調整する事です。

    -
  • -
  • 方向性の違い

    -

    three.jsは一般的にはy = upです。モデリングツールによってはZ = upにデフォルトで設定されているものもあれば、Y = upに設定されているものもあります。 -設定可能なものもあります。 -モデルをロードして横になっているようなケースに遭遇した場合、モデルを回転させるコードをハックすることもできます(推奨されません)。 -また、お気に入りのモデリングツールにモデルを読み込むか、コマンドラインツールを使い、ウェブサイト用の画像をダウンロードしてコードを適用するのではなく、ウェブサイト用の画像を編集するように必要な方向にオブジェクトを回転させる事もできます。

    -
  • -
  • MTLファイルや間違ったマテリアル、互換性のないパラメータがない場合

    -

    上記ではMTLファイルを使用していましたが、マテリアルの読込には問題がありました。 -OBJファイルの中身を見てどんなマテリアルがあるのかを確認したり、three.jsでOBJファイルを読み込んでシーンを歩いて全てのマテリアルをプリントアウトしたりするのも一般的です。

    -
  • -
  • テクスチャが大きすぎる

    -

    3Dモデルの多くは建築用、映画やCM用、ゲーム用のどちらかに作られています。 -建築や映画の場合は誰もがテクスチャのサイズを気にしていません。 -ゲームはメモリが限られていますが、ほとんどのゲームはローカルで実行されているので、ゲーム開発者は気にしています。 -Webページはできるだけ速く読みたいので、テクスチャをできるだけ小さく、かつ見栄えの良いものにする必要があります。 -実際に最初の風車では、間違いなくテクスチャについて何かをするべきでした。現在のサイズ合計は10MBです!

    -

    テクスチャの記事で述べたようにテクスチャはメモリを取ります。 - 4096 x 4096に展開された50kのJPGは高速にダウンロードされますが、大量のメモリを消費する事を覚えておいて下さい。

    -
  • -
-

最後に見せたかったのは風車を回している所です。残念ながらOBJファイルには階層がありません。 -つまり、各風車のパーツは基本的に1つのメッシュとして考えられています。 -ミルの羽根は分離されていないので回転させる事はできません。

-

これがOBJファイルは良いフォーマットではない主な理由の1つです。 -推測するならば、他のフォーマットよりも一般的な理由はシンプルで多くの機能をサポートしていないため、より多くの場合に動作します。 -特に建築物のイメージのような静止したものを作っていて、何かをアニメーション化する必要がない場合はシーンに静的な小道具を入れるのには悪くない方法です。

-

次はgLTFシーンをロードしてみます。gLTFフォーマットは他にも多くの機能をサポートしています。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/material-table.html b/manual/ja/material-table.html deleted file mode 100644 index bcc345b7d71868..00000000000000 --- a/manual/ja/material-table.html +++ /dev/null @@ -1,42 +0,0 @@ - - - Material Feature Table - - - - - - - - - - - - - -
-
-

Material Feature Table

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/materials.html b/manual/ja/materials.html deleted file mode 100644 index 1068b80fc7bdf5..00000000000000 --- a/manual/ja/materials.html +++ /dev/null @@ -1,301 +0,0 @@ - - - マテリアル - - - - - - - - - - - - - -
-
-

マテリアル

-
-
-
-

この記事はthree.jsについてのシリーズ記事の一つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでない人は、そちらから先に読んでみるといいかもしれません。

-

Three.jsはいくつかの種類のマテリアルを提供しています。 -これらは、オブジェクトがどのようにシーンに表示されるかを定義します。 -どのマテリアルを使うべきかは、皆さんが何をしたいかによります。

-

マテリアルの属性の設定方法は、だいたい2つです。 -一つは、表示される前の作成時です。

-
const material = new THREE.MeshPhongMaterial({
-  color: 0xFF0000,    // red (can also use a CSS color string here)
-  flatShading: true,
-});
-
-

もう一つは作成後です。

-
const material = new THREE.MeshPhongMaterial();
-material.color.setHSL(0, 1, .5);  // red
-material.flatShading = true;
-
-

THREE.Color型の属性は設定方法が複数あることに注意してください。

-
material.color.set(0x00FFFF);    // same as CSS's #RRGGBB style
-material.color.set(cssString);   // any CSS color, eg 'purple', '#F32',
-                                 // 'rgb(255, 127, 64)',
-                                 // 'hsl(180, 50%, 25%)'
-material.color.set(someColor)    // some other THREE.Color
-material.color.setHSL(h, s, l)   // where h, s, and l are 0 to 1
-material.color.setRGB(r, g, b)   // where r, g, and b are 0 to 1
-
-

作成時に、16進数かCSS文字列を渡すことができます。

-
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000});         // red
-const m2 = new THREE.MeshBasicMaterial({color: 'red'});            // red
-const m3 = new THREE.MeshBasicMaterial({color: '#F00'});           // red
-const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'});   // red
-const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'}); // red
-
-

では、three.jsのマテリアルの設定の説明をしましょう。

-

MeshBasicMaterialは光源の影響を受けません。 -MeshLambertMaterialは頂点でのみ光を計算します。 -一方で、MeshPhongMaterialは全てのピクセルで光を計算します。 -MeshPhongMaterialは、specularによるハイライトもサポートします。

-
-
-
-
Basic
-
-
-
-
Lambert
-
-
-
-
Phong
-
-
-
-
-
-
-
-
-
-
-
-
-
-
同じマテリアルでポリゴン数を変えたモデル
- -

MeshPhongMaterialshininess設定は特定のハイライトの輝きを決めます。デフォルトは30です。

-
-
-
-
shininess: 0
-
-
-
-
shininess: 30
-
-
-
-
shininess: 150
-
-
- -

MeshLambertMaterialMeshPhongMaterialのどちらかで、colorに対してemissive属性を設定し、 -色を黒(phongならshininessを0)に設定すると、ちょうどMeshBasicMaterialのように見えることに注意してください。

-
-
-
-
-
Basic
-
color: 'purple'
-
-
-
-
-
-
Lambert
-
color: 'black'
-
emissive: 'purple'
-
-
-
-
-
-
Phong
-
color: 'black'
-
emissive: 'purple'
-
shininess: 0
-
-
-
- -

MeshPhongMaterialMeshBasicMaterialMeshLambertMaterialと同じようにできるのに、なぜ3種もあるのでしょうか。 -理由は、より洗練されたマテリアルは、描写するのにGPUパワーを必要とするためです。 -携帯電話といった、遅いGPCでは、より簡単なマテリアルを使うことで、描画に必要なGPUパワーを削減できるかもしれません。 -また、余計な機能を必要としないなら、一番シンプルなマテリアルを使用するとよいです。 -光源やspecularによるハイライトが不要なら、MeshBasicMaterialを使うこともできます。

-

MeshToonMaterialMeshPhongMaterialに似ていますが、一点大きな違いがあります。 -連続的にシェーディングするのではなく、グラデーションマップ(X×1のテクスチャ)を使ってシェーディングの方法を決めます。 -デフォルトは明るさの始まりが70%、終わりが100%のグラデーションマップを適用しますが、自分で決めたグラデーションマップを適用することもできます。 -これにより、まるでアニメのようなツートーンになります。

-
-
-
- -

続いて2つの物理ベースレンダリングのマテリアルがあります。 -物理ベースレンダリングはよくPBRと略します。

-

上記のマテリアルは、3Dに見えるマテリアルを簡単な数学で作っていますが、 -これは現実世界で本当に起きている現象にのっとっていません。 -2つのPBRマテリアルはもっと複雑な数学を使い、現実世界に近づいています。

-

一つ目はMeshStandardMaterialです。MeshPhongMaterialMeshStandardMaterialの -最大の違いは、異なるパラメータを使っていることです。 -MeshPhongMaterialshininess設定があります。 -MeshStandardMaterialroughnessmetalnessの2つの設定があります。

-

基本的に、roughnessshininessの逆です。 -野球ボールがほとんど反射しないように、とても粗いのものがある一方で、 -とても光沢があるビリヤード玉のように、粗くないものもあります。 -roughnessは0から1の間をとります。

-

もう一つの設定で、metalnessは、マテリアルの金属っぽさです。 -金属は非金属と異なった振る舞いをします。 -0は非金属で、1は金属です。

-

ここに、MeshStandardMaterialのサンプルがあります。 -右に行くにつれて、roughnessは0から1に変わります。 -下に行くにつれて、metalnessは0から1に変わります。

-
- -

MeshPhysicalMaterialは、MeshStandardMaterialと同様ですが、 -clearcoatパラメータが追加されています。このパラメータは、0から1につれて、 -clearcoat光沢層が適用されます。 -また、clearCoatRoughnessパラメータも追加されていて、これは光沢層の粗さを決定します。

-

ここに、上と同じmetalnessroughnessのグリッドがあります。 -ただし、clearcoatclearCoatRoughnessの設定が付いています。

-
- -

様々な標準のマテリアルのうち、高速なものから低速なものを並べると、 -MeshBasicMaterialMeshLambertMaterialMeshPhongMaterial ➡ -MeshStandardMaterialMeshPhysicalMaterialになります。 -低速なマテリアルは、より現実味のある見た目のシーンを作ることができますが、 -パワーが低いデバイスやモバイル端末では、より高速なマテリアルを使うようにコードを設計する必要があります。

-

続いて、特別な用途に使う3つのマテリアルがあります。 -ShadowMaterialは影から作られたデータを得るのに使われます。 -まだ影については説明していませんでしたね。 -その際には、このマテリアルを使って、シーンの裏で何が起きているのか、のぞいてみたいと思います。

-

MeshDepthMaterialは各ピクセルの深度を描写します。 -カメラの負のnearにあるピクセルは0、負のfarにあるピクセルは1です。 -また別の機会に、特定の特殊効果がこのデータを使うかもしれません。

-
-
-
-
-
- - -

MeshNormalMaterialはジオメトリの法線を表示します。 -法線は、特定の三角形かピクセル表面の方向です。 -MeshNormalMaterialは見えている空間の法線を描画します(法線はカメラに依存します)。

-

xは赤、 -yは緑そして -zは青なので、 -物体の右側はpink、 -左側はaqua、 -上側はlight green、 -下側はpurple、 -そして画面側はlavenderになるでしょう。

-
-
-
-
-
- -

ShaderMaterialは、three.jsのシェーダーシステムを使ったカスタムマテリアルを作るためのものです -RawShaderMaterialは、three.jsの補助なしで、完全に独自シェーダーを作るためのものです。 -これらのトピックはどちらも大きいため、後ほど説明します。

-

全てのマテリアルはMaterialによって決められた設定を共有しています。 -それらはドキュメントを見てください。けれども、最も一般的に使われる2つの属性について説明しましょう。

-

flatShading:物体の面が分割されて見えるか、滑らかに見えるか。デフォルトはfalseです。

-
-
-
-
flatShading: false
-
-
-
-
flatShading: true
-
-
- -

side:三角形の両面を表示するか。デフォルトはTHREE.FrontSideです。 -ほかのオプションは THREE.BackSideTHREE.DoubleSide(両面)です。 -threeで描写されるほとんどの3Dオブジェクトは、たぶん不透明な固体です。 -そのため、裏面(固体の内側を向いている面)は描画する必要はありません。 -sideを設定する最も一般的な理由は、平面やほかの固体ではないオブジェクトのためです。 -これらは、三角形の裏面を見ることが普通だからです。

-

ここに、THREE.FrontSideTHREE.DoubleSideで描画された6つの平面があります。

-
-
-
-
side: THREE.FrontSide
-
-
-
-
side: THREE.DoubleSide
-
-
- -

マテリアルについては、本当にたくさん考えることがあり、実際にはもっとたくさんの説明したいパラメータがあります。 -特に、私たちは多くのオプションの話につながる、テクスチャをほとんど無視していました。 -テクスチャを説明する前に、休憩を取って、開発環境のセットアップを説明する必要があります。

-
-

material.needsUpdate

- -

-このトピックはめったにthree.jsアプリに影響しませんが、単にFYIのつもりで...。 -Three.jsはマテリアルが"使われた"ときに設定を適用します。 -"使われた"は"マテリアルを使って何かが描画される"ということです。 -マテリアルの設定はたった一度だけ適用されます。変更するとthree.jsに多くの仕事が必要になります。 -変更するケースでは、three.jsに変更を伝えるため、material.needsUpdate = trueを設定する必要があります。 -マテリアルを試用した後で、needsUpdateの設定を必要とする一般的な設定はこのようになります: - -

-
    -
  • flatShading
  • -
  • テクスチャの追加や削除 -

    - テクスチャの変更はOKですが、テクスチャを使わない状態から使う状態に変更したり、 - テクスチャを使っている状態から使わない状態に変更したいとすると、 - needsUpdate = trueを設定する必要があります。 -

    -

    テクスチャありからテクスチャなしに変更するケースでは、 - 1x1ピクセルのホワイトテクスチャを使うことがよいです。

    -
  • -
-

この問題は、ほとんどのアプリには関係ありません。 -ほとんどのアプリではフラットシェードありとフラットシェードなしを切り替えません。 -また、ほとんどのアプリは、与えられたマテリアルにテクスチャか固定の色のどちらかを使い、 -めったに一方からもう一方に切り替えたりしません。 -

-
- -

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/multiple-scenes.html b/manual/ja/multiple-scenes.html deleted file mode 100644 index 3ad88efc53720b..00000000000000 --- a/manual/ja/multiple-scenes.html +++ /dev/null @@ -1,644 +0,0 @@ - - - の複数キャンバスと複数シーン - - - - - - - - - - - - - -
-
-

の複数キャンバスと複数シーン

-
-
-
-

よくある質問として、どうやってThree.jsで複数キャンバスを使用するのかがあります。 -ECサイトを作りたい、3Dダイアグラムをたくさん使ったページを作りたいとしましょう。 -一見簡単そうに見えます。 -ダイアグラムが欲しい所にキャンバスを作るだけです。 -それぞれのキャンバスで Renderer を作成します。

-

以下の問題にすぐに気づくでしょう。

-
    -
  1. ブラウザはWebGLコンテキスト数を制限している

    -

    一般的にはコンテキスト数の制限は約8個です。 - 9個目のコンテキストを作成すると、すぐに古いコンテキストが失われます。

    -
  2. -
  3. WebGLリソースはコンテキスト間で共有できない

    -

    10MBの3Dモデルを2つのキャンバスにロードしたいとします。 - 20MBのテクスチャを持ち、10MBの3Dモデルも20MBのテクステャも2回ロードしなければなりません。 - コンテキスト間で共有はできません。 - つまり、初期化もシェーダーコンパイルも2回する必要があります。 - キャンバスが増えると回数が増えさらに悪化します。

    -
  4. -
-

何か解決策はないでしょうか?

-

解決策としては、背景のViewPortを埋める1つのキャンバスと、キャンバス以外のHTML要素で"仮想"のキャンバスを持つ事です。 -仮想キャンバスごとに RendererScene を1つずつ作成します。 -次に仮想キャンバス要素の位置を確認し、その要素が画面上にある場合はシーンの正しい場所に描画するようにします。

-

この解決策はキャンバスが1つしかないため、上記の1と2の問題を解決します。 -1つのコンテキストだけなので、WebGLコンテキストの制限は問題ありません。 -同じ理由で共有の問題もありません。

-

2つのシーンだけの簡単な例から始めましょう。まずはHTMLを作成します。

-
<canvas id="c"></canvas>
-<p>
-  <span id="box" class="diagram left"></span>
-  I love boxes. Presents come in boxes.
-  When I find a new box I'm always excited to find out what's inside.
-</p>
-<p>
-  <span id="pyramid" class="diagram right"></span>
-  When I was a kid I dreamed of going on an expedition inside a pyramid
-  and finding a undiscovered tomb full of mummies and treasure.
-</p>
-
-

次にCSSを次のように設定します。

-
#c {
-  position: fixed;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: block;
-  z-index: -1;
-}
-.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-  border: 1px solid black;
-}
-.left {
-  float: left;
-  margin-right: .25em;
-}
-.right {
-  float: right;
-  margin-left: .25em;
-}
-
-

キャンバスを画面一杯にし、z-index を-1に設定し他のDOM要素よりも後に表示されるようにします。 -仮想キャンバスにはサイズ指定がないため、幅と高さを指定する必要があります。

-

次にライトとカメラをそれぞれ2つのシーンに作成します。 -1つ目のシーンにキューブを追加し、もう1つのシーンにはひし形を追加します。

-
function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  return {scene, camera, elem};
-}
-
-function setupScene1() {
-  const sceneInfo = makeScene(document.querySelector('#box'));
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({color: 'red'});
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-function setupScene2() {
-  const sceneInfo = makeScene(document.querySelector('#pyramid'));
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-const sceneInfo1 = setupScene1();
-const sceneInfo2 = setupScene2();
-
-

DOM要素が画面上にある場合のみ、各シーンをレンダリングする関数を作成します。 -Renderer.setScissorTestシザー テストを有効にし、キャンバスの一部だけをレンダリングするように指定できます。 -Renderer.setViewportRenderer.setScissor でシザーとビューポートの両方を設定します。

-
function renderSceneInfo(sceneInfo) {
-  const {scene, camera, elem} = sceneInfo;
-
-  // get the viewport relative position of this element
-  const {left, right, top, bottom, width, height} =
-      elem.getBoundingClientRect();
-
-  const isOffscreen =
-      bottom < 0 ||
-      top > renderer.domElement.clientHeight ||
-      right < 0 ||
-      left > renderer.domElement.clientWidth;
-
-  if (isOffscreen) {
-    return;
-  }
-
-  camera.aspect = width / height;
-  camera.updateProjectionMatrix();
-
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  renderer.render(scene, camera);
-}
-
-

render関数で最初に画面をクリア後、各シーンをレンダリングします。

-
function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  sceneInfo1.mesh.rotation.y = time * .1;
-  sceneInfo2.mesh.rotation.y = time * .1;
-
-  renderSceneInfo(sceneInfo1);
-  renderSceneInfo(sceneInfo2);
-
-  requestAnimationFrame(render);
-}
-
-

その結果がこれです。

-

- -

-

最初の <span> が赤いキューブ、2つ目の span が青いひし形です。

-

同期する

-

上記のコードは動作していますが、1つだけ小さな問題があります。 -シーンが複雑だったり、何らかの理由でレンダリングに時間がかかり過ぎる場合、 -キャンバスに描画したシーンの位置が他のページよりも遅れてしまいます。

-

各エリアにborderを与えて

-
.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-+  border: 1px solid black;
-}
-
-

各シーンに背景色を設定します。

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('red');
-
-

そして、素早く上下にスクロールすると問題が分かります。以下はスクロールが10倍に遅くなった動画です。

-
- -

別のトレードオフになる別の方法に切り替える事もできます。 -キャンバスのCSSを position: fixed から position: absolute に切り替えます。

-
#c {
--  position: fixed;
-+  position: absolute;
-
-

キャンバスの変形を設定し、キャンバス上部が現在のページスクロールしている部分の上部にくるように移動させます。

-
function render(time) {
-  ...
-
-  const transform = `translateY(${window.scrollY}px)`;
-  renderer.domElement.style.transform = transform;
-
-

position: fixed はページの残りの部分がスクロールしている間、キャンバスがスクロールしないようにしていました。 -position: absolute は、キャンバスをページの残りの部分と一緒にスクロールさせます。 -これはレンダリングに時間がかかりすぎても、描画したものがスクロールしてもページに密着します。 -ページがスクロールされた位置に合わせてキャンバスを移動し再レンダリングします。 -ウィンドウの端だけが一瞬レンダリングされていないビットが表示されますが、ページの真ん中にあるものは一致しているのでスライドしません。新しい方法で10倍に遅くなった結果を見てみましょう。

-
- -

もっと汎用的なコードにする

-

複数のシーンが機能したので、もう少し汎用的なコードにしてみましょう。

-

キャンバスを管理するメインのrender関数にDOM要素のリストと関連するrender関数だけ持たせる事ができます。 -各要素に対して画面上に表示されているかチェックし、表示されている場合は対応するrender関数を呼び出します。 -この方法は個々のシーンが小さな空間でレンダリングされている事を意識せず、汎用的なシステムになります。

-

これがメインのrender関数です。

-
const sceneElements = [];
-function addScene(elem, fn) {
-  sceneElements.push({elem, fn});
-}
-
-function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.setClearColor(clearColor, 0);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  const transform = `translateY(${window.scrollY}px)`;
-  renderer.domElement.style.transform = transform;
-
-  for (const {elem, fn} of sceneElements) {
-    // get the viewport relative position of this element
-    const rect = elem.getBoundingClientRect();
-    const {left, right, top, bottom, width, height} = rect;
-
-    const isOffscreen =
-        bottom < 0 ||
-        top > renderer.domElement.clientHeight ||
-        right < 0 ||
-        left > renderer.domElement.clientWidth;
-
-    if (!isOffscreen) {
-      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
-      renderer.setScissor(left, positiveYUpBottom, width, height);
-      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-      fn(time, rect);
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

elemfn プロパティを持つオブジェクトの配列があり、sceneElements でループしているのが分かります。

-

要素が画面上にあるかどうかをチェックします。 -画面上にある場合は fn を呼び出し、引数に現在の時刻と矩形を渡します。

-

これで各シーン設定のコードがシーンのリストに追加されます。

-
{
-  const elem = document.querySelector('#box');
-  const {scene, camera} = makeScene();
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({color: 'red'});
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-{
-  const elem = document.querySelector('#pyramid');
-  const {scene, camera} = makeScene();
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-

sceneInfo1sceneInfo2 が不要になり、メッシュを回転させていたコードがシーンごとに固有になりました。

-

- -

-

HTML Datasetを使う

-

最後にもっと汎用的にするためにHTML datasetを使います。 -これはHTML要素に独自のデータを追加する方法です。 -id="...." の代わりに data-diagram="...." を使います。

-
<canvas id="c"></canvas>
-<p>
--  <span id="box" class="diagram left"></span>
-+  <span data-diagram="box" class="left"></span>
-  I love boxes. Presents come in boxes.
-  When I find a new box I'm always excited to find out what's inside.
-</p>
-<p>
--  <span id="pyramid" class="diagram left"></span>
-+  <span data-diagram="pyramid" class="right"></span>
-  When I was a kid I dreamed of going on an expedition inside a pyramid
-  and finding a undiscovered tomb full of mummies and treasure.
-</p>
-
-

CSSのセレクタを変更し、それを選択するようにします。

-
-.diagram
-+*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-
-

シーン設定のコードを変更して シーン初期化関数 への名前のマップにします。 -そして、シーンのレンダリング関数 を返すようにします。

-
const sceneInitFunctionsByName = {
-  'box': () => {
-    const {scene, camera} = makeScene();
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-  'pyramid': () => {
-    const {scene, camera} = makeScene();
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

次に querySelectorAll で全てのdiagramを見つけ、対応するinit関数を呼び出します。

-
document.querySelectorAll('[data-diagram]').forEach((elem) => {
-  const sceneName = elem.dataset.diagram;
-  const sceneInitFunction = sceneInitFunctionsByName[sceneName];
-  const sceneRenderFunction = sceneInitFunction(elem);
-  addScene(elem, sceneRenderFunction);
-});
-
-

見た目の変更はありませんが、コードはさらに汎用的になっています。

-

-

各要素にコントロールを追加する

-

TrackballControls のようなインタラクティブな要素を追加するのは簡単です。 -最初にコントロール用のスクリプトを追加します。

-
import {TrackballControls} from 'three/addons/controls/TrackballControls.js';
-
-

そして TrackballControls を各シーンに追加し、シーンに関連付けられた要素を渡します。

-
-function makeScene() {
-+function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-+  scene.add(camera);
-
-+  const controls = new TrackballControls(camera, elem);
-+  controls.noZoom = true;
-+  controls.noPan = true;
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
--    scene.add(light);
-+    camera.add(light);
-  }
-
--  return {scene, camera};
-+ return {scene, camera, controls};
-}
-
-

シーンにカメラを追加し、カメラにライティングを追加しました。 -これにより、カメラに対する相対的な光を受けます。 -TrackballControls がカメラを動かしているので、これが望んだ形です。 -見ている対象物の側に光を当て続けます。

-

render関数でこれらのコントロールを更新する必要があります。

-
const sceneInitFunctionsByName = {
-- 'box': () => {
--    const {scene, camera} = makeScene();
-+ 'box': (elem) => {
-+    const {scene, camera, controls} = makeScene(elem);
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
--  'pyramid': () => {
--    const {scene, camera} = makeScene();
-+  'pyramid': (elem) => {
-+    const {scene, camera, controls} = makeScene(elem);
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

オブジェクトをドラッグすると回転するようになりました。

-

- -

-

これらのテクニックはこのサイト自体にも使われています。 -特にプリミティブの記事マテリアルの記事では、このテクニックを使ってページ全体に様々なサンプルを追加しています。

-

もう1つの解決策はオフスクリーンのキャンバスにレンダリングし、各要素で結果を2Dキャンバスにコピーする事です。 -この解決策の利点は、分離した各領域を合成する方法に制限がないです。 -以前の解決策では、背景に単一のキャンバスを使用していました。 -この解決策では通常のHTML要素を使用しています。

-

欠点は、領域ごとにコピーが発生するため遅いという事です。 -どのくらい遅くなるかはブラウザとGPUに依存します。

-

必要な変更は非常に小さいです。

-

まず、ページ内にキャンバスが不要になったのでHTMLを変更します。

-
<body>
--  <canvas id="c"></canvas>
-  ...
-</body>
-
-

CSSも変更します。

-
-#c {
--  position: absolute;
--  left: 0;
--  top: 0;
--  width: 100%;
--  height: 100%;
--  display: block;
--  z-index: -1;
--}
-canvas {
-  width: 100%;
-  height: 100%;
-  display: block;
-}
-*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-

全てのキャンバスは作成し、コンテナとなる変数に格納する形にします。

-

では、JavaScriptを変更してみましょう。 -もはやキャンバスを探す事は不要になりました。 -代わりに私たちは1つのキャンバスを作ります。 -また、最初にシザーテストをONにします。

-
function main() {
--  const canvas = document.querySelector('#c');
-+  const canvas = document.createElement('canvas');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas, alpha: true});
-+  renderer.setScissorTest(true);
-
-  ...
-
-

次に各シーンに対して2Dレンダリングのコンテキストを作成し、そのシーンの要素にキャンバスを追加します。

-
const sceneElements = [];
-function addScene(elem, fn) {
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  elem.appendChild(ctx.canvas);
--  sceneElements.push({elem, fn});
-+  sceneElements.push({elem, ctx, fn});
-}
-
-

レンダリング時に、レンダラーのキャンバスがレンダリングするのに十分な大きさでない場合はサイズを大きくします。 -また、キャンバスのサイズが間違っている場合はそのサイズを変更します。 -最後にシザーとビューポートを設定し、シーンをレンダリングしその結果をキャンバスにコピーします。

-
function render(time) {
-  time *= 0.001;
-
--  resizeRendererToDisplaySize(renderer);
--
--  renderer.setScissorTest(false);
--  renderer.setClearColor(clearColor, 0);
--  renderer.clear(true, true);
--  renderer.setScissorTest(true);
--
--  const transform = `translateY(${window.scrollY}px)`;
--  renderer.domElement.style.transform = transform;
-
--  for (const {elem, fn} of sceneElements) {
-+  for (const {elem, fn, ctx} of sceneElements) {
-    // get the viewport relative position of this element
-    const rect = elem.getBoundingClientRect();
-    const {left, right, top, bottom, width, height} = rect;
-+    const rendererCanvas = renderer.domElement;
-
-    const isOffscreen =
-        bottom < 0 ||
--        top > renderer.domElement.clientHeight ||
-+        top > window.innerHeight ||
-        right < 0 ||
--        left > renderer.domElement.clientWidth;
-+        left > window.innerWidth;
-
-    if (!isOffscreen) {
--      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
--      renderer.setScissor(left, positiveYUpBottom, width, height);
--      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-+      // make sure the renderer's canvas is big enough
-+      if (rendererCanvas.width < width || rendererCanvas.height < height) {
-+        renderer.setSize(width, height, false);
-+      }
-+
-+      // make sure the canvas for this area is the same size as the area
-+      if (ctx.canvas.width !== width || ctx.canvas.height !== height) {
-+        ctx.canvas.width = width;
-+        ctx.canvas.height = height;
-+      }
-+
-+      renderer.setScissor(0, 0, width, height);
-+      renderer.setViewport(0, 0, width, height);
-
-      fn(time, rect);
-
-+      // copy the rendered scene to this element's canvas
-+      ctx.globalCompositeOperation = 'copy';
-+      ctx.drawImage(
-+          rendererCanvas,
-+          0, rendererCanvas.height - height, width, height,  // src rect
-+          0, 0, width, height);                              // dst rect
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

結果は同じように見えます。

-

- -

-

この解決策のもう1つの利点は、Web workerでレンダリングするためにOffscreenCanvasのテクニックも使用しています。 -残念ながら2020年7月現在、OffscreenCanvas はChromeのみの対応となっています。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/offscreencanvas.html b/manual/ja/offscreencanvas.html deleted file mode 100644 index cd1d363e2276d2..00000000000000 --- a/manual/ja/offscreencanvas.html +++ /dev/null @@ -1,1040 +0,0 @@ - - - のOffscreenCanvas - - - - - - - - - - - - - -
-
-

のOffscreenCanvas

-
-
-
-

OffscreenCanvasは新しいブラウザの機能で現在はChromeでしか利用できませんが、他のブラウザにも来るようです。 -OffscreenCanvas はWeb Workerでキャンバスにレンダリングできます。 -複雑な3Dシーンのレンダリングなど重い作業をWeb Workerで行い負荷を軽減させ、ブラウザのレスポンスを低下させない方法です。 -また、データが読み込まれWorkerで解析されてるのでページ読み込み中にページ表示の途切れは少ないでしょう。

-

OffscreenCanvasの利用を開始するのは非常に簡単です。 -レスポンシブデザインの記事から3つのキューブを回転させるコードに修正してみましょう。

-

通常はWorkerのコードを別ファイルに分離しますが、このサイトのほとんどのサンプルコードではスクリプトをHTMLファイルに埋め込んでいます。

-

ここでは offscreencanvas-cubes.js というファイルを作成し、レスポンシブデザインの例から全てのJavaScriptをコピーして下さい。 -そして、Workerで実行するために必要な変更を行います。

-

HTMLファイルにはJavaScriptのいくつかの処理が必要です。 -まず最初に行う必要があるのはキャンバスを検索し、canvas.transferControlToOffscreen 呼び出してキャンバスのコントロールをオフスクリーンに転送します。

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-
-  ...
-
-

new Worker(pathToScript, {type: 'module'})でWorkerを起動し、offscreen オブジェクトを渡します。

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-cubes.js', {type: 'module'});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-}
-main();
-
-

ここで重要なのはWorkerが DOM にアクセスできない事です。 -HTML要素の参照やマウスイベントやキーボードイベントを受け取る事もできません。 -Workerは、送られたメッセージに返信してWebページにメッセージを送り返す事だけです。

-

Workerにメッセージを送信するにはworker.postMessageを呼び出し、1つまたは2つの引数を渡します。 -1つ目の引数はクローンされるJavaScriptオブジェクトでWorkerに送ります。 -2番目の引数は任意でWorkerに 転送 したい最初のオブジェクトです。 -このオブジェクトはクローンされません。 -その代わりに 転送 され、メインページには存在しなくなります。 -存在しなくなるというのはおそらく間違った説明であり、むしろ取り除かれます。 -クローンではなく、特定のタイプのオブジェクトのみを転送する事ができます。 -転送するオブジェクトには OffscreenCanvas が含まれているので、1度転送した offscreen オブジェクトをメインページに戻しても意味がありません。

-

Workerは onmessage ハンドラからメッセージを受け取ります。 -postMessage に渡したオブジェクトはWorkerの onmessage ハンドラに渡され event.data を更新します。 -上記のコードではWorkerに渡すオブジェクトに type: 'main' を宣言しています。 -このオブジェクトはブラウザには何の意味もありません。Workerで使うためだけのものです。 -type に基づいて、Worker内で別の関数を呼び出すハンドラを作成します。 -あとは必要に応じて関数を追加し、メインページから簡単に呼び出す事ができます。

-
const handlers = {
-  main,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

上記コードのように type に基づいてハンドラを検索し、メインページから送られてきた data を渡します。 -あとはレスポンシブデザインの記事から offscreencanvas-cubes.js に貼り付けた main を変更するだけです。

-

DOMからキャンバスを探すのではなく、イベントデータからキャンバスを受け取ります。

-
-function main() {
--  const canvas = document.querySelector('#c');
-+function main(data) {
-+  const {canvas} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  ...
-
-

最初の問題はWorkerからDOMを参照できず、resizeRendererToDisplaySizecanvas.clientWidthcanvas.clientHeight を参照できない事です。 -clientWidthcanvas.clientHeight はDOMの値です。

-

元のコードは以下の通りです。

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
-  const width = canvas.clientWidth;
-  const height = canvas.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

DOMを参照できないため、変更したサイズの値をWorkerに送る必要があります。 -そこでグローバルな状態を追加し、幅と高さを維持するようにしましょう。

-
const state = {
-  width: 300,  // canvas default
-  height: 150,  // canvas default
-};
-
-

これらの値を更新するための 'size' ハンドラを追加してみます。

-
+function size(data) {
-+  state.width = data.width;
-+  state.height = data.height;
-+}
-
-const handlers = {
-  main,
-+  size,
-};
-
-

これで resizeRendererToDisplaySize を変更すると state.widthstate.height が使えるようになりました。

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = canvas.clientWidth;
--  const height = canvas.clientHeight;
-+  const width = state.width;
-+  const height = state.height;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

以下も同様の変更が必要です。

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.aspect = state.width / state.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

メインページに戻りページのリサイズの度に size イベントを送信します。

-
const worker = new Worker('offscreencanvas-picking.js', {type: 'module'});
-worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-+function sendSize() {
-+  worker.postMessage({
-+    type: 'size',
-+    width: canvas.clientWidth,
-+    height: canvas.clientHeight,
-+  });
-+}
-+
-+window.addEventListener('resize', sendSize);
-+sendSize();
-
-

初期サイズを送るために1度sendSizeを呼んでいます。

-

ブラウザが OffscreenCanvas を完全にサポートしていると仮定して、これらの変更を行うだけで動作するはずです。 -実行する前にブラウザが OffscreenCanvas を実際にサポートしているか確認し、サポートしていない場合はエラーを表示してみましょう。 -まずはエラーを表示するためのHTMLを追加します。

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="noOffscreenCanvas" style="display:none;">
-+    <div>no OffscreenCanvas support</div>
-+  </div>
-</body>
-
-

そして、CSSを追加します。

-
#noOffscreenCanvas {
-    display: flex;
-    width: 100vw;
-    height: 100vh;
-    align-items: center;
-    justify-content: center;
-    background: red;
-    color: white;
-}
-
-

ブラウザが OffscreenCanvas をサポートしているか確認するためには transferControlToOffscreen を呼びます。

-
function main() {
-  const canvas = document.querySelector('#c');
-+  if (!canvas.transferControlToOffscreen) {
-+    canvas.style.display = 'none';
-+    document.querySelector('#noOffscreenCanvas').style.display = '';
-+    return;
-+  }
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-picking.js', {type: 'module});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-  ...
-
-

ブラウザが OffscreenCanvas をサポートしていれば、このサンプルは動作するはずです。

-

- -

-

これは素晴らしい事ですが、今の所は全てのブラウザが OffscreenCanvas をサポートしている訳ではなく、 -OffscreenCanvas サポートありとサポートなしの両方で動作するコードに変更し、サポートなしの場合はメインページのキャンバスを通常のように表示します。

-
-

余談ですがページをレスポンシブにするためにOffscreenCanvasが必要な場合、フォールバックを持つ意味がよくわかりません。 -メインページで実行するかWorkerで実行するかには、Workerで実行している時にメインページで実行している時よりも多くの事ができるように -調整するかもしれません。何をするかは本当にあなた次第です。

-
-

まず最初にthree.jsのコードとWorkerの固有コードを分離しましょう。 -これでメインページとWorkerの両方で同じコードを使う事ができます。 -つまり、3つのファイルを持つ事になります。

-
    -
  1. htmlファイル

    -

    threejs-offscreencanvas-w-fallback.html

    -
  2. -
  3. three.jsを含むJavaScriptコード

    -

    shared-cubes.js

    -
  4. -
  5. workerをサポートするコード

    -

    offscreencanvas-worker-cubes.js

    -
  6. -
-

shared-cubes.jsoffscreencanvas-worker-cubes.js は前の offscreencanvas-cubes.js ファイルを分割したものです。

-

まず offscreencanvas-cubes.js を全て shared-cube.js にコピーします。 -次にHTMLファイルには既に main があり、initstate をエクスポートする必要があるため main の名前を init に変更します。

-
import * as THREE from 'three';
-
--const state = {
-+export const state = {
-  width: 300,   // canvas default
-  height: 150,  // canvas default
-};
-
--function main(data) {
-+export function init(data) {
-  const {canvas} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-

そして、three.js関連以外の部分だけを切り取ります。

-
-function size(data) {
--  state.width = data.width;
--  state.height = data.height;
--}
--
--const handlers = {
--  main,
--  size,
--};
--
--self.onmessage = function(e) {
--  const fn = handlers[e.data.type];
--  if (typeof fn !== 'function') {
--    throw new Error('no handler for type: ' + e.data.type);
--  }
--  fn(e.data);
--};
-
-

削除した部分を offscreencanvas-worker-cubes.js にコピーして shared-cubes.js をインポートし、main の代わりに init を呼び出します。

-
import {init, state} from './shared-cubes.js';
-
-function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-const handlers = {
--  main,
-+  init,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

同様にメインページに shared-cubes.js を含める必要があります。

-
<script type="module">
-+import {init, state} from './shared-cubes.js';
-
-

前に追加したHTMLとCSSを削除します。

-
<body>
-  <canvas id="c"></canvas>
--  <div id="noOffscreenCanvas" style="display:none;">
--    <div>no OffscreenCanvas support</div>
--  </div>
-</body>
-
-

そして、CSSは以下のようになります。

-
-#noOffscreenCanvas {
--    display: flex;
--    width: 100vw;
--    height: 100vh;
--    align-items: center;
--    justify-content: center;
--    background: red;
--    color: white;
--}
-
-

次にブラウザが OffscreenCanvas をサポートありなしに応じて、メインページのコードを変更して起動関数を呼び出すようにしてみましょう。

-
function main() {
-  const canvas = document.querySelector('#c');
--  if (!canvas.transferControlToOffscreen) {
--    canvas.style.display = 'none';
--    document.querySelector('#noOffscreenCanvas').style.display = '';
--    return;
--  }
--  const offscreen = canvas.transferControlToOffscreen();
--  const worker = new Worker('offscreencanvas-picking.js', {type: 'module'});
--  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-+  if (canvas.transferControlToOffscreen) {
-+    startWorker(canvas);
-+  } else {
-+    startMainPage(canvas);
-+  }
-  ...
-
-

Workerのセットアップコードを全て startWorker の中に移動します。

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-cubes.js', {type: 'module'});
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');
-}
-
-

そして main の代わりに init を送信します。

-
-  worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]);
-+  worker.postMessage({type: 'init', canvas: offscreen}, [offscreen]);
-
-

メインページで開始するには次のようにします。

-
function startMainPage(canvas) {
-  init({canvas});
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');
-}
-
-

このサンプルコードではOffscreenCanvasで実行、またはメインページで実行されるようにフォールバックしています。

-

- -

-

比較的簡単でした。ピッキングしてみましょう。 -ピッキングの記事にある RayCaster の例からコードをいくつか取り出し、画面外でオフスクリーンが動作するようにします。

-

shared-cube.jsshared-picking.js にコピーし、ピッキング部分を追加してみましょう。 -この例では PickHelper をコピーします。

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // restore the color if there is a picked object
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // cast a ray through the frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // get the list of objects the ray intersected
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // pick the first object. It's the closest one
-      this.pickedObject = intersectedObjects[0].object;
-      // save its color
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // set its emissive color to flashing red/yellow
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-const pickPosition = {x: 0, y: 0};
-const pickHelper = new PickHelper();
-
-

マウスの pickPosition を以下のように更新しました。

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // note we flip Y
-}
-window.addEventListener('mousemove', setPickPosition);
-
-

Workerではマウスの位置を直接読み取れないので、サイズのコードと同じようにマウスの位置を指定してメッセージを送信してみましょう。 -サイズのコードと同様にマウスの位置を送信して pickPosition を更新します。

-
function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-+function mouse(data) {
-+  pickPosition.x = data.x;
-+  pickPosition.y = data.y;
-+}
-
-const handlers = {
-  init,
-+  mouse,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

メインページに戻ってマウスをWorkerやメインページに渡すコードを追加します。

-
+let sendMouse;
-
-function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-picking.js', {type: 'module'});
-  worker.postMessage({type: 'init', canvas: offscreen}, [offscreen]);
-
-+  sendMouse = (x, y) => {
-+    worker.postMessage({
-+      type: 'mouse',
-+      x,
-+      y,
-+    });
-+  };
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-function startMainPage(canvas) {
-  init({canvas});
-
-+  sendMouse = (x, y) => {
-+    pickPosition.x = x;
-+    pickPosition.y = y;
-+  };
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');  /* eslint-disable-line no-console */
-}
-
-

全てのマウス操作コードをメインページにコピーし、sendMouse を使用するようにマイナーチェンジを加えます。

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // note we flip Y
-+  sendMouse(
-+      (pos.x / canvas.clientWidth ) *  2 - 1,
-+      (pos.y / canvas.clientHeight) * -2 + 1);  // note we flip Y
-}
-
-function clearPickPosition() {
-  // unlike the mouse which always has a position
-  // if the user stops touching the screen we want
-  // to stop picking. For now we just pick a value
-  // unlikely to pick something
--  pickPosition.x = -100000;
--  pickPosition.y = -100000;
-+  sendMouse(-100000, -100000);
-}
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-window.addEventListener('touchstart', (event) => {
-  // prevent the window from scrolling
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

これでこのピッキングは OffscreenCanvas で動作するはずです。

-

- -

-

もう1歩踏み込んで OrbitControls を追加してみましょう。 -これはもう少し複雑です。 -OrbitControls はマウス、タッチイベント、キーボードなどDOMをかなり広範囲にチェックしています。

-

これまでのコードとは異なり、グローバルな state オブジェクトを使う事はできません。 -これを使用して動作するようにOrbitControlsのコードを全て書き換える必要はありません。 -OrbitControlsは HTMLElement を取り、それに使用するDOMイベントのほとんどをアタッチします。 -OrbitControlsが必要とする機能をサポートする必要があります。

-

OrbitControlsのソースコードを掘り下げてみると、次のイベントを処理する必要があるように見えます。

-
    -
  • contextmenu
  • -
  • pointerdown
  • -
  • pointermove
  • -
  • pointerup
  • -
  • touchstart
  • -
  • touchmove
  • -
  • touchend
  • -
  • wheel
  • -
  • keydown
  • -
-

マウスイベントには ctrlKeymetaKeyshiftKeybuttonpointerTypeclientXclientYpageXpageY プロパティが必要です。

-

キーダウンイベントには ctrlKey, metaKey, shiftKey, keyCode プロパティが必要です。

-

ホイールイベントに必要なのは deltaY プロパティだけです。

-

また、タッチイベントに必要なのは touches プロパティの pageXpageY だけです。

-

そこでproxyオブジェクトのペアを作ってみましょう。 -ある時はメインページで実行され、全てのイベント、関連するプロパティ値をWorkerに渡します。 -また、ある時はWorkerで実行され、全てのイベント、DOMイベントと同じ構造をもつイベントをメインページに渡すので、OrbitControlsは違いを見分けられません。

-

ここにWorker部分のコードがあります。

-
import {EventDispatcher} from 'three';
-
-class ElementProxyReceiver extends EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-}
-
-

メッセージを受信した場合にdataを送信するだけです。 -これは EventDispatcher を継承しており、DOM要素のように addEventListenerremoveEventListener のようなメソッドを提供しているので、OrbitControlsに渡せば動作するはずです。

-

ElementProxyReceiver は1つの要素を扱います。 -私たちの場合は1つの頭しか必要ありませんが、頭で考えるのがベストです。 -つまり、マネージャーを作って複数のElementProxyReceiverを管理するようにしましょう。

-
class ProxyManager {
-  constructor() {
-    this.targets = {};
-    this.handleEvent = this.handleEvent.bind(this);
-  }
-  makeProxy(data) {
-    const {id} = data;
-    const proxy = new ElementProxyReceiver();
-    this.targets[id] = proxy;
-  }
-  getProxy(id) {
-    return this.targets[id];
-  }
-  handleEvent(data) {
-    this.targets[data.id].handleEvent(data.data);
-  }
-}
-
-

ProxyManagerのインスタンスを作成し makeProxy メソッドにidを指定して呼び出す事で、そのidを持つメッセージに応答する ElementProxyReceiver を作成できます。

-

Workerのメッセージハンドラに接続してみましょう。

-
const proxyManager = new ProxyManager();
-
-function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-function makeProxy(data) {
-  proxyManager.makeProxy(data);
-}
-
-...
-
-const handlers = {
--  init,
--  mouse,
-+  start,
-+  makeProxy,
-+  event: proxyManager.handleEvent,
-   size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

共有のthree.jsコードでは OrbitControls をインポートして設定する必要があります。

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-export function init(data) {
--  const {canvas} = data;
-+  const {canvas, inputElement} = data;
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-+  const controls = new OrbitControls(camera, inputElement);
-+  controls.target.set(0, 0, 0);
-+  controls.update();
-
-

OffscreenCanvas以外のサンプルコード例のようにキャンバスを渡すのではなく、 -inputElement を介してOrbitControlsをProxyに渡している事に注目して下さい。

-

次に canvasinputElement に変更し、HTMLファイルから全てのピッキングイベントのコードを共有のthree.jsコードに移動させます。

-
function getCanvasRelativePosition(event) {
--  const rect = canvas.getBoundingClientRect();
-+  const rect = inputElement.getBoundingClientRect();
-  return {
-    x: event.clientX - rect.left,
-    y: event.clientY - rect.top,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  sendMouse(
--      (pos.x / canvas.clientWidth ) *  2 - 1,
--      (pos.y / canvas.clientHeight) * -2 + 1);  // note we flip Y
-+  pickPosition.x = (pos.x / inputElement.clientWidth ) *  2 - 1;
-+  pickPosition.y = (pos.y / inputElement.clientHeight) * -2 + 1;  // note we flip Y
-}
-
-function clearPickPosition() {
-  // unlike the mouse which always has a position
-  // if the user stops touching the screen we want
-  // to stop picking. For now we just pick a value
-  // unlikely to pick something
--  sendMouse(-100000, -100000);
-+  pickPosition.x = -100000;
-+  pickPosition.y = -100000;
-}
-
-*inputElement.addEventListener('mousemove', setPickPosition);
-*inputElement.addEventListener('mouseout', clearPickPosition);
-*inputElement.addEventListener('mouseleave', clearPickPosition);
-
-*inputElement.addEventListener('touchstart', (event) => {
-  // prevent the window from scrolling
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-*inputElement.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-*inputElement.addEventListener('touchend', clearPickPosition);
-
-

メインページに戻り、上記で列挙した全てのイベントにメッセージを送信するコードが必要です。

-
let nextProxyId = 0;
-class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // register an id
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-  }
-}
-
-

ElementProxy はProxyしたいイベントの要素を受け取ります。 -次にWorkerにidを登録し、先ほど設定した makeProxy メッセージを使って送信します。 -Workerは ElementProxyReceiver を作成しそのidに登録します。

-

そして登録するイベントハンドラのオブジェクトを用意します。 -このようにして、Workerに転送したいイベントにハンドラを渡す事ができます。

-

Workerを起動する時はまずProxyを作成しイベントハンドラを渡します。

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-orbitcontrols.js', {type: 'module'});
-
-+  const eventHandlers = {
-+    contextmenu: preventDefaultHandler,
-+    mousedown: mouseEventHandler,
-+    mousemove: mouseEventHandler,
-+    mouseup: mouseEventHandler,
-+    pointerdown: mouseEventHandler,
-+    pointermove: mouseEventHandler,
-+    pointerup: mouseEventHandler,
-+    touchstart: touchEventHandler,
-+    touchmove: touchEventHandler,
-+    touchend: touchEventHandler,
-+    wheel: wheelEventHandler,
-+    keydown: filteredKeydownEventHandler,
-+  };
-+  const proxy = new ElementProxy(canvas, worker, eventHandlers);
-  worker.postMessage({
-    type: 'start',
-    canvas: offscreen,
-+    canvasId: proxy.id,
-  }, [offscreen]);
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-

以下はイベントハンドラです。 -受信したイベントからプロパティのリストをコピーするだけです。 -sendEvent 関数に渡され作成したデータを渡します。 -この関数は正しいidを追加してWorkerに送信します。

-
const mouseEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'button',
-  'pointerType',
-  'clientX',
-  'clientY',
-  'pointerId',
-  'pageX',
-  'pageY',
-]);
-const wheelEventHandlerImpl = makeSendPropertiesHandler([
-  'deltaX',
-  'deltaY',
-]);
-const keydownEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'keyCode',
-]);
-
-function wheelEventHandler(event, sendFn) {
-  event.preventDefault();
-  wheelEventHandlerImpl(event, sendFn);
-}
-
-function preventDefaultHandler(event) {
-  event.preventDefault();
-}
-
-function copyProperties(src, properties, dst) {
-  for (const name of properties) {
-      dst[name] = src[name];
-  }
-}
-
-function makeSendPropertiesHandler(properties) {
-  return function sendProperties(event, sendFn) {
-    const data = {type: event.type};
-    copyProperties(event, properties, data);
-    sendFn(data);
-  };
-}
-
-function touchEventHandler(event, sendFn) {
-  // preventDefault() fixes mousemove, mouseup and mousedown 
-  // firing when doing a simple touchup touchdown
-  // Happens only at offscreen canvas
-  event.preventDefault(); 
-  const touches = [];
-  const data = {type: event.type, touches};
-  for (let i = 0; i < event.touches.length; ++i) {
-    const touch = event.touches[i];
-    touches.push({
-      pageX: touch.pageX,
-      pageY: touch.pageY,
-      clientX: touch.clientX,
-      clientY: touch.clientY,
-    });
-  }
-  sendFn(data);
-}
-
-// The four arrow keys
-const orbitKeys = {
-  '37': true,  // left
-  '38': true,  // up
-  '39': true,  // right
-  '40': true,  // down
-};
-function filteredKeydownEventHandler(event, sendFn) {
-  const {keyCode} = event;
-  if (orbitKeys[keyCode]) {
-    event.preventDefault();
-    keydownEventHandler(event, sendFn);
-  }
-}
-
-

これで動くと思われるが、実際に試してみると OrbitControls がもう少し必要なものがあると分かります。

-

1つは element.focus です。Workerには必要ないのでStubを追加しておきましょう。

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-+  focus() {
-+    // no-op
-+  }
-}
-
-

もう1つは event.preventDefaultevent.stopPropagation を呼び出す事です。 -メインページでは既に対応してるのでそれらも不要になります。

-
+function noop() {
-+}
-
-class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-+    data.preventDefault = noop;
-+    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // no-op
-  }
-}
-
-

もう1つは clientWidthclientHeight を見る事です。 -以前はサイズを渡してましたが、Proxyペアを更新してそれも渡すようにします。

-

Workerの中では

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-+  get clientWidth() {
-+    return this.width;
-+  }
-+  get clientHeight() {
-+    return this.height;
-+  }
-+  getBoundingClientRect() {
-+    return {
-+      left: this.left,
-+      top: this.top,
-+      width: this.width,
-+      height: this.height,
-+      right: this.left + this.width,
-+      bottom: this.top + this.height,
-+    };
-+  }
-  handleEvent(data) {
-+    if (data.type === 'size') {
-+      this.left = data.left;
-+      this.top = data.top;
-+      this.width = data.width;
-+      this.height = data.height;
-+      return;
-+    }
-    data.preventDefault = noop;
-    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // no-op
-  }
-}
-
-

メインページに戻るにはサイズと左と上の位置も送信する必要があります。 -このままではキャンバスを移動しても処理されず、サイズを変更しても処理されないです。 -移動を処理したい場合は何かがキャンバスを移動する度に sendSize を呼び出す必要があります。

-
class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // register an id
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-+    sendSize();
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-
-+    function sendSize() {
-+      const rect = element.getBoundingClientRect();
-+      sendEvent({
-+        type: 'size',
-+        left: rect.left,
-+        top: rect.top,
-+        width: element.clientWidth,
-+        height: element.clientHeight,
-+      });
-+    }
-+
-+    window.addEventListener('resize', sendSize);
-  }
-}
-
-

そして共有のthree.jsコードでは state は不要になりました。

-
-export const state = {
--  width: 300,   // canvas default
--  height: 150,  // canvas default
--};
-
-...
-
-function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = state.width;
--  const height = state.height;
-+  const width = inputElement.clientWidth;
-+  const height = inputElement.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = state.width / state.height;
-+    camera.aspect = inputElement.clientWidth / inputElement.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

他にもいくつかのハックがあります。 -OrbitControlsは pointermovepointerup イベントをマウスキャプチャ(マウスがウィンドウの外に出た時)を処理するための要素の ownerDocument です。

-

さらにコードはグローバルな document を参照していますが、Workerにはグローバルなdocumentはありません。

-

これは2つの簡単なハックで全て解決できます。 -Workerコードでは両方の問題に対してProxyを再利用します。

-
function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-+  proxy.ownerDocument = proxy; // HACK!
-+  self.document = {} // HACK!
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-

これで OrbitControls が期待に沿った検査を行うための機能を提供します。

-

難しいのは分かっていますが手短に言うと:

-

ElementProxy はメインページ上で動作し、DOMイベントを転送します。 -Worker内の ElementProxyReceiver は一緒に使うことができる HTMLElement を装っています。 -OrbitControls と独自のコードを使用しています。

-

最後にOffscreenCanvasを使用していない時のフォールバックです。 -必要なのはcanvas自体を inputElement として渡す事です。

-
function startMainPage(canvas) {
--  init({canvas});
-+  init({canvas, inputElement: canvas});
-  console.log('using regular canvas');
-}
-
-

これでOrbitControlsがOffscreenCanvasで動作するようになりました。

-

- -

-

これはおそらくこのサイトで最も複雑な例です。 -各サンプルには3つのファイルが含まれているので少しわかりにくいです。 -HTMLファイル、Workerファイル、共有のthree.jsコードなどです。

-

理解する事が難し過ぎず、少しでも参考になれば幸いです。 -three.js、OffscreenCanvas、Web Workerを使った動作の便利な例を紹介しました。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/optimize-lots-of-objects-animated.html b/manual/ja/optimize-lots-of-objects-animated.html deleted file mode 100644 index d8f7a490d29a7e..00000000000000 --- a/manual/ja/optimize-lots-of-objects-animated.html +++ /dev/null @@ -1,452 +0,0 @@ - - - でアニメーションする多くのオブジェクトを最適化 - - - - - - - - - - - - - -
-
-

でアニメーションする多くのオブジェクトを最適化

-
-
-
-

この記事は多くのオブジェクトを最適化の続きです。まだ読んでいない場合は先に読んでみて下さい。

-

前回の記事では約19000個のキューブを単体のジオメトリにマージしました。 -19000個のキューブの描画を最適化する利点がありましたが、個々のキューブを動かすのが難しくなる欠点がありました。

-

何を達成するかによって様々な解決策があります。 -今回は複数のデータセットをグラフ化し、そのデータセットでクロスフェードアニメーションさせてみましょう。

-

まず、複数のデータセットを取得する必要があります。 -オフラインでデータの前処理をするのが理想的ですが、今回は2つのデータセットをロードしてさらに2つのデータを生成してみましょう。

-

以下は古いデータロードのコードです。

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(addBoxes)
-  .then(render);
-
-

このような感じに変更してみましょう。

-
async function loadData(info) {
-  const text = await loadFile(info.url);
-  info.file = parseData(text);
-}
-
-async function loadAll() {
-  const fileInfos = [
-    {name: 'men',   hueRange: [0.7, 0.3], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc' },
-    {name: 'women', hueRange: [0.9, 1.1], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014ft_2010_cntm_1_deg.asc' },
-  ];
-
-  await Promise.all(fileInfos.map(loadData));
-
-  ...
-}
-loadAll();
-
-

上記のコードでは fileInfos 内の各オブジェクトがローティングされたファイルを file プロパティに持ち、Promise.allで全てのファイルをロードします。 -namehueRange プロパティはあとで使います。name はUIフィールドです。hueRange は色相の範囲をマップし選択するために使います。

-

上記2ファイルは2010年時点でのエリア別の男性数と女性数を示しています。

-

注:このデータが正しいかわかりませんが、それは重要ではありません。 -重要なのは異なるデータセットを示す事です。

-

さらに2つのデータセットを生成してみましょう。 -1つは女性数よりも男性数が多い場所、逆にもう1つは男性数より女性数が多い場所です。

-

まず先ほどのデータで新しい2次元配列をマップする前に、2次元配列を生成する関数を書いてみましょう。

-
function mapValues(data, fn) {
-  return data.map((row, rowNdx) => {
-    return row.map((value, colNdx) => {
-      return fn(value, rowNdx, colNdx);
-    });
-  });
-}
-
-

通常の Array.map 関数と同様に mapValues 関数は配列の各値に対して関数 fn を呼び出します。 -fnには値と行と列のインデックスを渡します。

-

2つのファイルを比較した新しいファイルを生成するコードを作成します。

-
function makeDiffFile(baseFile, otherFile, compareFn) {
-  let min;
-  let max;
-  const baseData = baseFile.data;
-  const otherData = otherFile.data;
-  const data = mapValues(baseData, (base, rowNdx, colNdx) => {
-    const other = otherData[rowNdx][colNdx];
-      if (base === undefined || other === undefined) {
-        return undefined;
-      }
-      const value = compareFn(base, other);
-      min = Math.min(min === undefined ? value : min, value);
-      max = Math.max(max === undefined ? value : max, value);
-      return value;
-  });
-  // make a copy of baseFile and replace min, max, and data
-  // with the new data
-  return {...baseFile, min, max, data};
-}
-
-

上記のコードは compareFn 関数で比較された値を元に mapValues 関数で新しいデータセットを生成しています。また minmax の比較結果も持っています。 -最後のreturnで新しく minmaxdata を追加した以外は baseFile と同じプロパティを持つ新しいファイルを作成します。

-

それを使って2つの新しいデータセットを作りましょう。

-
{
-  const menInfo = fileInfos[0];
-  const womenInfo = fileInfos[1];
-  const menFile = menInfo.file;
-  const womenFile = womenInfo.file;
-
-  function amountGreaterThan(a, b) {
-    return Math.max(a - b, 0);
-  }
-  fileInfos.push({
-    name: '>50%men',
-    hueRange: [0.6, 1.1],
-    file: makeDiffFile(menFile, womenFile, (men, women) => {
-      return amountGreaterThan(men, women);
-    }),
-  });
-  fileInfos.push({
-    name: '>50% women',
-    hueRange: [0.0, 0.4],
-    file: makeDiffFile(womenFile, menFile, (women, men) => {
-      return amountGreaterThan(women, men);
-    }),
-  });
-}
-
-

これらのデータセットを選択するUIを生成しましょう。まず、いくつかのhtmlのUIが必要です。

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui"></div>
-</body>
-
-

次に左上のエリアに表示するためにCSSを追加しました。

-
#ui {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-}
-#ui>div {
-  font-size: 20pt;
-  padding: 1em;
-  display: inline-block;
-}
-#ui>div.selected {
-  color: red;
-}
-
-

各ファイルを調べてデータセットごとにマージされたボックスのセットを生成します。 -これでラベル上にマウスカーソルを置くとそのデータセットを表示し、他の全てのデータセットを非表示にするラベルUIを生成できます。

-
// show the selected data, hide the rest
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
-    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-  });
-  requestRenderIfNotRequested();
-}
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
-  const boxes = addBoxes(info.file, info.hueRange);
-  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  div.addEventListener('mouseover', () => {
-    showFileInfo(fileInfos, info);
-  });
-});
-// show the first set of data
-showFileInfo(fileInfos, fileInfos[0]);
-
-

もう1つ変更が必要で addBoxes の引数に hueRange があります。

-
-function addBoxes(file) {
-+function addBoxes(file, hueRange) {
-
-  ...
-
-    // compute a color
--    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const hue = THREE.MathUtils.lerp(...hueRange, amount);
-
-  ...
-
-

これで4つのデータセットを表示できるようになるはずです。ラベルの上にマウスを置いたり、タッチしてデータセットを切り替える事ができます。

-

- -

-

注意してほしいのは突出したいくつかの奇妙なデータポイントがあります。

-

これは何が起きてるのでしょう!?

-

いずれにしてもこの4つのデータセットをラベルから切り替えた際にクロスフェードアニメーションさせるにはどうすればいいのでしょうか。

-

たくさんのアイデアがあります。

-
    -
  • Material.opacity でクロスフェードアニメーションする

    -

    この解決策の問題点はキューブが完全に重なっているため、Z軸の戦いの問題を意味します。 -depth関数とブレンディングを使い修正できる可能性があります。調べてみた方が良さそうですね。

    -
  • -
  • 見たいデータセットをスケールアップして他のデータセットをスケールダウンする

    -

    全てのボックスは惑星の中心に位置しているので、1.0以下に縮小すると惑星の中に沈んでしまいます。 -最初は良いアイデアのように聞こえますが、高さの低いボックスはほとんどすぐに消えてしまい、新しいデータセットが1.0までスケールアップするまで置き換えできません。 -このため、アニメーション遷移があまり気持ち良くありません。派手なカスタムシェーダーで修正できるかもしれません。

    -
  • -
  • モーフターゲットを使用する

    -

    モーフターゲットはジオメトリ内の各頂点に複数の値を与え、それらの中間を モーフ または lerp (線形補間) する方法です。 -モーフターゲットは3Dキャラクターの表情アニメーションに最も一般的に使用されていますがそれだけではありません。

    -
  • -
-

モーフターゲットを使ってみましょう。

-

これまで通りにデータセットごとにジオメトリを作成しますが、それぞれのデータから position を抜き出してモーフターゲットとして使用します。

-

まず addBoxes を変更してマージされたジオメトリを返すだけに変更してみましょう。

-
-function addBoxes(file, hueRange) {
-+function makeBoxes(file, hueRange) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  ...
-
--  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
--      geometries, false);
--  const material = new THREE.MeshBasicMaterial({
--    vertexColors: true,
--  });
--  const mesh = new THREE.Mesh(mergedGeometry, material);
--  scene.add(mesh);
--  return mesh;
-+  return BufferGeometryUtils.mergeGeometries(
-+     geometries, false);
-}
-
-

ここでもう1つやるべき事があります。モーフターゲットは全ての頂点数が全く同じである必要があります。 -あるターゲットの頂点#123は、他の全てのターゲットに対応する頂点#123を持つ必要があります。 -しかし、異なるデータセットにはデータのないデータポイントがあるかもしれないので、 -そのポイントに対してはボックスが生成されず、別のデータセットに対応する頂点も生成されません。

-

そこで全てのデータセットをチェックし、どのセットにもデータがある場合は常に何かを生成するか、 -またはどのセットにもデータがない場合は何も生成しないかのどちらかを選択する必要があります。後者をやってみましょう。

-
+function dataMissingInAnySet(fileInfos, latNdx, lonNdx) {
-+  for (const fileInfo of fileInfos) {
-+    if (fileInfo.file.data[latNdx][lonNdx] === undefined) {
-+      return true;
-+    }
-+  }
-+  return false;
-+}
-
--function makeBoxes(file, hueRange) {
-+function makeBoxes(file, hueRange, fileInfos) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  ...
-
-  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-+      if (dataMissingInAnySet(fileInfos, latNdx, lonNdx)) {
-+        return;
-+      }
-      const amount = (value - min) / range;
-
-  ...
-
-

addBoxes を呼び出していたコードを makeBoxes に変更し、モーフターゲットを設定します。

-
+// make geometry for each data set
-+const geometries = fileInfos.map((info) => {
-+  return makeBoxes(info.file, info.hueRange, fileInfos);
-+});
-+
-+// use the first geometry as the base
-+// and add all the geometries as morphtargets
-+const baseGeometry = geometries[0];
-+baseGeometry.morphAttributes.position = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('position');
-+  const name = `target${ndx}`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+baseGeometry.morphAttributes.color = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('color');
-+  const name = `target${ndx}`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-+});
-+const mesh = new THREE.Mesh(baseGeometry, material);
-+scene.add(mesh);
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
--  const boxes = addBoxes(info.file, info.hueRange);
--  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  function show() {
-    showFileInfo(fileInfos, info);
-  }
-  div.addEventListener('mouseover', show);
-  div.addEventListener('touchstart', show);
-});
-// show the first set of data
-showFileInfo(fileInfos, fileInfos[0]);
-
-

上記では最初のデータセットをベースとしたジオメトリを作成し、各ジオメトリから position を取得し、 -それを position のベースジオメトリにモーフターゲットとして追加します。 -あとはデータセットの表示・非表示の仕方を変える必要があります。 -メッシュを表示・非表示するのではなく、モーフターゲットの影響を変える必要があります。 -見たいデータセットは1の影響を持つ必要があり、見たくないデータセットは0の影響を持つ必要があります。

-

直接0か1にすれば良いのですがそうするとクロスフェードアニメーションが見られなくなり、すでに持っている値に変更がなくスナップします。 -または簡単にカスタムアニメーションのコードを書く事ができますが、 -オリジナルのwebgl globeではアニメーションライブラリを使っているので合わせましょう。

-

アニメーションライブラリをimportする必要があります。

-
import * as THREE from 'three';
-import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import TWEEN from 'three/addons/libs/tween.module.js';
-
-

そして、影響を与えるアニメーションの Tween を作成します。

-
// show the selected data, hide the rest
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
--    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-+    const targets = {};
-+    fileInfos.forEach((info, i) => {
-+      targets[i] = info === fileInfo ? 1 : 0;
-+    });
-+    const durationInMs = 1000;
-+    new TWEEN.Tween(mesh.morphTargetInfluences)
-+      .to(targets, durationInMs)
-+      .start();
-  });
-  requestRenderIfNotRequested();
-}
-
-

レンダリングループ内でフレームごとに TWEEN.update を呼び出しますが問題があります。 -"tween.js"は連続的なレンダリング用に設計されていますが、ここでは要求されたレンダリングをしています。 -連続的なレンダリングに切り替えれますが、何も起きていない時にはレンダリングコストを下げた方が良いため、要求されたレンダリングだけにするのもいいかもしれません。 -これを助けるために TweenManager を作ります。 -TweenManagerは update メソッドを持ち、再度呼び出す必要がある場合は true を返し、全てのアニメーションが終了した場合は false を返します。

-
class TweenManger {
-  constructor() {
-    this.numTweensRunning = 0;
-  }
-  _handleComplete() {
-    --this.numTweensRunning;
-    console.assert(this.numTweensRunning >= 0);
-  }
-  createTween(targetObject) {
-    const self = this;
-    ++this.numTweensRunning;
-    let userCompleteFn = () => {};
-    // create a new tween and install our own onComplete callback
-    const tween = new TWEEN.Tween(targetObject).onComplete(function(...args) {
-      self._handleComplete();
-      userCompleteFn.call(this, ...args);
-    });
-    // replace the tween's onComplete function with our own
-    // so we can call the user's callback if they supply one.
-    tween.onComplete = (fn) => {
-      userCompleteFn = fn;
-      return tween;
-    };
-    return tween;
-  }
-  update() {
-    TWEEN.update();
-    return this.numTweensRunning > 0;
-  }
-}
-
-

TweenMangerを使用するために次のようなコードにします。

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const tweenManager = new TweenManger();
-
-  ...
-
-

TweenMangerを使って Tween を作成します。

-
// show the selected data, hide the rest
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
-    info.elem.className = visible ? 'selected' : '';
-    const targets = {};
-    fileInfos.forEach((info, i) => {
-      targets[i] = info === fileInfo ? 1 : 0;
-    });
-    const durationInMs = 1000;
--    new TWEEN.Tween(mesh.morphTargetInfluences)
-+    tweenManager.createTween(mesh.morphTargetInfluences)
-      .to(targets, durationInMs)
-      .start();
-  });
-  requestRenderIfNotRequested();
-}
-
-

次にtweenManagerを更新するためにレンダーループを修正し、アニメーションが実行されている場合はレンダリングを継続します。

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (tweenManager.update()) {
-+    requestRenderIfNotRequested();
-+  }
-
-  controls.update();
-  renderer.render(scene, camera);
-}
-render();
-
-

そして、データセットでクロスフェードアニメーションを行う必要があります。

-

- -

-

これがお役に立てれば幸いです。 -three.jsが提供するサービスを利用するか、カスタムシェーダーを使ってモーフターゲットを使うのは多くのオブジェクトを移動させるための一般的なテクニックです。 -例として全てのキューブに別の目標を設定し、そこから地球上での最初の位置へと変化します。 -地球儀を紹介するにはかっこいいかもしれません。

-

次はHTML要素を3Dに整列させるで説明している地球儀にラベルを追加します。

-

注: 男性や女性の割合、または正の差をグラフ化する事もできますが、情報を表示する方法に基づいて地表から成長するキューブはほとんどのキューブが低い方が良いでしょう。 -これらの他の比較を使用した場合、ほとんどのキューブは最大高さの約1/2の大きさになり可視化として良くありません。 -amountGreaterThan を変えたように感じますが、このような場合は Math.max(a - b, 0)(a - b) "正の差" や a / (a +b) "パーセント" のようなものに変えると何を言っているのかわかるでしょう。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/optimize-lots-of-objects.html b/manual/ja/optimize-lots-of-objects.html deleted file mode 100644 index 6f64fb6046286e..00000000000000 --- a/manual/ja/optimize-lots-of-objects.html +++ /dev/null @@ -1,467 +0,0 @@ - - - で多くのオブジェクトを最適化 - - - - - - - - - - - - - -
-
-

で多くのオブジェクトを最適化

-
-
-
-

この記事はthree.jsの連載記事の1つです。最初の記事はThree.jsの基礎知識です。まだ読んでいない場合はそこから始めて下さい。

-

three.jsには最適化する方法は多々あります。1つの方法はジオメトリのマージと呼ばれています。メッシュを作成すると描画リクエストを1つ以上行った事を表します。 -2つのメッシュを描画すると結果が同じでも1つのメッシュを描画するよりもオーバーヘッドが大きく、最適化する1つの方法がメッシュのマージです。

-

これが問題解決になるか、例を示してみます。 -WebGL Globeを作り直してみましょう。

-

まずデータが必要です。WebGL Globeで使用しているデータはSEDACです。 -サイトをチェックすると人口統計データのグリッド形式があります。 -私は60分間の解像度データをダウンロードしました。データを見てみると以下のような感じになっています。

-
 ncols         360
- nrows         145
- xllcorner     -180
- yllcorner     -60
- cellsize      0.99999999999994
- NODATA_value  -9999
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- 9.241768 8.790958 2.095345 -9999 0.05114867 -9999 -9999 -9999 -9999 -999...
- 1.287993 0.4395509 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
-
-

キーと値のペアのような行がいくつかあり、その行に続くグリッドポイントごとの値の行があり、データポイントごとに1行ずつ並んでいます。 -データをもっと理解するために2Dでプロットしてみましょう。

-

最初にテキストファイルをロードするコードです。

-
async function loadFile(url) {
-  const res = await fetch(url);
-  return res.text();
-}
-
-

上記のコードは Promise を返しファイルの内容は url にあります。 -次にファイルを解析するコードが必要です。

-
function parseData(text) {
-  const data = [];
-  const settings = {data};
-  let max;
-  let min;
-  // split into lines
-  text.split('\n').forEach((line) => {
-    // split the line by whitespace
-    const parts = line.trim().split(/\s+/);
-    if (parts.length === 2) {
-      // only 2 parts, must be a key/value pair
-      settings[parts[0]] = parseFloat(parts[1]);
-    } else if (parts.length > 2) {
-      // more than 2 parts, must be data
-      const values = parts.map((v) => {
-        const value = parseFloat(v);
-        if (value === settings.NODATA_value) {
-          return undefined;
-        }
-        max = Math.max(max === undefined ? value : max, value);
-        min = Math.min(min === undefined ? value : min, value);
-        return value;
-      });
-      data.push(values);
-    }
-  });
-  return Object.assign(settings, {min, max});
-}
-
-

上記のコードはファイルから全てのキーと値のペアを持つオブジェクトを返します。またdata プロパティには全てのデータを1つの大きな配列にまとめて、データに含まれる minmax の値を返します。

-

次にデータの描画コードが必要です。

-
function drawData(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-  const ctx = document.querySelector('canvas').getContext('2d');
-  // make the canvas the same size as the data
-  ctx.canvas.width = ncols;
-  ctx.canvas.height = nrows;
-  // but display it double size so it's not too small
-  ctx.canvas.style.width = px(ncols * 2);
-  ctx.canvas.style.height = px(nrows * 2);
-  // fill the canvas to dark gray
-  ctx.fillStyle = '#444';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-  // draw each data point
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const hue = 1;
-      const saturation = 1;
-      const lightness = amount;
-      ctx.fillStyle = hsl(hue, saturation, lightness);
-      ctx.fillRect(lonNdx, latNdx, 1, 1);
-    });
-  });
-}
-
-function px(v) {
-  return `${v | 0}px`;
-}
-
-function hsl(h, s, l) {
-  return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
-}
-
-

最後にすべてを統合します。

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(drawData);
-
-

そして、以下のような結果が得られました。

-

- -

-

どうやら上手くいったようです。

-

これを3Dでやってみましょう。 -要求されたレンダリングのコードから始めてファイル内のデータごとに1つのボックスを作ります。

-

まずは世界地図テクスチャで簡単な球体を作ってみましょう。テクスチャはこんな感じです。

-
- -

テクスチャをセットするコードです。

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/world.jpg', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({map: texture});
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

テクスチャ読込後に render を呼び出している部分に注目して下さい。 -renderが必要なのは連続的なレンダリングでなく、要求されたレンダリングなのでテクスチャ読込後に一度レンダリングする必要があるからです。

-

次に上記のデータポイントごとにドット描画するコードをデータポイントごとにボックスを作成するコードに変更する必要があります。

-
function addBoxes(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-
-  // make one box geometry
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-  // make it so it scales away from the positive Z axis
-  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // these helpers will make it easy to position the boxes
-  // We can rotate the lon helper on its Y axis to the longitude
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // We rotate the latHelper on its X axis to the latitude
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // The position helper moves the object to the edge of the sphere
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const material = new THREE.MeshBasicMaterial();
-      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-      const saturation = 1;
-      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
-      material.color.setHSL(hue, saturation, lightness);
-      const mesh = new THREE.Mesh(geometry, material);
-      scene.add(mesh);
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-      // use the world matrix of the position helper to
-      // position this mesh.
-      positionHelper.updateWorldMatrix(true, false);
-      mesh.applyMatrix4(positionHelper.matrixWorld);
-
-      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    });
-  });
-}
-
-

2Dドットの描画コードからほとんどの部分が単純明快なものになっています。

-

1つのボックスを作り、ボックスの中心が正のZから離れるように調整します。これをしないと中心からのスケールになってしまうため、原点から離れるようになってほしいからです。

-
-
-
-
default
-
-
-
-
adjusted
-
-
- -

シーングラフで説明したように、多くの THREE.Object3D オブジェクトでボックスを親にして解決できますが、シーングラフにノードを追加すればするほど遅くなってしまいます。

-

また lonHelperlatHelperpositionHelperという小さなノード階層を設定します。 -これらのオブジェクトを使用し、ボックスを配置する球体の周りの位置を計算します。

-
-
-
- -

上記のgreen barlonHelperlongHelper を表し、赤道上の経度方向に回転させるために使用します。 -blue barlatHelper を表し、赤道上や赤道下の緯度を回転させるために使用します。 -red spherepositionHelper が提供するオフセットを表します。

-

地球儀上の位置の計算を手動で行う事もできますが、ほとんどの計算をライブラリ自体に任せてしまうので処理をする必要がありません。

-

各データポイントに対して MeshBasicMaterialMesh を作成し、positionHelper のワールド座標を求めてそれを新しい Mesh に適用します。 -最後にメッシュを新しい位置で拡大縮小します。

-

上記のように新しいボックスを作成する度に latHelperlonHelperpositionHelper を作成できましたが、それではさらに時間がかかります。

-

これから作るボックスは360 × 145まであります。最大で52000個のボックスです。 -いくつかのデータポイントが "NO_DATA "とマークされているので、実際に作成するボックスの数は約19000個です。 -1ボックスごとに3つのヘルパーオブジェクトを追加した場合、シーングラフのノードが80000個近くになり、THREE.jsはその位置を計算しなければなりません。 -ヘルパーの1つのセットを使用して単にメッシュを使用する事で約60000回の操作を削減できます。

-

また lonFudgelatFudge には注意点があります。lonFudge はπ/2で1/4回転です。 -これは理にかなっています。テクスチャやテクスチャ座標が地球の周りの異なるオフセットから始まる事を意味しているだけです。 -一方、latFudgeについてはなぜπ * -0.135にする必要があるのか私にはわかりません。

-

最後に行う必要があるのはローダーの呼出です。

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
--  .then(drawData)
-+  .then(addBoxes)
-+  .then(render);
-

データ読込と解析が終わったら、少なくとも一度は要求されたレンダリングをする必要があります。

-

- -

-

上記のサンプルをドラッグして回転させようとすると遅い事に気づくでしょう。

-

devtoolsを開いてFPS meterをオンにする事でFPSを確認できます。

-
- -

私のマシンでは20fps以下のFPSが表示されています。

-
- -

FPSの遅延はあまり好ましくなく、多くの人々がさらにFPSが遅くなるマシンを持っているのではないでしょうか。最適化を検討した方がいいですね。

-

このFPS遅延の問題解決では、全てのボックスを1つのジオメトリに統合する事ができます。 -現在は19000個前後のボックスを描画してます。1つのジオメトリに統合する事で18999個の操作を削除する事ができます。

-

以下はボックスを1つのジオメトリに統合する新しいコードです。

-
function addBoxes(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-
--  // make one box geometry
--  const boxWidth = 1;
--  const boxHeight = 1;
--  const boxDepth = 1;
--  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
--  // make it so it scales away from the positive Z axis
--  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // these helpers will make it easy to position the boxes
-  // We can rotate the lon helper on its Y axis to the longitude
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // We rotate the latHelper on its X axis to the latitude
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // The position helper moves the object to the edge of the sphere
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-+  // Used to move the center of the box so it scales from the position Z axis
-+  const originHelper = new THREE.Object3D();
-+  originHelper.position.z = 0.5;
-+  positionHelper.add(originHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-+  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-
--      const material = new THREE.MeshBasicMaterial();
--      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
--      const saturation = 1;
--      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
--      material.color.setHSL(hue, saturation, lightness);
--      const mesh = new THREE.Mesh(geometry, material);
--      scene.add(mesh);
-
-+      const boxWidth = 1;
-+      const boxHeight = 1;
-+      const boxDepth = 1;
-+      const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
--      // use the world matrix of the position helper to
--      // position this mesh.
--      positionHelper.updateWorldMatrix(true, false);
--      mesh.applyMatrix4(positionHelper.matrixWorld);
--
--      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-
-+      // use the world matrix of the origin helper to
-+      // position this geometry
-+      positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-+      originHelper.updateWorldMatrix(true, false);
-+      geometry.applyMatrix4(originHelper.matrixWorld);
-+
-+      geometries.push(geometry);
-    });
-  });
-
-+  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-+      geometries, false);
-+  const material = new THREE.MeshBasicMaterial({color:'red'});
-+  const mesh = new THREE.Mesh(mergedGeometry, material);
-+  scene.add(mesh);
-
-}
-
-

上記ではボックスジオメトリの中心点を変更していたコードを削除し、代わりに originHelper を追加しています。 -前は同じジオメトリを19000回も使っていました。 -今回は1つ1つのジオメトリを新しく作成し、各ボックスジオメトリの頂点を移動するために applyMatrix を使用するので、2回ではなく1回にした方が良いかもしれません。

-

最後に全てのジオメトリの配列を BufferGeometryUtils.mergeGeometries に渡します。 -また BufferGeometryUtils も含める必要があります。

-
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
-
-

少なくとも私のマシンでは毎秒60フレームになりました。

-

- -

-

これで上手くいったのですが、以前はそれぞれのボックスに異なる色がありましたが、1つのメッシュなので1つのマテリアルとなり1つの色だけになります。 -これは頂点カラーを使い修正できます。

-

頂点カラーは頂点ごとに色を追加します。各ボックスの各頂点の全ての色を特定の色に設定する事で、全てのボックスが異なる色を持つようになります。

-
+const color = new THREE.Color();
-
-const lonFudge = Math.PI * .5;
-const latFudge = Math.PI * -0.135;
-const geometries = [];
-data.forEach((row, latNdx) => {
-  row.forEach((value, lonNdx) => {
-    if (value === undefined) {
-      return;
-    }
-    const amount = (value - min) / range;
-
-    const boxWidth = 1;
-    const boxHeight = 1;
-    const boxDepth = 1;
-    const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-    // adjust the helpers to point to the latitude and longitude
-    lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-    latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-    // use the world matrix of the origin helper to
-    // position this geometry
-    positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    originHelper.updateWorldMatrix(true, false);
-    geometry.applyMatrix4(originHelper.matrixWorld);
-
-+    // compute a color
-+    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const saturation = 1;
-+    const lightness = THREE.MathUtils.lerp(0.4, 1.0, amount);
-+    color.setHSL(hue, saturation, lightness);
-+    // get the colors as an array of values from 0 to 255
-+    const rgb = color.toArray().map(v => v * 255);
-+
-+    // make an array to store colors for each vertex
-+    const numVerts = geometry.getAttribute('position').count;
-+    const itemSize = 3;  // r, g, b
-+    const colors = new Uint8Array(itemSize * numVerts);
-+
-+    // copy the color into the colors array for each vertex
-+    colors.forEach((v, ndx) => {
-+      colors[ndx] = rgb[ndx % 3];
-+    });
-+
-+    const normalized = true;
-+    const colorAttrib = new THREE.BufferAttribute(colors, itemSize, normalized);
-+    geometry.setAttribute('color', colorAttrib);
-
-    geometries.push(geometry);
-  });
-});
-
-

上記のコードではジオメトリから position を取得して必要な頂点の数を調べています。 -次に色を入れるための変数を Uint8Array で作成します。その後に geometry.setAttribute を呼び出して属性として追加します。

-

最後に頂点カラーを扱うようにthree.jsで指定する必要があります。

-
const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-    geometries, false);
--const material = new THREE.MeshBasicMaterial({color:'red'});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-+});
-const mesh = new THREE.Mesh(mergedGeometry, material);
-scene.add(mesh);
-
-

これで色を取り戻す事ができました。

-

- -

-

ジオメトリのマージは一般的な最適化手法です。 -例えば100本の木を1つのジオメトリに統合したり、個々の岩の山を1つの岩のジオメトリに統合したり、個々の杭から1つの柵メッシュに統合したりする事ができます。 -別の例としてマインクラフトではそれぞれのキューブを個別に描画するのではなく、マージされたキューブのグループを作成したり描画されない面は選択的に削除したりします。

-

全てを1つのメッシュにする問題点としては、以前は分離されていた部分を移動する事が容易ではなくなった事です。 -ユースケースに応じて創造的なソリューションがあります。 -1つは別の記事で紹介します。

-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/picking.html b/manual/ja/picking.html deleted file mode 100644 index e329a1a038262b..00000000000000 --- a/manual/ja/picking.html +++ /dev/null @@ -1,430 +0,0 @@ - - - でピッキング - - - - - - - - - - - - - -
-
-

でピッキング

-
-
-
-

ピッキングとはユーザーがどのオブジェクトをクリックしたか、またはタッチしたかを把握するプロセスの事です。 -ピッキングする方法のそれぞれにトレードオフがありますが、実装の仕方はたくさんあります。最も一般的な2つの方法を見てみましょう。

-

おそらく、最も一般的なピッキングはレイキャスティングでマウスからシーンの錐台を通して光線をキャストし、その光線が交差するオブジェクトを計算する方法です。 -概念的には非常にシンプルです。

-

まずはマウスの位置を決めます。 -それをカメラの投影と向きをワールド座標に変換します。 -カメラの錐台の近くの面から遠くの面までの光線を計算します。 -そして、シーン内の全ての三角形オブジェクトで光線と交差するかチェックします。 -もしシーンに1000個のオブジェクトがあり、各オブジェクトに1000個の三角形がある場合、100万個の三角形をチェックする必要があります。

-

光線がオブジェクトのバウンディングスフィアやバウンディングボックス、つまりオブジェクト全体を含む球やボックスと交差するかを最初にチェックする事は最適化になります。 -もし光線がオブジェクトと交差しなければ、そのオブジェクトの三角形をチェックする必要はありません。

-

Three.jsにはこれを行う RayCaster クラスを提供しています。

-

100個のオブジェクトがあるシーンを作ってピッキングしてみましょう。 -レスポンシブデザインの記事のコード例から始めてみます。

-

いくつかの変更点

-

カメラを別のオブジェクトの親にして、そのオブジェクトを回転させるとカメラが自撮り棒のようにシーンの周りを動き回るようになります。

-
*const fov = 60;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-*const far = 200;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-*camera.position.z = 30;
-
-const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-+// put the camera on a pole (parent it to an object)
-+// so we can spin the pole to move the camera around the scene
-+const cameraPole = new THREE.Object3D();
-+scene.add(cameraPole);
-+cameraPole.add(camera);
-
-

そして、render 関数でcameraPoleを回転させます。

-
cameraPole.rotation.y = time * .1;
-
-

カメラにライトを追加し、ライトが動くようにしましょう。

-
-scene.add(light);
-+camera.add(light);
-
-

ランダムな色、位置、向き、スケールの100個のキューブを生成してみましょう。

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return min + (max - min) * Math.random();
-}
-
-function randomColor() {
-  return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`;
-}
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-}
-
-

最後にピックします。

-

ピッキングを管理する簡単なクラスを作ってみましょう。

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // restore the color if there is a picked object
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // cast a ray through the frustum
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // get the list of objects the ray intersected
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // pick the first object. It's the closest one
-      this.pickedObject = intersectedObjects[0].object;
-      // save its color
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // set its emissive color to flashing red/yellow
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

RayCaster を作成し、pick 関数を呼び出してシーンに光線をキャストできます。 -光線が何かに当たった場合、最初に当たったオブジェクトの色を変更します。

-

もちろん、マウスを down した時だけこの関数を呼べますが、今回は全てのフレームでマウスの下に何かあるかピックします。 -そのためにはまずマウスがどこにあるかを追跡する必要があります。

-
const pickPosition = {x: 0, y: 0};
-clearPickPosition();
-
-...
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // note we flip Y
-}
-
-function clearPickPosition() {
-  // unlike the mouse which always has a position
-  // if the user stops touching the screen we want
-  // to stop picking. For now we just pick a value
-  // unlikely to pick something
-  pickPosition.x = -100000;
-  pickPosition.y = -100000;
-}
-
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-

正規化されたマウスの位置を記録している事に注意して下さい。 -キャンバスの大きさに関わらず、leftの-1からrightの+1までの値が必要です。 -同様にbottomが-1からtopが+1になるような値が必要です。

-

これでモバイル端末もサポートできます。

-
window.addEventListener('touchstart', (event) => {
-  // prevent the window from scrolling
-  event.preventDefault();
-  setPickPosition(event.touches[0]);
-}, {passive: false});
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

最後に render 関数で PickHelperpick 関数を呼び出します。

-
+const pickHelper = new PickHelper();
-
-function render(time) {
-  time *= 0.001;  // convert to seconds;
-
-  ...
-
-+  pickHelper.pick(pickPosition, scene, camera, time);
-
-  renderer.render(scene, camera);
-
-  ...
-
-

その結果がこれです。

-

- -

-

望んだ動作でおそらく多くのユースケースに対応できますが、いくつか問題点があります。

-
    -
  1. CPUベース

    -

    JavaScriptは各オブジェクトを通過し、光線がそのオブジェクトのバウンディングボックス、またはバウンディングスフィアと交差するかをチェックしています。 -そのオブジェクト内の各三角形を通過し、光線が三角形と交差するかチェックしなければなりません。

    -

    これの良い点はJavaScriptが簡単に光線が三角形と交差する場所を正確に計算し、その結果が分かります。 -例えば交差する点があった場所に目印をつけたい場合などです。

    -

    悪い点はCPUの負担が大きい所ですね。 -三角形がたくさんあるオブジェクトを持っている場合は遅いかもしれません。

    -
  2. -
  3. 変なシェーダーやズレを処理しません

    -

    ジオメトリを変形またはモーフィングするシェーダーがある場合、JavaScriptはその変形を認識できなく、間違った答えを返してしまいます。 -例えばAFAIKのように、メソッドはスキニングされたオブジェクトでは使えません。

    -
  4. -
  5. 透明な穴には対応しません

    -
  6. -
-

例として、このテクスチャをキューブに適用してみましょう。

-
- -

以下のように変更します。

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load('resources/images/frame.png');
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    +map: texture,
-    +transparent: true,
-    +side: THREE.DoubleSide,
-    +alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  ...
-
-

以下の例で動作確認をすると、すぐにこの問題が分かると思います。

-

- -

-

ボックスの穴の部分でピックしてみて下さい。

-
- -

この原因は、JavaScriptがテクスチャやマテリアルを調べて、オブジェクトの一部が本当に透明か判断できないからです。

-

これらの問題を全て解決するのが、GPUベースのピッキングです。 -概念的には簡単ですが、残念ながら上記のレイキャスティングよりも使用方法が複雑になっています。

-

GPUピッキングを行うには、各オブジェクトをオフスクリーンでユニークな色でレンダリングします。 -次にマウスの位置に対応するピクセルの色を調べます。 -色でどのオブジェクトが選ばれたか分かります。

-

これで上記の2と3の問題を解決できます。問題1は速度に依存しています。 -全てのオブジェクトは2回描画されなければなりません。 -1回は見るための描画、もう1回はピッキングの描画です。 -洗練された解決策は、その両方を同時に行う事ですが今回はそれを試しません。

-

1つのやり方としては、1つのピクセルしか読まないのでそのピクセルだけ描画されるようにカメラを設定します。 -これを行うには PerspectiveCamera.setViewOffset を使用します。 -これでカメラを計算できます。 -これで時間を節約できるはずです。

-

現時点ではこのピッキングを行うには、2つのシーンを作成する必要があります。 -1つは通常のメッシュで埋めます。 -もう1つはピッキングマテリアルを使用したメッシュで埋めます。

-

そこでまず2つ目のシーンを作り黒でクリアします。

-
const scene = new THREE.Scene();
-scene.background = new THREE.Color('white');
-const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

次にメインシーンに配置する各キューブでオリジナルのキューブと同じ位置に対応する"ピッキングキューブ"を作成し、pickingScene に配置します。 -オブジェクトのidを色として描画するようにマテリアルを設定します。 -また、idとオブジェクトのマップがあるので、後でidを調べた時に対応するオブジェクトにマップを戻す事ができます。

-
const idToObject = {};
-+const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-+  const id = i + 1;
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    map: texture,
-    transparent: true,
-    side: THREE.DoubleSide,
-    alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-+  idToObject[id] = cube;
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-
-+  const pickingMaterial = new THREE.MeshPhongMaterial({
-+    emissive: new THREE.Color().setHex(id, THREE.NoColorSpace),
-+    color: new THREE.Color(0, 0, 0),
-+    specular: new THREE.Color(0, 0, 0),
-+    map: texture,
-+    transparent: true,
-+    side: THREE.DoubleSide,
-+    alphaTest: 0.5,
-+    blending: THREE.NoBlending,
-+  });
-+  const pickingCube = new THREE.Mesh(geometry, pickingMaterial);
-+  pickingScene.add(pickingCube);
-+  pickingCube.position.copy(cube.position);
-+  pickingCube.rotation.copy(cube.rotation);
-+  pickingCube.scale.copy(cube.scale);
-}
-
-

ここでは MeshPhongMaterial を悪用している事に注意して下さい。 -emissive をidにし、colorspecular を0に設定しテクスチャのアルファ値が alphaTest よりも大きい場合にのみ、idをレンダリングできます。 -また、blendingNoBlending に設定し、idにアルファが乗算しないようにする必要があります。

-

MeshPhongMaterialを悪用する事は、最良の解決策でない事に注意して下さい。 -さらに最適化された解決策は、テクスチャのアルファ値が alphaTest よりも大きい場合にidを書き込むカスタムシェーダーを作成する事です。

-

レイキャスティングではなくピクセルからピックしているので、ピック位置を設定するコードを変更してピクセルだけを使用できます。

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // note we flip Y
-+  pickPosition.x = pos.x;
-+  pickPosition.y = pos.y;
-}
-
-

PickHelperGPUPickHelper に変更してみましょう。 -レンダーターゲットの記事で説明したように WebGLRenderTarget を使います。 -ここでのレンダーターゲットは1 x 1の1ピクセルのサイズしかありません。

-
-class PickHelper {
-+class GPUPickHelper {
-  constructor() {
--    this.raycaster = new THREE.Raycaster();
-+    // create a 1x1 pixel render target
-+    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-+    this.pixelBuffer = new Uint8Array(4);
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera, time) {
-+    const {pickingTexture, pixelBuffer} = this;
-
-    // restore the color if there is a picked object
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-+    // set the view offset to represent just a single pixel under the mouse
-+    const pixelRatio = renderer.getPixelRatio();
-+    camera.setViewOffset(
-+        renderer.getContext().drawingBufferWidth,   // full width
-+        renderer.getContext().drawingBufferHeight,  // full top
-+        cssPosition.x * pixelRatio | 0,             // rect x
-+        cssPosition.y * pixelRatio | 0,             // rect y
-+        1,                                          // rect width
-+        1,                                          // rect height
-+    );
-+    // render the scene
-+    renderer.setRenderTarget(pickingTexture)
-+    renderer.render(scene, camera);
-+    renderer.setRenderTarget(null);
-+
-+    // clear the view offset so rendering returns to normal
-+    camera.clearViewOffset();
-+    //read the pixel
-+    renderer.readRenderTargetPixels(
-+        pickingTexture,
-+        0,   // x
-+        0,   // y
-+        1,   // width
-+        1,   // height
-+        pixelBuffer);
-+
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2]      );
-
--    // cast a ray through the frustum
--    this.raycaster.setFromCamera(normalizedPosition, camera);
--    // get the list of objects the ray intersected
--    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
--    if (intersectedObjects.length) {
--      // pick the first object. It's the closest one
--      this.pickedObject = intersectedObjects[0].object;
-
-+    const intersectedObject = idToObject[id];
-+    if (intersectedObject) {
-+      // pick the first object. It's the closest one
-+      this.pickedObject = intersectedObject;
-      // save its color
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // set its emissive color to flashing red/yellow
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

それならば、それを使えばいいだけです。

-
-const pickHelper = new PickHelper();
-+const pickHelper = new GPUPickHelper();
-
-

これを指定し scene の代わりに pickScene を渡します。

-
-  pickHelper.pick(pickPosition, scene, camera, time);
-+  pickHelper.pick(pickPosition, pickScene, camera, time);
-
-

そして、透明な部分を選択するようにする必要があります。

-

- -

-

ピッキングを実装する方法のアイデアをいくつか得られたと思います。 -今後の記事ではマウスを使ってオブジェクトを操作する方法を取り上げるかもしれません。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/post-processing.html b/manual/ja/post-processing.html deleted file mode 100644 index 5c236810a3c649..00000000000000 --- a/manual/ja/post-processing.html +++ /dev/null @@ -1,254 +0,0 @@ - - - のポストプロセス - - - - - - - - - - - - - -
-
-

のポストプロセス

-
-
-
-

ポストプロセスとは、一般的には2D画像に何らかのエフェクトやフィルターを適用する事です。 -Three.jsの場合、たくさんのメッシュが入ったシーンがあり、そのシーンを2D画像にレンダリングします。 -通常はその2D画像はキャンバスに直接レンダリングしブラウザに表示されますが、 -代わりにレンダーターゲットにレンダリングし、キャンバス描画前にポストプロセスエフェクトを適用できます。 -メインシーンのレンダリング後に行われるため、ポストプロセスと呼ばれています。

-

ポストプロセスの例としては、InstagramやPhotoshopのフィルターなどがあります。

-

Three.jsには、ポストプロセスのパイプラインを設定するサンプルクラスがいくつかあります。 -今回は最初に EffectComposer を作成し、複数の Pass オブジェクトを追加します。 -次に EffectComposer.render を呼び出し、シーンを レンダーターゲットにレンダリングしてそれぞれの Pass を適用します。

-

それぞれの Pass には、ビネットの追加、ブラーやブルームの適用、フィルムグレインの適用、色相、彩度、コントラストの調整などのポストプロセスを適用できます。 -最後のレンダリングでポストプロセス結果をキャンバスにレンダリングします。

-

EffectComposer 関数がどのようなものか理解するのは少し重要です。 -ここでは2つのレンダーターゲットを作成します。 -これをrtArtBと呼ぶ事にしましょう。

-

次に EffectComposer.addPass を呼び出し、それぞれのPassに適用したい順番で追加します。 -Passは次の図のように適用されます。

-
- -

RenderPassに渡されたシーンは、まずrtAにレンダリングされrtAは次のPassに渡されます。 -このPassはrtAを入力として使用し、rtBに結果を書き込みます。 -その後にrtBは次のPassに渡され、rtBを入力として使用しrtAに書き戻します。 -これは全てのPassを通ります。

-

それぞれの Pass には4つの基本的なオプションがあります。

-

enabled

-

このPassを使用するかどうか

-

needsSwap

-

このPass終了後に rtArtB を入れ替えるかどうか

-

clear

-

このPassをレンダリングする前にクリアするかどうか

-

renderToScreen

-

現在の出力先のレンダーターゲットではなく、キャンバスにレンダリングするかどうか。 -通常は EffectComposer に追加する最後のPassでtrueに設定する必要があります。

-

基本的な例をまとめてみましょう。 -まずはレスポンシブデザインの記事から例を挙げてみます。

-

そのためにまず EffectComposer を作成します。

-
const composer = new EffectComposer(renderer);
-
-

次に最初のPassとして RenderPass を追加し、最初のレンダーターゲットにカメラを使ってシーンをレンダリングします。

-
composer.addPass(new RenderPass(scene, camera));
-
-

次に BloomPass を追加します。 -BloomPass は一般的には入力を小さなレンダーターゲットにレンダリングし、結果にブラーをかけます。 -そして、元の入力の上にブラーされた結果を追加します。 -これでシーンに ブルーム をかけます。

-
const bloomPass = new BloomPass(
-    1,    // strength
-    25,   // kernel size
-    4,    // sigma ?
-    256,  // blur render target resolution
-);
-composer.addPass(bloomPass);
-
-

最終的には、元の入力の上にノイズとスキャンラインを描画する FilmPass ができました。

-
const filmPass = new FilmPass(
-    0.5,   // intensity
-    false,  // grayscale
-);
-composer.addPass(filmPass);
-
-

これらのクラスを使用するには、以下をインポートする必要があります。

-
import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js';
-import {RenderPass} from 'three/addons/postprocessing/RenderPass.js';
-import {BloomPass} from 'three/addons/postprocessing/BloomPass.js';
-import {FilmPass} from 'three/addons/postprocessing/FilmPass.js';
-import {OutputPass} from 'three/addons/postprocessing/OutputPass.js';
-
-

ほとんどのポストプロセスには EffectComposer.jsRenderPass.js が必須です。

-

最後に WebGLRenderer.render の代わりに EffectComposer.render を使用し、EffectComposer にキャンバスのサイズを合わせます。

-
-function render(now) {
--  time *= 0.001;
-+let then = 0;
-+function render(now) {
-+  now *= 0.001;  // convert to seconds
-+  const deltaTime = now - then;
-+  then = now;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-+    composer.setSize(canvas.width, canvas.height);
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
--    const rot = time * speed;
-+    const rot = now * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
--  renderer.render(scene, camera);
-+  composer.render(deltaTime);
-
-  requestAnimationFrame(render);
-}
-
-

EffectComposer.renderdeltaTime で最後のフレームのレンダリング後からの時間を秒単位で受け取ります。 -deltaTimeをアニメーションしてる様々なエフェクトに渡します。 -今回は FilmPass がアニメーションしています。

-

- -

-

実行時にエフェクトパラメーターを変更するには、uniformの値を設定する必要があります。 -パラメータを調整するためのGUIを追加してみましょう。 -どの値を調整できるか把握するには、以下のコードを調べる必要があります。

-

BloomPass.jsの中でこの行を見つけました。

-
this.copyUniforms[ "opacity" ].value = strength;
-
-

strengthを設定できます。

-
bloomPass.copyUniforms.opacity.value = someValue;
-
-

同様にFilmPass.jsでこの行を見つけました。

-
this.uniforms.intensity.value = intensity;
-this.uniforms.grayscale.value = grayscale;
-
-

これでどのように設定するか、かなり明確になりました。

-

これらの値を設定する簡単なGUIを作ってみましょう。

-
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

そして

-
const gui = new GUI();
-{
-  const folder = gui.addFolder('BloomPass');
-  folder.add(bloomPass.copyUniforms.opacity, 'value', 0, 2).name('strength');
-  folder.open();
-}
-{
-  const folder = gui.addFolder('FilmPass');
-  folder.add(filmPass.uniforms.grayscale, 'value').name('grayscale');
-  folder.add(filmPass.uniforms.intensity, 'value', 0, 1).name('intensity');
-  folder.open();
-}
-
-

これで設定を調整できるようになりました。

-

- -

-

これはあなた自身のエフェクトを作る小さな1歩です。

-

ポストプロセスエフェクトではシェーダーを使用します。 -シェーダーはGLSL (Graphics Library Shading Language)と呼ばれる言語で書かれています。 -この記事では、GLSL言語全体を解説するのはあまりにも大きなトピックです。 -この記事このシェーダーの本を参考にしてみて下さい。

-

サンプルがあると便利だと思うので、簡単なGLSLのポストプロセスのシェーダーを作ってみましょう。 -画像に色を乗算したものを作ります。

-

Three.jsではポストプロセス用に ShaderPass という便利なヘルパーを提供しています。 -頂点シェーダー、フラグメントシェーダー、デフォルト入力を定義した情報を持つオブジェクトを取得します。 -前のPassの結果を得るためにどのテクスチャから読み込むか、EffectComposer のどこにレンダリングするかを設定します。

-

前のPassの結果に色を乗算するシンプルなポストプロセスシェーダーです。

-
const colorShader = {
-  uniforms: {
-    tDiffuse: { value: null },
-    color:    { value: new THREE.Color(0x88CCFF) },
-  },
-  vertexShader: `
-    varying vec2 vUv;
-    void main() {
-      vUv = uv;
-      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
-    }
-  `,
-  fragmentShader: `
-    varying vec2 vUv;
-    uniform sampler2D tDiffuse;
-    uniform vec3 color;
-    void main() {
-      vec4 previousPassColor = texture2D(tDiffuse, vUv);
-      gl_FragColor = vec4(
-          previousPassColor.rgb * color,
-          previousPassColor.a);
-    }
-  `,
-};
-
-

上記の tDiffuseShaderPass が前のPassの結果テクスチャを渡す名前です。 -color を Three.jsの Color として宣言します。

-

次に頂点シェーダーが必要です。 -ポストプロセスでは上記コードの頂点シェーダーは標準的なものであり、ほとんど変更する必要はありません。 -あまり詳しく説明しませんが(上記のリンク先の記事を参照してください)、 -変数 uv, projectionMatrix, modelViewMatrix, position は全てThree.jsによって魔法のように追加されています。

-

最後にフラグメントシェーダーを作成します。この中で前のPassのピクセルカラーを次の行で取得します。

-
vec4 previousPassColor = texture2D(tDiffuse, vUv);
-
-

これに色を掛けて gl_FragColor を設定します。

-
gl_FragColor = vec4(
-    previousPassColor.rgb * color,
-    previousPassColor.a);
-
-

3つ色の設定用に簡単なGUIを追加します。

-
const gui = new GUI();
-gui.add(colorPass.uniforms.color.value, 'r', 0, 4).name('red');
-gui.add(colorPass.uniforms.color.value, 'g', 0, 4).name('green');
-gui.add(colorPass.uniforms.color.value, 'b', 0, 4).name('blue');
-
-

色で乗算するシンプルなポストプロセスエフェクトができました。

-

- -

-

GLSLやカスタムシェーダーの詳細は、ネット上にたくさんの記事があります。 -WebGL自体がどのように動作するかを知りたいならば、これらの記事をチェックしてみて下さい。 -もう1つの素晴らしいリソースは、THREE.jsレポートの既存ポストプロセスシェーダーを読み解く事です。 -複雑なものもいくつかありますが、小さいものから始めるとどのように動作するかのアイデアを得る事ができます。

-

残念ながらThree.jsレポートにあるほとんどのポストプロセスエフェクトは文書化されていないので、使用するにはこの例か -エフェクト自体のコードを読んで下さい。 -これらのシンプルな例とレンダーターゲットの記事がポストプロセスを始めるのに十分な知識を提供してくれると思います。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/prerequisites.html b/manual/ja/prerequisites.html deleted file mode 100644 index dda13665f6bca6..00000000000000 --- a/manual/ja/prerequisites.html +++ /dev/null @@ -1,267 +0,0 @@ - - - の前提条件 - - - - - - - - - - - - - -
-
-

の前提条件

-
-
-
-

これらの記事は、three.jsの使用方法を学習するためものです。 -JavaScriptのプログラミング方法を把握してる事を前提とします。 -DOMとは何か、HTMLの記述方法、JavaScriptでDOMの作成方法を把握してる事を前提とします。 -es6 modules のimportや <script type="module"> タグを把握してる事を前提とします。 -CSSや CSSセレクター が何か把握してる事を前提とします。 -ES5、ES6、およびES7を把握してる事を前提とします。 -イベントとコールバックでJavaScripが実行されるのを把握してる事を前提とします。 -クロージャとは何かを知っている事を前提とします。

-

また、以下に簡単な復習と注意事項があります。

-

es6モジュール

-

es6モジュールはスクリプトの中で import キーワード、または <script type="module"> タグを使用してインラインでロードできます。 -以下に両方の使用​​例があります。

-
<script type="module">
-import * as THREE from 'three';
-
-...
-
-</script>
-
-

パスは絶対パス、または相対パスでなければなりません。相対パスは常に ./ または ../ で始まり <img><a> などの他のタグやcss参照とは異なります。

-

詳細はこの記事の最後に記載しています。

-

document.querySelectordocument.querySelectorAll

-

document.querySelector を使用し、CSSセレクターに一致する最初の要素を選択できます。 -document.querySelectorAll は、CSSセレクターに一致するすべての要素を返します。

-

onbody は必要ありません

-

20年前の古いWebページでは、以下のようなHTMLが多く使われてました。

-
<body onload="somefunction()">
-

このスタイルは非推奨です。スクリプトをページの下部に配置します。

-
<html>
-  <head>
-    ...
-  </head>
-  <body>
-     ...
-  </body>
-  <script>
-    // inline javascript
-  </script>
-</html>
-
-

または、deferプロパティを使用します

-

クロージャーの仕組みを知る

-
function a(v) {
-  const foo = v;
-  return function() {
-     return foo;
-  };
-}
-
-const f = a(123);
-const g = a(456);
-console.log(f());  // prints 123
-console.log(g());  // prints 456
-
-

上記のコードでは、新しい関数が作成される度に関数 a を呼び出します。 -その関数は変数 foo閉じ込めます 。 -ここに詳細な情報 があります。

-

this がどのように機能するか知る

-

this は魔法ではありません。 -引数が関数に渡されるのと同じように、関数に自動的に渡される実質的な変数です。 -簡単に説明すると、次のような関数を直接呼び出す場合です。

-
somefunction(a, b, c);
-

thisnull(strictモードまたはモジュールの場合)になりますが、ドット演算子を使用して関数を呼び出す場合と同様です。

-
someobject.somefunction(a, b, c);
-

thissomeobject がセットされます。

-

この部分はみなさんが混乱するコールバックです。

-
 const callback = someobject.somefunction;
- loader.load(callback);
-

これは経験の浅い人が期待するように動作しません。 -なぜなら loader.load がコールバックを呼び出す時、. 演算子で this を呼び出していないため、デフォルトではnullになります(ローダーが明示的に何かを設定しない限り) -コールバックが発生した時に thissomeobject したい場合は、関数をバインドする必要があります。

-
 const callback = someobject.somefunction.bind(someobject);
- loader.load(callback);
-

この記事は this を理解するのに役立つかもしれません.

-

ES5/ES6/ES7 stuff

-

var は非推奨です。 constlet を使って下さい

-

var は使用する理由がありません。varを使用するのは悪い習慣と見なされます。ほとんどの場合、変数の値を変えない場合は const を使用します。 -値が変更される場合は let を使用します。これにより大量のバグを回避できます。

-

for of を使用し for in は使用しない

-

for of は新しい書き方で、 for in は古い書き方です。 for in で解決できない問題を for of が解決しています。 -解決した一例として、オブジェクトのすべてのkey/valueのペアを反復処理ができます。

-
for (const [key, value] of Object.entries(someObject)) {
-  console.log(key, value);
-}
-
-

forEachmapfilter は役に立ちます

-

配列の関数である forEach や -map 、 -filter - はモダンなJavaScriptで広く使われています。

-

分割代入を使う

-

const dims = {width: 300, height: 150} のObjectがあるとします。

-

古いコードの場合

-
 const width = dims.width;
- const height = dims.height;
-

新しいコードの場合

-
 const {width, height} = dims;
-

オブジェクト宣言のショートカットを使う

-

古いコードの場合

-
 const width = 300;
- const height = 150;
- const obj = {
-   width: width,
-   height: height,
-   area: function() {
-     return this.width * this.height
-   },
- };
-
-

新しいコードの場合

-
 const width = 300;
- const height = 150;
- const obj = {
-   width,
-   height,
-   area() {
-     return this.width * this.height;
-   },
- };
-
-

スプレット演算子 ... を使う

-

スプレット演算子にはたくさんの使い方があります。例えば

-
 function log(className, ...args) {
-   const elem = document.createElement('div');
-   elem.className = className;
-   elem.textContent = [...args].join(' ');
-   document.body.appendChild(elem);
- }
-
-

もう1つの例

-
const position = [1, 2, 3];
-somemesh.position.set(...position);
-
-

class を使う

-

ES5より以前のオブジェクトのようなクラス構文は、ほとんどのプログラマーにはなじみがありませんでした。 -ES5以降では、C ++やC#、Javaのスタイルに近いclass キーワードを使用 -できるようになりました。

-

gettersとsettersを理解する

-

Getters と -setters は -ほとんどのモダンなプログラミン言語でよく使われます。 -ES5のクラス構文により、ES5以前よりもはるかに簡単に使えます。

-

必要に応じてアロー関数を使います

-

アロー関数はcallbackとPromiseで特に役立ちます。

-
loader.load((texture) => {
-  // use texture
-});
-
-

アロー関数は this をバインドします。

-
const foo = (args) => {/* code */};
-
-

ショートカットで書くなら

-
const foo = (function(args) {/* code */}).bind(this));
-
-

Promiseはasync/awaitと同様です

-

Promisesは非同期な処理を助ます。Async/awaitはpromiseを助けます。

-

ここで扱うには大きな話題になるため、promiseのドキュメントを読んで下さい。 -また、async/awaitもドキュメントを読んで下さい

-

テンプレートリテラルを使用する

-

テンプレートリテラルは、引用符("", '')の代わりにバックティック文字( )を使います。

-
const foo = `this is a template literal`;
-

テンプレートリテラルには基本的に2つの機能があります。1つは複数行にかけます。

-
const foo = `this
-is
-a
-template
-literal`;
-const bar = "this\nis\na\ntemplate\nliteral";
-
-

上記の foobar は同様の意味になります.

-

もう1つは、文字モードの中に ${javascript-expression} のようにJavaScriptのスニペッドを挿入できます。 -これはテンプレートの一部です。例えば

-
const r = 192;
-const g = 255;
-const b = 64;
-const rgbCSSColor = `rgb(${r},${g},${b})`;
-
-

または

-
const color = [192, 255, 64];
-const rgbCSSColor = `rgb(${color.join(',')})`;
-
-

または

-
const aWidth = 10;
-const bWidth = 20;
-someElement.style.width = `${aWidth + bWidth}px`;
-
-

JavaScriptのコーディング規則を学びましょう

-

自由にコードフォーマットする事ができますが、少なくとも1つの規則に注意する必要があります。 -JavaScriptの変数名や関数名、メソッド名はすべてローワーキャメルケースです。 -コンストラクターやクラスの名前はアッパーキャメルケースです。 -このルールに従うなら、他のほとんどのJavaScriptコードと一致します。

-

多くの リンター] やコード内の明らかなエラーをチェックするプログラムは、間違ったケースを使用するとエラーを指摘します。 -上記の規則に従うことで、エラーが間違っている事がわかるからです。

-
const v = new vector(); // clearly an error if all classes start with a capital letter
-const v = Vector();     // clearly an error if all functions start with a lowercase latter.
-
-

Visual Studio Codeの使用を検討する

-

もちろんあなたが望むエディタが良いですが、もし望むエディタがなければ Visual Studio Code を使う事を検討してみて下さい。 -インストールし eslintをセットアップ します。 -セットアップには数分かかる場合がありますが、バグを見つけるのに非常に役に立ちます。

-

いくつかの例

-

no-undef ルール を有効にすると、VSCodeのEsLintで多くの未定義の変数について警告します。

-
- -

上記は doTheThing のスペルを doThing と間違えている事がわかります。 -doThing の下に赤い波線があり、その上をホバリングすると定義されていない事がわかります。 -1つのエラーが回避されました。 -THREE を使用して警告が表示された場合、eslintに THREE が存在する事を伝えるため、JavaScriptファイルの先頭に /* global THREE */ を追加します。

-
- -

上記では、eslintは アッパーキャメルケース がコンストラクターであるというルールを知っているため、 new を使用する必要があります。 -他のエラーをキャッチして避けます。これはnew-cap ルール です。

-

数百のEslintルールをオン・オフにカスタム できます。 -上記の例では var でなく constlet を使用するルールを適用しました。 -コードでは var を使用しましたが、let または const を使用する必要があると警告されました。

-
- -

ここでは let を使用しましたが、値を変更しない事がわかったため、 const を使用することが提案されました。

-
- -

もちろん、 var を使い続けたい場合は、そのルールをオフにすることができます。 -上記で記述したように var よりも constlet を使用することを好みます。 -それらはうまく機能し、バグを防ぎます。

-

ルールをオーバーライドする必要がある場合、1行のコードまたはコードセクションに無効にするコメントを追加できます

-

レガシーブラウザをサポートする必要がある場合は、トランスパイラーを使用して下さい

-

ほとんどのモダンなブラウザは自動更新されるため、これらすべての機能を使用すると便利です。生産性を高め、バグを回避できます。 -あなたのプロジェクトで古いブラウザをサポートする必要があれば、ES5/ES6/ES7コードをES5のJavascriptにトランスパイラーするツール を使用して下さい。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/primitives.html b/manual/ja/primitives.html deleted file mode 100644 index 116023a58c67fd..00000000000000 --- a/manual/ja/primitives.html +++ /dev/null @@ -1,322 +0,0 @@ - - - のプリミティブ - - - - - - - - - - - - - -
-
-

のプリミティブ

-
-
-
-

この記事はthree.jsについてのシリーズ記事の一つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでない人は、そちらから先に読んでみるといいかもしれません。

-

Three.jsは多くのプリミティブがあります。 -プリミティブは、3D形状のことで、一般的に、実行時に複数のパラメータを指定して生成されます。

-

地球儀の球体や、3Dグラフを描くための箱の集まりのようなものに、プリミティブはよく使われます。 -特に、プリミティブを使って実験して、3Dを始めるのが一般的です。 -3Dアプリケーションの多くは、3DモデルをBlenderや -Mayaや -Cinema 4Dといった -3Dモデリングプログラムを使って、アーティストに作ってもらう方が一般的です。 -このシリーズの後半では、いくつかの3Dモデリングプログラムからデータを作って -読み込む方法もカバーするつもりです。 -では、three.jsで利用できるプリミティブについて説明しましょう。

-

以下のプリミティブの多くは、一部または全てのパラメータにデフォルト値が設定されています。 -そのため、必要に応じて、上手く使い分けることができます。

-
立方体
-
2次元の円
-
円錐
-
円筒
-
十二面体(12面のもの)
-
-押し出しでできた2次元形状、ベベルオプション付き。 -これはTextGeometryTextGeometryのそれぞれの基礎になることに注意してください。
-
二十面体(20面のもの)
-
線を回転させてできる形状。例としてはこんなところでしょうか:ランプやボーリングのピン、ろうそく、ろうそく立て、ワイングラス、ドリンクグラス、などなど...。点の連続として2次元の輪郭を与え、その輪郭を軸の周りで回転させる際に、どのくらい細分化するかthree.jsに指示することができます。
-
八面体(8面)
-
関数を与えることでできる表面。この関数は、グリッド上2次元の点を引数に取り、対応する3次元の点を返す。
-
2次元の四角形
-
三角形を点の周りに集めて球体にする
-
真ん中に穴のあいた円盤
-
三角形分割された2次元の輪郭
-
球体
-
四面体(4面のもの)
-
3Dフォントと文字列からできた、3Dテキスト
-
円環(ドーナツ)
-
円環(結び目)
-
経路をなぞらせた管
-
異なるジオメトリを入力として、その面同士の角度が閾値以上なら角を作り出す、補助オブジェクト。例えば、記事の最初の方で紹介した立方体を見てみると、それぞれの面に、立方体を作っている全ての三角形の線が表示されています。EdgesGeometryを代わりに使うことで、面内の線は全て除去されます。下記のthresholdAngleを調整してみてください。閾値以下の角が消えて見えるでしょう。
-
1つの角ごとに1つの線分(2点)を持つジオメトリを生成する。WebGLは線分を作るのに2点が必要なので、この機能がないと、しばしば角を忘れたり、余分な角を作ってしまうでしょう。例えば、たった3点しかない1つの三角形あるとします。wireframe: trueのマテリアルを使ってそれを描こうとした場合、1本の線分しか得られません。WireframeGeometryにその三角形のジオメトリを渡すと、6点からなる3つの線分を持った新しいジオメトリを生成します。
- -

別の記事で、カスタムジオメトリの作成について説明します。 -今はそれぞれの種類のプリミティブを作成する例を作ってみます。 -以前の記事を例に始めましょう。

-

最初の方で、背景色を指定します。

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color(0xAAAAAA);
-
-

これでthree.jsに、透明からライトグレーに変えるように伝えます。

-

全てのオブジェクトを見られるよう、カメラの位置も変える必要があります。

-
-const fov = 75;
-+const fov = 40;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 1000;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 120;
-
-

addObject関数を加えましょう。これはx座標とy座標とObject3Dを取り、シーンにオブジェクトを追加します。

-
const objects = [];
-const spread = 15;
-
-function addObject(x, y, obj) {
-  obj.position.x = x * spread;
-  obj.position.y = y * spread;
-
-  scene.add(obj);
-  objects.push(obj);
-}
-
-

ランダムに色付けされたマテリアルを作る関数も作成してみましょう。 -色相、彩度、輝度に基づいて色を設定できる、Colorの機能を使ってみます。

-

hueは色相環を0から1まで変化します。赤は0、緑は.33、青は.66です。 -saturationは0から1まで変化します。0 は無色で、1は最も彩度の高いです。 -luminanceは0から1まで変化します。0は黒、1は白、0.5が色の最大量になります。 -言い換えると、luminanceが0.0から0.5に変化するにつれて、色は黒からhueに -変わります。0.5から1.0に変化するにつれて、hueから白に変化します。

-
function createMaterial() {
-  const material = new THREE.MeshPhongMaterial({
-    side: THREE.DoubleSide,
-  });
-
-  const hue = Math.random();
-  const saturation = 1;
-  const luminance = .5;
-  material.color.setHSL(hue, saturation, luminance);
-
-  return material;
-}
-
-

私たちはside: THREE.DoubleSideもマテリアルに渡しました。 -これはthreeに形状を作るときに三角形の両面を描くように指示します。 -球体や立方体のような立体形状には、形状の内側を向いている裏側を描く -理由はありません。 -しかしこの例だと、2次元で裏側が存在しないPlaneGeometryShapeGeometryのようなものも描こうとしています。 -side: THREE.DoubleSideを設定しないと、裏側を見たときに消えてしまうことでしょう。

-

side: THREE.DoubleSidenotが設定された方が、描画が速くなります。 -そのため、理想的には本当に必要なときだけ設定するのが良いことを注記しておきます。 -しかしこの例だと、そんなにたくさん描画しないので心配ありません。

-

addSolidGeometry関数を作りましょう。ジオメトリを渡すとcreateMaterialによってランダムに色が付いたマテリアルを作り、addObjectによってシーンに追加してくれます。

-
function addSolidGeometry(x, y, geometry) {
-  const mesh = new THREE.Mesh(geometry, createMaterial());
-  addObject(x, y, mesh);
-}
-
-

これで私たちの作るプリミティブの大多数に、この関数が使用できます。 -例えば、立方体を作ってみます。

-
{
-  const width = 8;
-  const height = 8;
-  const depth = 8;
-  addSolidGeometry(-2, -2, new THREE.BoxGeometry(width, height, depth));
-}
-
-

下記のコードを覗いてみると、それぞれの種類のジオメトリに対して、同じような箇所があります。

-

結果はこのようになります:

-

- -

-

上記のパターンには、2つの特筆すべき例外があります。 -一番大きなものは、たぶんTextGeometryです。テキストのメッシュを作るときは、事前に3Dフォントデータを読み込む必要があります。このデータの読み込みは非同期的に行われるので、ジオメトリを作ろうとする前に、読み込みを待つ必要があります。フォントの読み込みにpromiseを使うと、もっと速く読み込むことができます。 -FontLoaderを作成し、読み込みが完了するとフォントを提供してくれるpromiseを返すloadFont関数を作ります。 -次に、doit と呼ばれるasync関数を作り、awaitを使ってフォントを読み込みます。 -最後に、ジオメトリを作り、addObjectを呼んでシーンに追加します。

-
{
-  const loader = new FontLoader();
-  // promisify font loading
-  function loadFont(url) {
-    return new Promise((resolve, reject) => {
-      loader.load(url, resolve, undefined, reject);
-    });
-  }
-
-  async function doit() {
-    const font = await loadFont('resources/threejs/fonts/helvetiker_regular.typeface.json');  /* threejs.org: url */
-    const geometry = new TextGeometry('three.js', {
-      font: font,
-      size: 3.0,
-      depth: .2,
-      curveSegments: 12,
-      bevelEnabled: true,
-      bevelThickness: 0.15,
-      bevelSize: .3,
-      bevelSegments: 5,
-    });
-    const mesh = new THREE.Mesh(geometry, createMaterial());
-    geometry.computeBoundingBox();
-    geometry.boundingBox.getCenter(mesh.position).multiplyScalar(-1);
-
-    const parent = new THREE.Object3D();
-    parent.add(mesh);
-
-    addObject(-1, -1, parent);
-  }
-  doit();
-}
-
-

また、もう一つ違いがあります。私たちはテキストを、自身の中心の周りで回転させたかったのですが、 -three.jsはデフォルトで、テキストを左端中心に回転するよう作成します。 -これを回避するため、three.jsにジオメトリのバウンディングボックスの計算をさせることができます。 -バウンディングボックスのgetCenterメソッドを呼ぶことができるので、それにメッシュの位置オブジェクトに渡します。 -すると、getCenterが箱の中心をその位置にコピーします。このとき、位置オブジェクトも返すので、回転の中心が物体の中心になるように、オブジェクト全体の位置に対してmultiplyScalar(-1)を呼ぶことができます。

-

これだと、もし先の例のようにaddSolidGeometryを呼ぶと、 -再び位置が設定されてしまいますが、それはよくありませんよね。 -そのためこの例では、three.jsのシーングラフの標準的なノードであるObject3Dを作ります。 -Meshは同様にObject3Dを継承しています。 -別の記事でどのようにシーングラフが働くかカバーします。 -今はとりあえず、DOMノードのように、子ノードは親ノードと関連して描画されると知っていれば十分です。 -Object3Dを作成し、メッシュをその子にすることで、どこにでもObject3Dに配置し、 -先ほど設定した中心のオフセットを維持したままにできます。

-

こうしないと、テキストが中央からずれて回ってしまうことになります。

-

- -

-

左側のものは自身の中心の周りを回転していませんが、右側のものはそうなっていることに -注意してください。

-

もう一つの例外は、EdgesGeometryWireframeGeometryの、2つの直線に基づいた例です。 -addSolidGeometryを呼ぶ代わりに、このようにaddLineGeometryを呼んでいます。

-
function addLineGeometry(x, y, geometry) {
-  const material = new THREE.LineBasicMaterial({color: 0x000000});
-  const mesh = new THREE.LineSegments(geometry, material);
-  addObject(x, y, mesh);
-}
-
-

黒色のLineBasicMaterialを作り、次にLineSegmentsオブジェクトを作成しています。 -これはMeshのラッパーで、あなたが線分(線分あたり2点)を描画しようとしていることを -threeが知る手助けをします。

-

プリミティブのそれぞれは、作成時に渡すことができる複数のパラメーターを持っていて、 -ここで繰り返し説明するよりもこのドキュメントを覗いてもらうのが最善です。 -また、各形状の横にある上記のリンクをクリックすると、その形状のドキュメントに直接案内されます。

-

上記パターンに全然当てはまらないクラスの組があります。 -それはPointsMaterialPointsクラスです。PointsLineSegmentsに似ていて、 -GeometryBufferGeometryを引数に取ります。しかし、線の代わりに各頂点の点を描画します。 -使うためには、PointsMaterialも渡す必要があります。 -これは、点をどれくらい大きくするか決めるためsize を引数に取ります。

-
const radius = 7;
-const widthSegments = 12;
-const heightSegments = 8;
-const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-const material = new THREE.PointsMaterial({
-    color: 'red',
-    size: 0.2,     // in world units
-});
-const points = new THREE.Points(geometry, material);
-scene.add(points);
-
-
-
-
- -

カメラからの距離に関わらず点の大きさを同じにしたいなら、sizeAttenuation をfalseにすることで、サイズ変更を止めることができます。

-
const material = new THREE.PointsMaterial({
-    color: 'red',
-+    sizeAttenuation: false,
-+    size: 3,       // in pixels
--    size: 0.2,     // in world units
-});
-...
-
-
-
-
- -

もう一つ説明が必要な大切なことは、ほとんど全部の形状が、 -どのくらい細分化するか決めるための設定を持っていることです。 -球体のジオメトリが良い例かもしれません。 -球体は周囲と上下にどのくらい分割するかのパラメータがあります。 -例えば、

-
-
-
-
-
- -

最初の球体は、15セグメントまたは30個の三角形になる、周囲に5セグメント、高さ3です。 -二つ目の球体は、240セグメントまたは480個の三角形になる、周囲に24セグメント、高さ10です。です。 -最後の球体は、2500セグメントまたは5000個の三角形になる、周囲に50セグメント、高さ50です。

-

どのくらい分割が必要かは、みなさんが決めることです。 -多くのセグメントが必要なように見えるかもしれませんが、線を除去して、 -影をならすことで、このようになります。

-
-
-
-
-
- -

5000個の三角形からできる右側の球体が、たった480個の三角形からできる真ん中の球体よりも良いかは、明らかではありません。 -地球の地図のために1個の地球儀を作るときのように、もし少ない数の球体を描くだけなら、 -10000個の三角形の球体でも悪い選択ではありません。 -一方で、1000個の球体を書こうとしているなら、1000個の球体におのおの10000個の三角形が -かかり、一千万個の三角形になります。 -滑らかに動かすにはブラウザが一秒間に60フレーム描画する必要があるため、 -ブラウザは1秒間に6億個の三角形を描画する必要があります。 -それは計算が多すぎます。

-

選ぶのが簡単なときもあります。例えば、平面の細分化を選ぶこともできます。

-
-
-
-
- -

左側の四角形は2個の三角形からできています。右側の四角形は200個の三角形からできています。 -球体のときと異なり、四角形の場合だと、質的なトレードオフは全くありません。 -いくつかの用途で、たいてい四角形を改造したり歪めたりしたいと思っているときに、細分化するだけで良いでしょう。 -立方体も同様です。

-

みなさんの状況にふさわしいものを選びましょう。 -物体は、選んだ細分化が小さいほど、より滑らかに動いて、省メモリになることでしょう。 -あなたの特定の状況にふさわしい、正しいトレードオフは何か、決めなければいけません。

-

みなさんの用途に適した形状がないなら、例えば、.obj file -や.gltf fileからジオメトリを読み込むことができます。 -カスタムBufferGeometryを作ることもできます。

-

次は、threeのシーングラフの動き方と使い方を説明します。

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/rendering-on-demand.html b/manual/ja/rendering-on-demand.html deleted file mode 100644 index 9bf2b820b3c88f..00000000000000 --- a/manual/ja/rendering-on-demand.html +++ /dev/null @@ -1,213 +0,0 @@ - - - で要求されたレンダリング - - - - - - - - - - - - - -
-
-

で要求されたレンダリング

-
-
-
-

多くの人にとって当然かもしれませんが、ほとんどのThree.js exampleでは連続したレンダリングをします。 -言い換えると requestAnimationFrame ループ、または"rAF loop"ループは以下のようになります。

-
function render() {
-  ...
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

アニメーションする時は意味がありますがしない時はどうでしょう? -連続したレンダリングはデバイスの電力浪費になり、ポータブルデバイスを使用している場合はバッテリーを浪費します。

-

これを解決する最も明確な方法は、最初に一度レンダリングして何か変更された時だけレンダリングする事です。 -変更にはテクスチャやモデルの読込完了、外部ソースからのデータ受取、ユーザーによる設定やカメラ調整などその他の関連する入力などが含まれます。

-

レスポンシブデザインの記事を例に要求に応じてレンダリングするように修正してみましょう。

-

最初に OrbitControls を追加します。これで何かの変更を反映してレンダリングする事ができます。

-
import * as THREE from 'three';
-+import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-

次に以下のように設定します。

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-camera.position.z = 2;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

cubesのアニメーションは必要がないのでトラッキングは必要はありません。

-
-const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
--];
-+makeInstance(geometry, 0x44aa88,  0);
-+makeInstance(geometry, 0x8844aa, -2);
-+makeInstance(geometry, 0xaa8844,  2);
-
-

cubesをアニメーションさせるコードと requestAnimationFrame の呼出を削除する事ができます。

-
-function render(time) {
--  time *= 0.001;
-+function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
--  cubes.forEach((cube, ndx) => {
--    const speed = 1 + ndx * .1;
--    const rot = time * speed;
--    cube.rotation.x = rot;
--    cube.rotation.y = rot;
--  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
--requestAnimationFrame(render);
-
-

そして、もう一度レンダリングする必要があります。

-
render();
-
-

OrbitControls がカメラ設定を変更する時はレンダリングする必要があります。 -幸いな事に OrbitControls は何か変更された時に change イベントをdispatchします。

-
controls.addEventListener('change', render);
-
-

ウィンドウのリサイズ時の対応も必要です。 -前は連続したレンダリングで自動的な処理でしたが、ウィンドウのリサイズ時にレンダリングする必要があります。

-
window.addEventListener('resize', render);
-
-

これで要求されたらレンダリングする事ができます。

-

- -

-

OrbitControls には慣性のようなものを追加して動きを滑らかにするオプションがあります。 -これを有効にするには enableDamping プロパティをtrueに設定します。

-
controls.enableDamping = true;
-
-

enableDamping をオンにした状態で、render関数内で controls.update を呼び出す必要があります。 -これで動きを滑らかにする新しいカメラ設定を OrbitControls に与えてくれます。 -この設定は動きを滑らかにしてくれますが、無限ループになってしまうので change イベントから直接 render を呼び出す事はできません。 -controlsは change イベントを送信し render を呼び出します。 rendercontrols.update を呼び出します。 -controltrols.update は別の change イベントを送信します。

-

この問題は requestAnimationFrame を使い render を呼び出す事で解決できます。 -まだ新しいフレームが要求されていない場合、新しいフレームを要求するようにしなければなりません。

-
+let renderRequested = false;
-
-function render() {
-+  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  renderer.render(scene, camera);
-}
-render();
-
-+function requestRenderIfNotRequested() {
-+  if (!renderRequested) {
-+    renderRequested = true;
-+    requestAnimationFrame(render);
-+  }
-+}
-
--controls.addEventListener('change', render);
-+controls.addEventListener('change', requestRenderIfNotRequested);
-
-

リサイズにも requestRenderIfNotRequested を使うべきでしょう。

-
-window.addEventListener('resize', render);
-+window.addEventListener('resize', requestRenderIfNotRequested);
-
-

違いがわかりにくいかもしれません。以下のサンプルで矢印キーを使って移動したりドラッグして回転させてみて下さい。 -次にこのページの一番上のサンプルで同じ事をしてみて下さい。 -一番上のサンプルでは矢印キーを押したりドラッグしたりするとスナップし、以下のサンプルではスライドします。

-

- -

-

シンプルなlil-guiを追加し、GUIで値の変更時にレンダリングを要求してみましょう。

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

各キューブの色と×スケールを設定できるようにしましょう。 -色を設定するには照明の記事で作成した ColorGUIHelper を使います。

-

まずはGUIを作成する必要があります。

-
const gui = new GUI();
-
-

次に各キューブに対してフォルダを作成し、2つのコントロールを追加します。 -1つは material.color、もう1つは cube.scale.xです。

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const folder = gui.addFolder(`Cube${x}`);
-+  folder.addColor(new ColorGUIHelper(material, 'color'), 'value')
-+      .name('color')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.add(cube.scale, 'x', .1, 1.5)
-+      .name('scale x')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.open();
-
-  return cube;
-}
-
-

lil-guiには onChange メソッドがあり、GUIで値を変更時にコールバックを渡す事ができます。今回は requestRenderIfNotRequested をコールバックするだけです。 -folder.open でフォルダ展開できます。

-

- -

-

three.jsを連続したレンダリングでなく、要求に応じてレンダリングさせる方法のヒントになれば幸いです。 -three.jsを要求に応じてレンダリングするアプリ/ページはあまり一般的ではありませんが、three.jsを使用しているページの多くはゲームや3Dアニメーション、エディタ、3Dグラフ生成、商品カタログなどのアートです。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/rendertargets.html b/manual/ja/rendertargets.html deleted file mode 100644 index 105cf4c38d2456..00000000000000 --- a/manual/ja/rendertargets.html +++ /dev/null @@ -1,160 +0,0 @@ - - - のレンダーターゲット - - - - - - - - - - - - - -
-
-

のレンダーターゲット

-
-
-
-

レンダーターゲットとはレンダリングする先のテクスチャです。一度レンダリングすればテクスチャのように使うことができます。

-

簡単な例を作ってみましょう。レスポンシブデザインの記事にある例を試してみましょう。

-

レンダーターゲットへのレンダリングは通常のレンダリングとほぼ同じです。まずWebGLRenderTargetを作ります。

-
const rtWidth = 512;
-const rtHeight = 512;
-const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
-
-

CameraSceneを作ります。

-
const rtFov = 75;
-const rtAspect = rtWidth / rtHeight;
-const rtNear = 0.1;
-const rtFar = 5;
-const rtCamera = new THREE.PerspectiveCamera(rtFov, rtAspect, rtNear, rtFar);
-rtCamera.position.z = 2;
-
-const rtScene = new THREE.Scene();
-rtScene.background = new THREE.Color('red');
-
-

アスペクトをキャンバスのアスペクトではなくレンダーターゲットのアスペクトに設定したことに注意してください。レンダリング先のアスペクトに合わせるのが正解です。この例では立方体の側面につかうテクスチャにレンダリング先にします。立方体の側面ば正方形なのでアスペクトは1.0です。

-

いろいろ入れてみましょう。この例ではライトと3つの立方体をこの前の記事から使います。

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(-1, 2, 4);
-*  rtScene.add(light);
-}
-
-const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-*  rtScene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-*const rtCubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

前の記事のSceneCameraはそのままにしてあります。これらをキャンバスにレンダリングするために使います。空の空間をレンダリングしても意味がないのでとりあえず入れてあります。

-

レンダーターゲットとなるテクスチャを貼る立方体をシーンに追加します。

-
const material = new THREE.MeshPhongMaterial({
-  map: renderTarget.texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-
-

このシーンをレンダーターゲットにレンダリングします。

-
function render(time) {
-  time *= 0.001;
-
-  ...
-
-  // rotate all the cubes in the render target scene
-  rtCubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  // draw render target scene to render target
-  renderer.setRenderTarget(renderTarget);
-  renderer.render(rtScene, rtCamera);
-  renderer.setRenderTarget(null);
-
-

次にレンダーターゲットのテクスチャが貼られている立方体を追加したシーンをキャンバスにレンダリングします。

-
  // rotate the cube in the scene
-  cube.rotation.x = time;
-  cube.rotation.y = time * 1.1;
-
-  // render the scene to the canvas
-  renderer.render(scene, camera);
-
-

見てください!

-

- -

-

立方体が赤いのはレンダーターゲットのテクスチャとしてレンダリングしたrtScenebackgroundを赤でクリアーしたからです。

-

レンダーターゲットは色々な使い方ができます。シャドウもレンダーターゲットを使います。ピッキングもレンダーターゲットを使います。ポストプロセッシング効果もレンダーターゲットを使います。車のミラーを再現するために車の背後をレンダリングしたテクスチャを利用できますし、3Dゲームに出てくる監視モニターにも使うことができます。

-

WebGLRenderTargetを使う時にはいくつか注意点があります。

-
    -
  • デフォルトでWebGLRenderTargetは2つのテクスチャを作ります。

    -

    color textureとdepth (stencil) textureです。もし後者のテクスチャが必要なければオプションでオフにできます。

    -
      const rt = new THREE.WebGLRenderTarget(width, height, {
    -    depthBuffer: false,
    -    stencilBuffer: false,
    -  });
    -
    -
  • -
  • レンダーテクスチャのサイズを変更する必要があるかもしれません

    -

    上の例では512 x 512のサイズのレンダーテクスチャを作りました。通常はポストプロセッシングにおいてキャンバスと同じサイズのレンダーターゲットが必要になります。つまりキャンバスのサイズを変えたら同時にレンダーターゲットとレンダーターゲットに使うカメラのサイズも一緒に変える必要があります。

    -
    function render(time) {
    -  time *= 0.001;
    -
    -  if (resizeRendererToDisplaySize(renderer)) {
    -    const canvas = renderer.domElement;
    -    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    -    camera.updateProjectionMatrix();
    -
    -+    renderTarget.setSize(canvas.width, canvas.height);
    -+    rtCamera.aspect = camera.aspect;
    -+    rtCamera.updateProjectionMatrix();
    -}
    -
  • -
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/responsive.html b/manual/ja/responsive.html deleted file mode 100644 index 933ebbd4088ea2..00000000000000 --- a/manual/ja/responsive.html +++ /dev/null @@ -1,204 +0,0 @@ - - - のレスポンシブデザイン - - - - - - - - - - - - - -
-
-

のレスポンシブデザイン

-
-
-
-

これはthree.jsの2番目の連載記事です。 -最初の記事は Three.jsの基礎知識 でした。 -まだ読んでいない場合はそこから始めて下さい。

-

この記事はthree.jsアプリをどんな状況にもレスポンシブにする方法を説明します。 -一般的なレスポンシブ対応のWebページはデスクトップやタブレット、スマートフォンなど異なったディスプレイサイズに対応します。

-

three.jsの場合、さらに考慮すべき状況があります。例えば3Dエディターで左・右・上・下に何かを制御したい場合です。このドキュメントの真ん中にあるコードが一つの例です。 -最後のサンプルコードはCSSでサイズ指定なしのcanvasを使ってます。

-
<canvas id="c"></canvas>
-
-

このcanvasのデフォルトサイズは300 x 150です。 -Web上ではCSSでサイズ指定する事が推奨されています。 -CSSを追加しcanvasをWebページ一杯にしましょう。

-
<style>
-html, body {
-   margin: 0;
-   height: 100%;
-}
-#c {
-   width: 100%;
-   height: 100%;
-   display: block;
-}
-</style>
-
-

bodyのmarginはデフォルトで5ピクセルのためマージンを0にします。 -htmlとbodyの高さは100%にしウィンドウ一杯に設定します。 -そうしないとhtmlとbodyはbody内のコンテンツと同じぐらいのサイズにしかなりません。

-

次にbodyのコンテナーである id=c のelementが100%のサイズになるようにします。

-

最後にそのコンテナーの displayblock に設定します。canvasのdisplayのデフォルトは inline です。インライン要素は表示されているものに空白を追加してしまう事があります。このような場合はcanvasを block に設定するとこの問題は解消されます。

-

その結果がこちらにあります。

-

- -

-

canvasがページを埋め尽くすようになりましたが、2つ問題があります。 -1つはキューブが伸びています。キューブは立方体でなく箱のようなものです。高すぎて広がりすぎています。サンプルを開いてブラウザのウィンドウサイズをリサイズすると、キューブが伸びていて高すぎるのがわかります。

-

-

2つ目の問題は解像度が低い、または濃淡にムラがありぼやけて見える事です。ウィンドウを大きく引き伸ばすとこの問題がわかります。

-

-

まず引き伸びている問題を解決しましょう。そのためにはカメラのアスペクトをcanvasの表示サイズのアスペクトに設定する必要があります。canvasの clientWidthclientHeight を参照する事で設定を行う事ができます。

-

レンダーのループ処理を次のように更新します。

-
function render(time) {
-  time *= 0.001;
-
-+  const canvas = renderer.domElement;
-+  camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+  camera.updateProjectionMatrix();
-
-  ...
-
-

これでキューブが歪むのを止められます。

-

- -

-

サンプルを別ウィンドウで開きウィンドウのサイズを変更すると、キューブが縦にも横にも伸びていない事がわかるはずです。ウィンドウの大きさに関係なく、正しいアスペクトを保っています。

-

-

次はブロックノイズを修正していきましょう。

-

キャンバス要素には2つのサイズがあります。1つ目のサイズは、キャンバスがページに表示されるサイズです。それはCSSで設定しています。2つ目のサイズはキャンバス自体のピクセル数です。これは画像と何ら変わりありません。 -例えば、128 x 64ピクセルの画像を持っていて、CSSを使って400 x 200ピクセルで表示する事ができるかもしれません。

-
<img src="some128x64image.jpg" style="width:400px; height:200px">
-
-

キャンバス内部のサイズ、その解像度は描画バッファサイズと呼ばれます。 -three.jsでは renderer.setSize を呼び出す事でキャンバスの描画バッファサイズを設定する事ができます。 -どのサイズを選ぶべきでしょうか?一番わかりやすい答えは"キャンバスが表示されているサイズと同じ"です。 -もう一度キャンバスの clientWidthclientHeight を見てみましょう。

-

レンダラーのキャンバスが表示されているサイズになっていないかどうかを確認し、表示されている場合はサイズを設定する関数を書いてみましょう。

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
-  const width = canvas.clientWidth;
-  const height = canvas.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

キャンバスのサイズを変更する必要があるかどうかをチェックしています。キャンバスのサイズを変更する事は、キャンバスの仕様の興味深い部分であり、すでに必要なサイズになっている場合は同じサイズを設定しない方が良いでしょう。

-

サイズを変更する必要があるかどうかわかったら、次に renderer.setSize を呼び出して新しい幅と高さを渡します。最後に false を渡す事が重要です。

-

デフォルトでは renderer.setSize はキャンバスのCSSサイズを設定しますが、これは私たちが望んでいるものではありません。ブラウザは他の全ての要素に対して、CSSを使用して要素の表示サイズを決定するという方法で動作し続けてほしいのです。3つの要素で使用されるキャンバスが他の要素と異なるのは避けたいのです。

-

この関数はキャンバスのサイズが変更された場合、trueを返す事に注意して下さい。この関数を使って他にも更新すべき事があるかどうかをチェックする事ができます。この関数を使ってレンダーのループ処理を修正してみましょう。

-
function render(time) {
-  time *= 0.001;
-
-+  if (resizeRendererToDisplaySize(renderer)) {
-+    const canvas = renderer.domElement;
-+    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.updateProjectionMatrix();
-+  }
-
-  ...
-
-

キャンバスの表示サイズが変更されて resizeRendererToDisplaySizetrue を返した場合のみ、カメラのアスペクトを設定します。

-

- -

-

これでキャンバスの表示サイズに合った解像度でレンダリングされるようになりました。

-

CSSにリサイズ処理を任せた場合のポイントを明確にするために、このコードを 分離した .js ファイル に入れてみましょう。 -ここではCSSがサイズを選択するいくつかのサンプルがあります。 -それらが動作するようにゼロからコードを変更しなければならなかった事に気づくでしょう。

-

文章の段落の真ん中にキューブを置いてみましょう。

-

- -

-

エディタスタイルのレイアウトで右側のコントロールエリアのサイズを変更できるようにしたのと同じコードです。

-

- -

-

注目すべき重要な部分はコードが変更されていない事です。HTMLとCSSだけが変更されました。

-

HD-DPIディスプレイの取り扱い

-

HD-DPIとは高解像度ディスプレイの略です。 -最近ではほとんどのスマートフォンと同じくらい、Macや多くのWindowsマシンで採用されています。

-

ブラウザでの動作方法は、CSSを使用してディスプレイの高解像度に関係なく同じサイズを設定する事です。ブラウザはテキストをさらに詳細にレンダリングしますが、物理的なサイズは同じです。

-

three.jsでHD-DPIを扱う方法は色々あります。

-

1つ目の方法は特に何もしない事です。これは間違いなく最も一般的な方法です。3DグラフィックのレンダリングにはたくさんのGPUの処理パワーが必要です。モバイルのGPUは少なくとも2018年時点ではデスクトップよりも電力が少ないが、それでも携帯電話は非常に高解像度のディスプレイを搭載している事が多いです。現在の上位機種はHD-DPI比が3倍という事は、非HD-DPIディスプレイの1ピクセルごとに9ピクセルを持っている事を意味します。つまり、9倍のレンダリングをしなければならないという事です。

-

9倍のピクセルを計算するのは大変な作業なので、コードをそのままにしておくと1倍のピクセルを計算して、ブラウザは3倍のサイズ(3x x 3x = 9xピクセル)で描画します。

-

重いthree.jsアプリの場合はこれが必要でしょう。そうしないとフレームレートが遅くなる可能性があります。

-

デバイスの解像度でレンダリングしたい場合、three.jsにはいくつかのデバイスを変更する方法があります。

-

1つは renderer.setPixelRatio でthree.jsに解像度の乗数を伝える事です。 -CSSピクセルからデバイスピクセルへの乗数をブラウザに伝え、それをthree.jsに渡します。

-
 renderer.setPixelRatio(window.devicePixelRatio);
-

renderer.setSize を呼び出し後、要求されたサイズに渡されたピクセル比を乗算したものが使用されます。これは強く非推奨です。以下を参照して下さい。

-

もう1つの方法は、キャンバスのサイズを変更する時に自分で設定する事です。

-
    function resizeRendererToDisplaySize(renderer) {
-      const canvas = renderer.domElement;
-      const pixelRatio = window.devicePixelRatio;
-      const width  = Math.floor( canvas.clientWidth  * pixelRatio );
-      const height = Math.floor( canvas.clientHeight * pixelRatio );
-      const needResize = canvas.width !== width || canvas.height !== height;
-      if (needResize) {
-        renderer.setSize(width, height, false);
-      }
-      return needResize;
-    }
-
-

この2つ目の方法の方が客観的には優れています。なぜかと言うと私が求めるものを手に入れる事ができるからです。

-

three.jsを使っていると実際のキャンバスの描画バッファのサイズを指定します。例えば、後処理フィルタを作成する場合などです。 -または gl_FragCoord にアクセスするシェーダを作成している場合、あるいは2Dキャンバスに描画するためのスクリーンショット、またはGPUピッキング用のピクセルを読み込んだ場合などに使用する事ができます。

-

setPixelRatio を使うと要求したサイズよりも実際のサイズが違ってしまう事が多々あります。いつ要求したサイズが使えるか、いつThree.jsの実際のサイズが使えるか推測しなければなりません。 -これを自分で行う事で使用されているサイズが要求したサイズである事を常に知る事ができます。 -裏で魔法がかかっているという特殊ケースではありません。

-

上のコードを使った例です。

-

- -

-

違いがわかりにくいかもしれませんが、HD-DPIディスプレイをお持ちの方はこのサンプルを上のサンプルと比較してみて下さい。エッジがより鮮明になっている事がわかると思います。

-

基礎な内容ですがこの記事ではとても基本的な所を取り上げました。次はthree.jsが提供する基本的なプリミティブについて簡単に説明します。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/scenegraph.html b/manual/ja/scenegraph.html deleted file mode 100644 index e5ca1faedc0a56..00000000000000 --- a/manual/ja/scenegraph.html +++ /dev/null @@ -1,449 +0,0 @@ - - - のシーングラフ - - - - - - - - - - - - - -
-
-

のシーングラフ

-
-
-
-

この記事はthree.jsについてのシリーズ記事の一つです。 -最初の記事はThree.jsの基礎です。 -まだ読んでない人は、そちらから先に読んでみるといいかもしれません。

-

Three.jsの核心は間違いなくシーングラフです。 -3Dエンジンのシーングラフは、各ノードがローカルな空間を表現している、グラフ内のノードの階層です。

-

-

抽象的なので、例をいくつか挙げてみましょう。

-

例の一つは太陽系、太陽・地球・月でしょうか。

-

-

地球は太陽を回っています。月は地球を回っています。 -月は地球の周りを円を描いて移動しています。月から見ると、地球の"ローカルな空間"を回っていることになります。 -太陽との相対的な動きは、月の視点から見るとクレイジーな螺旋のような曲線に見えますが、単に地球のローカルな空間を周回していると捉える必要があります。

-

- -
- -

-

別の考え方をしてみます。地球が地軸の周りを自転していることも、太陽の周りを公転していることも、 -地球に住んでいるあなたが考える必要はありません。 -皆さんは全くもって地球が動きも回りもしていないかのように、 -歩いたり、ドライブしたり、泳いだり、走ったりするだけです。 -地球の"ローカルな空間"で歩いたり、ドライブしたり、泳いだり、走ったり、そして生活したりしていても、みなさんは太陽と相対的に、地球の上で1,600km/hの速さで回転し、太陽の周りを107,200km/hの速度で回っています。 -太陽系上のみなさんの位置は、前述した月と同じようなものですが、気にする必要はありません。 -みなさんは地球の"ローカルな空間"で、地球との相対的な位置だけを心配していればいいのです。

-

一歩進みましょう。私たちは太陽と地球と月の図を作りたいと想像してみてください。 -まず、太陽から始めましょう。ただ球体を作り原点に置くだけです。 -シーングラフを使う方法の演習として、太陽、地球、月を使うことを、気に留めておいてください。 -もちろん、現実の太陽、地球、月は物理学に従いますが、演習目的なので、シーングラフで代用します。

-
// an array of objects whose rotation to update
-const objects = [];
-
-// use just one sphere for everything
-const radius = 1;
-const widthSegments = 6;
-const heightSegments = 6;
-const sphereGeometry = new THREE.SphereGeometry(
-    radius, widthSegments, heightSegments);
-
-const sunMaterial = new THREE.MeshPhongMaterial({emissive: 0xFFFF00});
-const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
-sunMesh.scale.set(5, 5, 5);  // make the sun large
-scene.add(sunMesh);
-objects.push(sunMesh);
-
-

とても少ないポリゴンからできた球体を使います。緯度方向にたった6分割です。 -これで、回転していることが見やすくなります。

-

同じ球体を全ての球体に使いまわすつもりなので、太陽のメッシュの大きさを5倍にしておきます。

-

また、phong materialのemissive属性を黄色に設定します。 -phong materialのemissive属性は、基本的に、光が当たっていない表面に描かれる色です。 -光源はその色に付け加えられます。

-

次に、シーンの真ん中に1つ点光源を置きましょう。後ほど、より詳細に点光源について説明しますが、 -一点から発せられる明かりというのが、とりあえずの簡単な説明です。

-
{
-  const color = 0xFFFFFF;
-  const intensity = 500;
-  const light = new THREE.PointLight(color, intensity);
-  scene.add(light);
-}
-
-

見やすくするために、直接原点を見下ろすようにカメラを置きましょう。 -最も簡単な方法は lookAt関数を使うことです。 -lookAt関数は、引数に渡した位置を「見る」ようにカメラを向けます。 -その前に、カメラの上部がどの方向を向いているか、もしくは、 -カメラにとってどの方向が"上"なのかを、カメラに伝える必要があります。 -ほとんどの場合、Y軸の正が上で十分ですが、 -今は見下ろしているので、Z軸の正が上だとカメラに伝える必要があります。

-
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-camera.position.set(0, 50, 0);
-camera.up.set(0, 0, 1);
-camera.lookAt(0, 0, 0);
-
-

レンダリングループの中で、前の例を参考にして、以下のコードで、objects配列内の全てのオブジェクトを回転させています。

-
objects.forEach((obj) => {
-  obj.rotation.y = time;
-});
-
-

sunMeshobjects配列に追加したので、回転します。

-

- -

-

さて、地球を追加してみましょう。

-
const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
-earthMesh.position.x = 10;
-scene.add(earthMesh);
-objects.push(earthMesh);
-
-

青いマテリアルを作っていますが、黒背景に対して目立つよう、 -emissiveに少し青色を設定します。

-

earthMeshを作るため、新しく作った青色のearthMaterialと、先と同じsphereGeometryを使います。 -それを太陽の10ユニット左側に置き、シーンに追加します。 -これはobjects配列にそれを追加されたので、同様に回転します。

-

- -

-

太陽と地球の両方が回転して見えますが、地球は太陽の周りを公転していません。 -地球を太陽の子要素にしてみましょう。

-
-scene.add(earthMesh);
-+sunMesh.add(earthMesh);
-
-

そして...

-

- -

-

なにが起きましたか?なぜ地球が太陽と同じ大きさで、こんなに離れているのでしょうか。 -地球を見るためには、実際のところ、カメラを50ユニット上から、150ユニット上に動かす必要がありました。

-

earthMeshsunMeshの子要素としました。 -sunMeshsunMesh.scale.set(5, 5, 5)によって5倍に大きさを設定しています。 -よって、sunMeshのローカルな空間は5倍大きくなりました。 -その空間におかれるあらゆるものは5倍されるのです。 -つまり、地球が5倍大きくなり、太陽からの距離も5倍(earthMesh.position.x = 10)になったのです。

-

シーングラフは、このようになります。

-

-

これを修正するため、シーングラフに空のノードを追加しましょう。 -そして、太陽と地球の両方をそのノードの子要素にしましょう。

-
+const solarSystem = new THREE.Object3D();
-+scene.add(solarSystem);
-+objects.push(solarSystem);
-
-const sunMaterial = new THREE.MeshPhongMaterial({emissive: 0xFFFF00});
-const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
-sunMesh.scale.set(5, 5, 5);
--scene.add(sunMesh);
-+solarSystem.add(sunMesh);
-objects.push(sunMesh);
-
-const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
-earthMesh.position.x = 10;
--sunMesh.add(earthMesh);
-+solarSystem.add(earthMesh);
-objects.push(earthMesh);
-
-

ここでObject3Dを作りました。Meshのように、シーングラフのノードですが、Meshとは異なり、マテリアルやジオメトリを持ちません。 -ただローカルな空間を表現するだけです。

-

新しいシーングラフは、このようになります。

-

-

sunMeshearthMeshは共にsolarSystemの子要素です。3つ全部が回転していますが、 -いまearthMeshsunMeshの子要素ではないので、5倍に拡大されません。

-

- -

-

とてもよくなりました。地球は太陽よりも小さく、太陽の周りを公転しつつ、自転しています。

-

続けて、同様の方法で月を追加してみましょう。

-
+const earthOrbit = new THREE.Object3D();
-+earthOrbit.position.x = 10;
-+solarSystem.add(earthOrbit);
-+objects.push(earthOrbit);
-
-const earthMaterial = new THREE.MeshPhongMaterial({color: 0x2233FF, emissive: 0x112244});
-const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
--solarSystem.add(earthMesh);
-+earthOrbit.add(earthMesh);
-objects.push(earthMesh);
-
-+const moonOrbit = new THREE.Object3D();
-+moonOrbit.position.x = 2;
-+earthOrbit.add(moonOrbit);
-
-+const moonMaterial = new THREE.MeshPhongMaterial({color: 0x888888, emissive: 0x222222});
-+const moonMesh = new THREE.Mesh(sphereGeometry, moonMaterial);
-+moonMesh.scale.set(.5, .5, .5);
-+moonOrbit.add(moonMesh);
-+objects.push(moonMesh);
-
-

再び、描画されないシーングラフのノードを追加しました。これは、earthOrbitと呼ばれるObject3Dです。 -そして、このノードにearthMeshmoonMeshの両方を追加しました。 -新しいシーングラフは、このようになります。

-

-

そして、このように描画されます。

-

- -

-

記事の上部でお見せした螺旋のパターンに沿った月が見えます。 -しかし、手動で操作する必要はありませんでした。 -ただ、シーングラフを設定しただけです。

-

シーングラフのノードが分かるような、なにかを描写すると、便利なことがあります。 -Three.jsはこれをするために、helpfulとか、helpersとかがあります。

-

一つはAxesHelperです。 -ローカルなXYZ軸を表す -3つの線を描画します。 -私たちが作った全てのノードに加えましょう。

-
// add an AxesHelper to each node
-objects.forEach((node) => {
-  const axes = new THREE.AxesHelper();
-  axes.material.depthTest = false;
-  axes.renderOrder = 1;
-  node.add(axes);
-});
-
-

私たちの場合、たとえ球体の内部であったとしても、軸を表示させたいです。 -これをするために、マテリアルのdepthTestをfalseにします。 -これによって、軸がなにかの内部に描画されているかどうかチェックしなくなります。 -全ての球体の後に描画されるように、renderOrderも1に設定します(デフォルト値は0です)。 -そうしないと、球体が軸の上に描画され、軸を覆ってしまう可能性があります。

-

- -

-

x (赤)z (青)の -軸が見えます。私たちはオブジェクトをまっすぐ見下ろしていて、オブジェクトはy軸を中心に -回転しているので、y (緑)軸があまり見えません。

-

位置が重なった軸が2組あるので、見づらいかもしれません。 -sunMeshsolarSystemは同じ場所にあります。 -同様に、earthMeshearthOrbitは同じ場所にあります。 -各ノードに対してオン/オフできるように、簡単な操作を加えてみましょう。 -そのついでに、GridHelper というヘルパー関数も追加しておきましょう。 -これはX,Z平面に2次元グリッドを作ります。デフォルトでは、グリッドは10x10ユニットです。

-

lil-guiも使います。 -これはthree.jsプロジェクトでとても一般的なUIライブラリです。 -lil-guiはオブジェクトとそのオブジェクトの属性名を受け取り、 -属性の型に基づいて、自動的にその属性を操作するUIを作成します。

-

それぞれのノードに対して、GridHelperAxesHelperの両方を作りたいです。 -それぞれのノートにラベルが必要なので、古いループを削除し、 -各ノードにhelperを加える関数を呼ぶ形式にします。

-
-// add an AxesHelper to each node
--objects.forEach((node) => {
--  const axes = new THREE.AxesHelper();
--  axes.material.depthTest = false;
--  axes.renderOrder = 1;
--  node.add(axes);
--});
-
-+function makeAxisGrid(node, label, units) {
-+  const helper = new AxisGridHelper(node, units);
-+  gui.add(helper, 'visible').name(label);
-+}
-+
-+makeAxisGrid(solarSystem, 'solarSystem', 25);
-+makeAxisGrid(sunMesh, 'sunMesh');
-+makeAxisGrid(earthOrbit, 'earthOrbit');
-+makeAxisGrid(earthMesh, 'earthMesh');
-+makeAxisGrid(moonMesh, 'moonMesh');
-
-

makeAxisGridは、lil-guiをハッピーにするAxisGridHelperクラスを作ります。 -前述したように、lil-guiは、オブジェクトの名前が付いた属性を操作するUIを自動的に生成します。 -属性の型に応じて異なるUIが作成されます。 -チェックボックスを作って欲しいので、bool属性を指定する必要があります。 -しかし、軸とグリッドの両方を一つの属性で表示/非表示にしたいので、 -属性のgetterとsetterを持ったクラスを作成します。 -この方法で、lil-guiに一つの属性を操作するように思わせることができますが、 -内部的には各ノードにAxesHelperGridHelperの両方のvisible属性を設定することができます。

-
// Turns both axes and grid visible on/off
-// lil-gui requires a property that returns a bool
-// to decide to make a checkbox so we make a setter
-// and getter for `visible` which we can tell lil-gui
-// to look at.
-class AxisGridHelper {
-  constructor(node, units = 10) {
-    const axes = new THREE.AxesHelper();
-    axes.material.depthTest = false;
-    axes.renderOrder = 2;  // after the grid
-    node.add(axes);
-
-    const grid = new THREE.GridHelper(units, units);
-    grid.material.depthTest = false;
-    grid.renderOrder = 1;
-    node.add(grid);
-
-    this.grid = grid;
-    this.axes = axes;
-    this.visible = false;
-  }
-  get visible() {
-    return this._visible;
-  }
-  set visible(v) {
-    this._visible = v;
-    this.grid.visible = v;
-    this.axes.visible = v;
-  }
-}
-
-

注意することは、AxesHelperrenderOrderを2に設定し、GridHelperには1を設定することです。 -こうすることで、軸はグリッドの後に描画されます。 -そうしないと、グリッドが軸を上書きしてしまうかもしれません。

-

- -

-

solarSystemのチェックをオンにすると、上で設定したように、 -どのように地球が中心からちょうど10ユニットにあるか分かるでしょう。 -地球がsolarSystemローカルな空間にどのように存在するか分かります。 -同様に、もしearthOrbitのチェックをオンにすると、 -どのように月がearthOrbitローカルな空間の中心から、ちょうど2ユニットあるか分かるでしょう。

-

もう少しシーングラフの例を紹介します。 -簡単なゲームの世界の自動車は、このようなシーングラフだとしましょう。

-

-

もし車のbody全体を動かすと、それに伴ってwheelsが動くでしょう。 -もしbodyにwheelsとは別にバウンドして欲しいとすると、 -bodyとwheelsを、車のフレームを表す"frame"ノードの子要素にできます。

-

別の例はゲームの世界の人間です。

-

-

とても複雑な人間のシーングラフを見てください。 -実際は、上記のシーングラフは単純化されています。 -例えば、全ての手の指(少なくとも28ノード)、全ての足の指(さらに28ノード)、 -加えて顔と顎、目、そしてもっと様々な部位もカバーするように、グラフを拡張できるかもしれません。

-

もう少し複雑なシーングラフを作りましょう。戦車を作ります。 -戦車は6つの車輪と砲塔があります。この戦車はある道筋に沿って走ります。 -そこら中を移動する球体があり、戦車はその球体を狙うとしましょう。

-

これがシーングラフです。メッシュは緑色、Object3Dは青色、明かりは金色、カメラは紫色です。 -シーングラフに追加されていないカメラが一つあります。

-
- -

コードを見て、これらのノードの設定を確認してください。

-

ターゲット、つまり戦車が狙っているものとして、targetOrbit(Object3D) があります。 -これはちょうど前述のearthOrbitと同じように回転します。 -targetOrbitの子要素であるtargetElevation (Object3D)は、 -targetOrbitからのオフセットと基準となる高さを提供します。 -この子要素には、targetElevationに対して相対的に浮き沈みする、targetBobと呼ばれるObject3Dがあります。 -最後に、targetMeshがあります。回転させて色を変えることができる、ただの立方体です。

-
// move target
-targetOrbit.rotation.y = time * .27;
-targetBob.position.y = Math.sin(time * 2) * 4;
-targetMesh.rotation.x = time * 7;
-targetMesh.rotation.y = time * 13;
-targetMaterial.emissive.setHSL(time * 10 % 1, 1, .25);
-targetMaterial.color.setHSL(time * 10 % 1, 1, .25);
-
-

戦車には、tankと呼ばれるObject3Dがあります。 -これを使って戦車の子要素をすべて移動させることができます。 -コードではSplineCurveを使っています。これは曲線に沿った位置を求めることができます。 -0.0は曲線の始点です。1.0は曲線の終点です。これにより、戦車がある現在地を求めます。 -次に、カーブの少し下の位置を求めて、Object3D.lookAtを使い、戦車をその方向に向けます。

-
const tankPosition = new THREE.Vector2();
-const tankTarget = new THREE.Vector2();
-
-...
-
-// move tank
-const tankTime = time * .05;
-curve.getPointAt(tankTime % 1, tankPosition);
-curve.getPointAt((tankTime + 0.01) % 1, tankTarget);
-tank.position.set(tankPosition.x, 0, tankPosition.y);
-tank.lookAt(tankTarget.x, 0, tankTarget.y);
-
-

戦車のてっぺんに付いている砲塔は、戦車の子要素なので自動的に動きます。 -ターゲットの方を向かせるのに、ターゲットの位置を求め、次に再びObject3D.lookAtを使うだけです。

-
const targetPosition = new THREE.Vector3();
-
-...
-
-// face turret at target
-targetMesh.getWorldPosition(targetPosition);
-turretPivot.lookAt(targetPosition);
-
-

turretCameraturretMeshの子要素なので、砲塔と一緒に上下に動き、回転します。

-
// make the turretCamera look at target
-turretCamera.lookAt(targetPosition);
-
-

targetBobの子要素であるtargetCameraPivotもあります。これはターゲットと一緒に浮遊します。 -戦車に狙いを定めましょう。targetCameraにターゲット自身に高さを合わせるためです。 -もしカメラをtargetBobの子要素にして、カメラ自身に狙いを定めさせただけだと、 -カメラがターゲットの内側に入り込んでしまうでしょう。

-
// make the targetCameraPivot look at the tank
-tank.getWorldPosition(targetPosition);
-targetCameraPivot.lookAt(targetPosition);
-
-

最後に、全ての車輪を回転させます。

-
wheelMeshes.forEach((obj) => {
-  obj.rotation.x = time * 3;
-});
-
-

初期化時に、4つ全てのカメラの配列を設定します。

-
const cameras = [
-  { cam: camera, desc: 'detached camera', },
-  { cam: turretCamera, desc: 'on turret looking at target', },
-  { cam: targetCamera, desc: 'near target looking at tank', },
-  { cam: tankCamera, desc: 'above back of tank', },
-];
-
-const infoElem = document.querySelector('#info');
-
-

描画時にカメラを周回させます。

-
const camera = cameras[time * .25 % cameras.length | 0];
-infoElem.textContent = camera.desc;
-
-

- -

-

シーングラフの動作と、使い方のアイデアを、この例から得られればと思います。 -Object3Dノードを作り、物体をその子要素にすることは、three.jsのような3Dエンジンを上手く使うために -重要なステップです。 -思い通りになにかを動かしたり回転させたりすることは、しばしば複雑な数学が必要に見えるかもしれません。 -例えばシーングラフなしで、月の動きを操作したり、車の車体に対して壮太知的に車輪を置いたりすることは、 -とても難しいかもしれません。しかし、シーングラフを使うことで、とても簡単になるのです。

-

次はマテリアルを説明します

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/setup.html b/manual/ja/setup.html deleted file mode 100644 index 032f29b59862eb..00000000000000 --- a/manual/ja/setup.html +++ /dev/null @@ -1,76 +0,0 @@ - - - のセットアップ - - - - - - - - - - - - - -
-
-

のセットアップ

-
-
-
-

これはthree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識でした。 -まだ読んでない人はそこから読んでみるといいかもしれません。

-

先に進む前に開発環境のセットアップの話をする必要があります。特にセキュリティ上の理由から、WebGLはハードディスクから直接画像を扱う事ができません。開発をするためにはWebサーバーを利用する必要があります。幸運な事に開発用のWebサーバーをセットアップし利用する事は非常に簡単です。

-

まず最初にこのサイト全体をこのリンクからダウンロードする事ができます。 -ダウンロードしたらzipファイルをダブルクリックで解凍して下さい。

-

次にシンプルなWebサーバーの1つをダウンロードします。 -ユーザーインターフェースのあるWebサーバーをお望みならServezがあります。

-

- -
- -

-

ファイルを解凍してフォルダを指定し、"Start"をクリックしてからブラウザでhttp://localhost:8080/を表示するか、またはサンプルを閲覧したい場合はhttp://localhost:8080/threejsにアクセスして下さい。

-

Servezのサービスを停止するにはstopを選ぶか、Servezを終了します。

-

コマンドラインが好きな方は(私はそうしてる)、別の方法としてnode.jsを使う事もできます。

-

ダウンロードしてインストールし、コマンドプロンプト / コンソール / ターミナルウィンドウを開きます。WindowsのNode.jsインストーラーで追加した場合、"Node Command Prompt"を選択する必要があります。

-

servezをインストールするには、次のように入力します。

-
npm -g install servez
-

もしMacを使ってる場合は以下を入力します。

-
sudo npm -g install servez
-

次に以下を入力します。

-
servez path/to/folder/where/you/unzipped/files
-

または、私と同じであれば以下を入力します。

-
cd path/to/folder/where/you/unzipped/files
-servez
-

そして、以下のように表示されるはずです。

-

- -
- -

-

ブラウザでhttp://localhost:8080/にアクセスして下さい。

-

もしパスを指定しなかった場合、servezは現在のフォルダをserveします。

-

これらのオプションが好きでない場合、他にもたくさんのシンプルなサーバーがあります

-

これでサーバーのセットアップが完了したのでテクスチャのページに移動しましょう。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/shadertoy.html b/manual/ja/shadertoy.html deleted file mode 100644 index 52d1e755477ac3..00000000000000 --- a/manual/ja/shadertoy.html +++ /dev/null @@ -1,389 +0,0 @@ - - - とShadertoy - - - - - - - - - - - - - -
-
-

とShadertoy

-
-
-
-

Shadertoyは凄いシェーダーの実験場で有名なサイトです。よく聞かれるのがThree.jsでShadertoyのシェーダーを使う方法です。

-

シェーダーのおもちゃと呼ばれている理由を認識する事が大切です。 -一般的にshadertoyのシェーダーはベストプラクティスではありません。 -むしろ、dwitter (140文字でコードを書く)やjs13kGames (13k以下でゲームを作る)のような楽しいチャレンジです。

-

Shadertoyの場合のパズルは、ピクセルに何か面白いものを描画する関数を書く事です。 -それは楽しいチャレンジで、多くの投稿は凄いシェーダーです。 -しかし、それはベストプラクティスではありません。

-

街全体を描く凄いshadertoyシェーダーで比較してみましょう。

-
- -

上記のシェーダーは私のPCではフルスクリーンだと1秒間に約5フレームで動作します。 -Citiesのようなゲーム: スカイラインとは対照的です。

-
- -

このゲームはテクスチャと三角形の建物を描画する伝統的な技術を使用しており、同じマシンで1秒間に30~60フレーム動作します。

-

それでもthree.jsでShadertoyのシェーダーを使ってみましょう。

-

以下は2019年1月現在でshadertoy.comで"New"を選ぶした時のデフォルトのshadertoyシェーダーです。

-
// By iq: https://www.shadertoy.com/user/iq
-// license: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    // Normalized pixel coordinates (from 0 to 1)
-    vec2 uv = fragCoord/iResolution.xy;
-
-    // Time varying pixel color
-    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-
-    // Output to screen
-    fragColor = vec4(col,1.0);
-}
-
-

シェーダーを理解する上で重要な事の1つは、特殊な型を含む3D数学用に設計されたGLSL (Graphics Library Shading Language)と呼ばれる言語で書かれている事です。 -上記コードでは vec4vec2vec3 のような特殊な型があります。 -vec2 は2つの値を持ち vec3 は3つ、vec4 は4つの値を持ちます。 -たくさんの方法で引数を指定できます。 -例えば以下のように xyzw を使うのが最も一般的です。

-
vec4 v1 = vec4(1.0, 2.0, 3.0, 4.0);
-float v2 = v1.x + v1.y;  // adds 1.0 + 2.0
-
-

JavaScriptとは異なり、GLSLはC/C++のように変数の型を宣言しなければなりません。 -var v = 1.2; ではなく float v = 1.2; となり v は浮動小数点数です。

-

GLSLを詳しく解説するとこの記事で紹介している以上の事ができます。 -GLSLの簡単な概要はこの記事を参照して下さい。 -The Book of Shadersの連載記事の後に続くかもしれません。

-

2019年1月現在ではshadertoy.comフラグメントシェーダー のみ使えます。 -フラグメントシェーダーの役割は、ピクセルの位置が与えられた時にそのピクセルの色を出力します。

-

上記の関数ではシェーダーに fragColor という out パラメーターがあります。 -outoutput の略です。 -outは関数が値を提供する事を意味するパラメーターです。 -これを何か他の色に設定します。

-

また、in (入力用) パラメーターとして fragCoord があります。 -これは描画しようとしているピクセル座標です。座標によって色を決めます。 -描画先のキャンバスが400 x 300ピクセルの場合、この関数は400 x 300回つまり12万回呼ばれます。 -毎回 fragCoord は別のピクセル座標になります。

-

コードに未定義の変数が2つ使用されています。 -1つは iResolution です。これはキャンバスの解像度です。 -キャンバスが400 x 300の場合、iResolution は400, 300になります。 -ピクセル座標が変化すると uv はテクスチャ全体で0.0 〜 1.0の間で変化します。 -正規化された値を使い動作させると物事が単純になる事が多く、shadertoyのシェーダーの大部分は正規化したものから始まります。

-

コードに定義されていないもう1つの変数は iTime です。 -これはページが読み込まれてからの時間を秒単位で表します。

-

シェーダの専門用語では、これらのグローバル変数は ユニフォーム(uniform) 変数と呼ばれています。 -この変数は変更されないため ユニフォーム と呼ばれ、シェーダーの1回のイテレーションから次のイテレーションまで同じ状態を保ちます。 -ここで注意したいのはそれらは全てshadertoy特有のものです。 -これらは オフィシャルな GLSL変数ではありません。 -それらはshadertoy側で作った変数です。

-

Shadertoyのドキュメントを見ると、さらにいくつか特有の定義があります。 -とりあえず、上記のシェーダーで使われている2つを処理するコードを書いてみましょう。

-

まずはキャンバスを塗りつぶす1枚の平面を作ってみましょう。 -まだ読んでいない方は背景とスカイボックスの記事でこのようにしましたので、その例を参考に立方体を削除してみましょう。 -かなり短いコードなので全体を紹介します。

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const camera = new THREE.OrthographicCamera(
-    -1, // left
-     1, // right
-     1, // top
-    -1, // bottom
-    -1, // near,
-     1, // far
-  );
-  const scene = new THREE.Scene();
-  const plane = new THREE.PlaneGeometry(2, 2);
-  const material = new THREE.MeshBasicMaterial({
-      color: 'red',
-  });
-  scene.add(new THREE.Mesh(plane, material));
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render() {
-    resizeRendererToDisplaySize(renderer);
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-
-

背景とスカイボックスの記事で説明したように、これらのパラメーターを持つ OrthographicCamera と2の長さの平面がキャンバスを塗り潰します。 -平面は赤の MeshBasicMaterial を使用しているため、赤いキャンバスが表示されます。

-

- -

-

これで動作するようになったので、shadertoyシェーダーを追加してみましょう。

-
const fragmentShader = `
-#include <common>
-
-uniform vec3 iResolution;
-uniform float iTime;
-
-// By iq: https://www.shadertoy.com/user/iq
-// license: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    // Normalized pixel coordinates (from 0 to 1)
-    vec2 uv = fragCoord/iResolution.xy;
-
-    // Time varying pixel color
-    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-
-    // Output to screen
-    fragColor = vec4(col,1.0);
-}
-
-void main() {
-  mainImage(gl_FragColor, gl_FragCoord.xy);
-}
-`;
-
-

上記では2つのユニフォーム変数を宣言しました。 -そして、shadertoyからGLSLのシェーダーコードを追加しました。 -最後に mainImage を呼び出し、gl_FragColorgl_FragCoord.xy を渡します。 -gl_FragColor はオフィシャルのグローバル変数でシェーダーが現在のピクセルに設定する色を指定します。 -gl_FragCoord は現在の色を選択しているピクセルの座標を教えてくれる、もう1つのオフィシャルなグローバル変数です。

-

次にシェーダーに値を設定できるようにThree.jsのユニフォームを設定します。

-
const uniforms = {
-  iTime: { value: 0 },
-  iResolution:  { value: new THREE.Vector3() },
-};
-
-

Three.jsの各ユニフォームには value パラメータがあります。 -この値はユニフォームの型と一致してなければなりません。

-

フラグメントシェーダーとユニフォームの両方を ShaderMaterial に渡します。

-
-const material = new THREE.MeshBasicMaterial({
--    color: 'red',
--});
-+const material = new THREE.ShaderMaterial({
-+  fragmentShader,
-+  uniforms,
-+});
-
-

レンダリングする前にユニフォームの値を設定します。

-
-function render() {
-+function render(time) {
-+  time *= 0.001;  // convert to seconds
-
-  resizeRendererToDisplaySize(renderer);
-
-+  const canvas = renderer.domElement;
-+  uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
-+  uniforms.iTime.value = time;
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-
-

注意点: なぜ iResolutionvec3 なのか、 3番目の値に何が入っているのか -shadertoy.comには文書化されてない のでさっぱりわかりません。 -上記では使わないのでとりあえず1にしておきます。 ¯\_(ツ)_/¯

-
-

- -

-

これは新しいシェーダーでShadertoyで見たものと一致します。 -少なくとも2019年1月の時点では😉。上記のシェーダーは何をしているのでしょうか?

-
    -
  • uv は0 〜 1です。
  • -
  • cos(uv.xyx) は3つのコサイン値を vec3 としてます。
  • -
  • 3つとは uv.xuv.yuv.z です。
  • -
  • 時間を加えて、cos(iTime+uv.xyx) でアニメーションさせます。
  • -
  • cos(iTime+uv.xyx+vec3(0,2,4)) のように vec3(0,2,4) を加えると、コサイン波の cos が-1 〜 1にオフセットされます。
  • -
  • そのため 0.5 * 0.5 + cos(....) は -1 <-> 1 〜 0.0 <-> 1.0 に変換され、その結果が現在のピクセルのRGB色として利用されます。
  • -
-

わずかな変更でコサイン波が見やすくなります。 -uv は0 〜 1までの間だけです。 -コサインは2πで繰り返すので、0 〜 40.0を掛けて40にしてみましょう。 -これで6.3回くらいリピートするはずです。

-
-vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
-+vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx*40.0+vec3(0,2,4));
-
-

以下を数えてみると6.3回くらいリピートしています。 -+vec3(0,2,4) で4だけオフセットされているので赤の間に青が見えます。 -それがないと青と赤が完全に重なり、紫になってしまいます。

-

- -

-

シンプルな入力でshadertoyにある -a city canalや -a forest、 -a snailや -a mushroom -をより印象的なものにして見る事ができます。 -上手くいけば三角形からシーンを作る伝統的な方法と比較して、一般的に正しいアプローチではない理由も明確になるでしょう。 -全てのピクセルの色を計算するために多くの計算をしなければならないので、これらの例は非常に遅く実行されます。

-

いくつかのshadertoyシェーダーは、これのようにテクスチャを入力として受け取るものがあります。

-
// By Daedelus: https://www.shadertoy.com/user/Daedelus
-// license: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
-#define TIMESCALE 0.25
-#define TILES 8
-#define COLOR 0.7, 1.6, 2.8
-
-void mainImage( out vec4 fragColor, in vec2 fragCoord )
-{
-    vec2 uv = fragCoord.xy / iResolution.xy;
-    uv.x *= iResolution.x / iResolution.y;
-
-    vec4 noise = texture2D(iChannel0, floor(uv * float(TILES)) / float(TILES));
-    float p = 1.0 - mod(noise.r + noise.g + noise.b + iTime * float(TIMESCALE), 1.0);
-    p = min(max(p * 3.0 - 1.8, 0.1), 2.0);
-
-    vec2 r = mod(uv * float(TILES), 1.0);
-    r = vec2(pow(r.x - 0.5, 2.0), pow(r.y - 0.5, 2.0));
-    p *= 1.0 - pow(min(1.0, 12.0 * dot(r, r)), 2.0);
-
-    fragColor = vec4(COLOR, 1.0) * p;
-}
-
-

シェーダーにテクスチャを渡すのは通常のマテリアルにテクスチャを渡すのと似ていますが、ユニフォームにテクスチャを設定する必要があります。

-

まず、シェーダーにテクスチャのユニフォームを追加します。 -GLSLでは sampler2D と呼ばれています。

-
const fragmentShader = `
-#include <common>
-
-uniform vec3 iResolution;
-uniform float iTime;
-+uniform sampler2D iChannel0;
-
-...
-
-

ここで取り上げたこれのようなテクスチャをロードし、ユニフォームの値を設定します。

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load('resources/images/bayer.png');
-+texture.minFilter = THREE.NearestFilter;
-+texture.magFilter = THREE.NearestFilter;
-+texture.wrapS = THREE.RepeatWrapping;
-+texture.wrapT = THREE.RepeatWrapping;
-const uniforms = {
-  iTime: { value: 0 },
-  iResolution:  { value: new THREE.Vector3() },
-+  iChannel0: { value: texture },
-};
-
-

- -

-

これまではShadertoy.comで使われているShadertoyシェーダーをそのまま使っていましたが、キャンバスを塗りつぶすように描画しています。 -しかし、そのユースケースだけに限定する必要はありません。 -覚えておくべき重要な事は、shadertoy上で書かれている関数は fragCoord の入力と iResolution を受け取るだけです。 -代わりにテクスチャ座標のような他のものを使えば、他のテクスチャと同じように使えます。 -関数を使ってテクスチャを生成するこの手法は、プロシージャルテクスチャと呼ばれています。

-

上記のシェーダーを変更してみましょう。 -最も簡単なのはthree.jsが通常提供しているテクスチャ座標を取得し、それに iResolution を掛けて fragCoords に渡す事かもしれません。

-

そのためには ヴァリイング(varying) を追加します。 -ヴァリイングとは頂点シェーダーからフラグメントシェーダーに渡される値で、頂点間で補間される値(または変化する値)の事です。 -フラグメントシェーダーで使用するために宣言します。 -Three.jsのテクスチャ座標は uv で前にある vヴァリイング を意味します。

-
...
-
-+varying vec2 vUv;
-
-void main() {
--  mainImage(gl_FragColor, gl_FragCoord.xy);
-+  mainImage(gl_FragColor, vUv * iResolution.xy);
-}
-
-

次に独自の頂点シェーダーも用意する必要があります。 -ここでは最小限のthree.jsの頂点シェーダーを紹介します。 -Three.jsは uvprojectionMatrixmodelViewMatrixposition を宣言し、その値を提供します。

-
const vertexShader = `
-  varying vec2 vUv;
-  void main() {
-    vUv = uv;
-    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
-  }
-`;
-
-

頂点シェーダーを ShaderMaterial に渡します。

-
const material = new THREE.ShaderMaterial({
-  vertexShader,
-  fragmentShader,
-  uniforms,
-});
-
-

iResolution の値は初期化時には変化しないので、iResolution の値をユニフォームに設定できます。

-
const uniforms = {
-  iTime: { value: 0 },
--  iResolution:  { value: new THREE.Vector3() },
-+  iResolution:  { value: new THREE.Vector3(1, 1, 1) },
-  iChannel0: { value: texture },
-};
-
-

レンダリング時に設定する必要がなくなりました。

-
-const canvas = renderer.domElement;
--uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
-uniforms.iTime.value = time;
-
-

元のカメラとレスポンシブデザインの記事から3つの回転する立方体を設定するコードでコピーバックしました。 -その結果です。

-

- -

-

これで少しでもthree.jsを使ったshadertoyシェーダーの使い方を知ってもらえればと思います。 -繰り返しになりますが、ほとんどのshadertoyシェーダーは実際にパフォーマンスの高い方法で描画する推奨された方法ではなく、 -面白いチャレンジ(単一の機能で全てを描画する)と覚えておく事が重要です。 -それでもshadertoyのシェーダー達は素晴らしく、印象的で、美しく、どのように機能するかコードを見て学ぶ事ができます。

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/shadows.html b/manual/ja/shadows.html deleted file mode 100644 index f07959802763bb..00000000000000 --- a/manual/ja/shadows.html +++ /dev/null @@ -1,434 +0,0 @@ - - - のシャドウ - - - - - - - - - - - - - -
-
-

のシャドウ

-
-
-
-

この記事はThree.jsの連載記事の1つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでいない場合、そこから始めると良いかもしれません。 -この記事を読む前に、前回のカメラの記事ライトの記事も読んでおくと良いです。

-

コンピュータ上での影の表現は複雑なトピックになります。 -three.jsで利用できる解決策も含め様々な解決策がありますが、どれもトレードオフがあります。

-

Three.jsは シャドウマップ をデフォルトで使用してます。 -シャドウマップを機能させるには、全てのライトにシャドウを落とし、光源に対して全てのオブジェクトもシャドウを落としてレンダリングします。 -急ぐ必要はないので もう一度読んでみて下さい!

-

つまり、20個のオブジェクトと5個のライトがあり、全てのオブジェクトとライトにシャドウを落としている場合、シーン全体が6回描画されます。 -全てのオブジェクトがライト#1、ライト#2、ライト#3に描画され、最初の5回の描画からデータを使って実際のシーンが描画されます。

-

さらに悪い事に点光源がシャドウを落としている場合、6回もシーン描画しなければならないのです。

-

これらの理由からシャドウを生成するライトをたくさん持つよりも、他の解決策を見つけるのが一般的です。 -一般的な解決策は複数ライトを持つ事ですが、ディレクショナルライトでシャドウを生成する方法があります。

-

もう1つの解決策はライトマップやアンビエントオクルージョンマップを使用し、オフラインでライティングの効果を事前計算する方法もあります。 -静的なライティングのヒントになりますが、少なくともそれは速いです。 -その両方に関しては別の記事で取り上げます。

-

もう1つの解決策はフェイクシャドウです。 -平面を作り影に似たグレースケールのテクスチャを入れて、オブジェクト下の地面の上に描画します。

-

例えばこのテクスチャをフェイクシャドウしてみましょう。

-
- -

前回の記事のコードの一部を使用します。

-

背景色を白に設定してみましょう。

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-

同じチェッカーボードの地面を使いますが、今回の地面には照明は必要ないので MeshBasicMaterial を使用します。

-
+const loader = new THREE.TextureLoader();
-
-{
-  const planeSize = 40;
-
--  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/checker.png');
-  texture.wrapS = THREE.RepeatWrapping;
-  texture.wrapT = THREE.RepeatWrapping;
-  texture.magFilter = THREE.NearestFilter;
-  const repeats = planeSize / 2;
-  texture.repeat.set(repeats, repeats);
-
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-  const planeMat = new THREE.MeshBasicMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-+  planeMat.color.setRGB(1.5, 1.5, 1.5);
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  mesh.rotation.x = Math.PI * -.5;
-  scene.add(mesh);
-}
-
-

色が 1.5, 1.5, 1.5 である事に注意して下さい。 -これにより、チェッカーボードのテクスチャの色がそれぞれ1.5倍になります。 -テクスチャの色は 0x808080 と 0xC0C0C0 でミディアムグレーとライトグレーなので、1.5を掛けると白とライトグレーのチェッカーボードになります。

-

シャドウテクスチャを読み込んでみましょう。

-
const shadowTexture = loader.load('resources/images/roundshadow.png');
-
-

各球体と関連するオブジェクトを保持する配列を作成します。

-
const sphereShadowBases = [];
-
-

そして、球体のジオメトリを作ります。

-
const sphereRadius = 1;
-const sphereWidthDivisions = 32;
-const sphereHeightDivisions = 16;
-const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-
-

フェイクシャドウのための平面のジオメトリも作ります。

-
const planeSize = 1;
-const shadowGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-
-

そして、たくさんの球体を作ります。 -各球体に対して THREE.Object3D を作成し base に格納しシャドウの平面と球体メッシュの両方をbaseの子にします。 -これでbaseを動かすと、球体とシャドウの両方が動きます。 -Zファイティングを防ぐためにシャドウを少し上にします。 -また、depthWrite をfalseにしてシャドウがお互いに混乱しないようにします。 -この2つの問題は別の記事で解説します。 -このシャドウは照明が不要なので MeshBasicMaterial にします。

-

各球体を異なる色相、ベース、球体メッシュ、シャドウのメッシュ、各球体のyの初期位置を保存します。

-
const numSpheres = 15;
-for (let i = 0; i < numSpheres; ++i) {
-  // make a base for the shadow and the sphere
-  // so they move together.
-  const base = new THREE.Object3D();
-  scene.add(base);
-
-  // add the shadow to the base
-  // note: we make a new material for each sphere
-  // so we can set that sphere's material transparency
-  // separately.
-  const shadowMat = new THREE.MeshBasicMaterial({
-    map: shadowTexture,
-    transparent: true,    // so we can see the ground
-    depthWrite: false,    // so we don't have to sort
-  });
-  const shadowMesh = new THREE.Mesh(shadowGeo, shadowMat);
-  shadowMesh.position.y = 0.001;  // so we're above the ground slightly
-  shadowMesh.rotation.x = Math.PI * -.5;
-  const shadowSize = sphereRadius * 4;
-  shadowMesh.scale.set(shadowSize, shadowSize, shadowSize);
-  base.add(shadowMesh);
-
-  // add the sphere to the base
-  const u = i / numSpheres;   // goes from 0 to 1 as we iterate the spheres.
-  const sphereMat = new THREE.MeshPhongMaterial();
-  sphereMat.color.setHSL(u, 1, .75);
-  const sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
-  sphereMesh.position.set(0, sphereRadius + 2, 0);
-  base.add(sphereMesh);
-
-  // remember all 3 plus the y position
-  sphereShadowBases.push({base, sphereMesh, shadowMesh, y: sphereMesh.position.y});
-}
-
-

2つのライトを設定しました。 -1つは HemisphereLight で強度2にしました。

-
{
-  const skyColor = 0xB1E1FF;  // light blue
-  const groundColor = 0xB97A20;  // brownish orange
-  const intensity = 2;
-  const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
-  scene.add(light);
-}
-
-

もう1つは DirectionalLight で球体はいくつかの定義を得られます。

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(0, 10, 5);
-  light.target.position.set(-5, 0, 0);
-  scene.add(light);
-  scene.add(light.target);
-}
-
-

そのままレンダリングしてますが、球体をアニメーション化してみましょう。 -それぞれの球体、シャドウ、baseのセットに対して、 -baseをxz平面内で移動させて Math.abs(Math.sin(time)) で球体を上下に移動させると弾むようなアニメーションします。 -シャドウのマテリアルの不透明度を設定し、各球体が高くなるにつれてシャドウを薄くなるようにしています。

-
function render(time) {
-  time *= 0.001;  // convert to seconds
-
-  ...
-
-  sphereShadowBases.forEach((sphereShadowBase, ndx) => {
-    const {base, sphereMesh, shadowMesh, y} = sphereShadowBase;
-
-    // u is a value that goes from 0 to 1 as we iterate the spheres
-    const u = ndx / sphereShadowBases.length;
-
-    // compute a position for the base. This will move
-    // both the sphere and its shadow
-    const speed = time * .2;
-    const angle = speed + u * Math.PI * 2 * (ndx % 1 ? 1 : -1);
-    const radius = Math.sin(speed - ndx) * 10;
-    base.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);
-
-    // yOff is a value that goes from 0 to 1
-    const yOff = Math.abs(Math.sin(time * 2 + ndx));
-    // move the sphere up and down
-    sphereMesh.position.y = y + THREE.MathUtils.lerp(-2, 2, yOff);
-    // fade the shadow as the sphere goes up
-    shadowMesh.material.opacity = THREE.MathUtils.lerp(1, .25, yOff);
-  });
-
-  ...
-
-

そして、ここに15種類の跳ねるボールがあります。

-

- -

-

全てのオブジェクトに丸や楕円形のシャドウを使用するのが一般的です。 -異なる形状のシャドウのテクスチャを使用できます。 -シャドウをハードエッジでギザギザにしてもいいかもしれません。 -このタイプのシャドウを使った良い例がどうぶつの森 ポケットキャンプです。 -それぞれのキャラクターがシンプルな丸いシャドウになっており、レンダリングコストが低く効果的です。 -モニュメントバレーでは、メインキャラクターにもこのシャドウが使われているようです。

-

そこでシャドウマップに移りますが、シャドウを落とす事ができるライトが3つあります。 -DirectionalLightPointLightSpotLight です。

-

まずは、ライトの記事のヘルパーの例を参考に DirectionalLight を使ってみましょう。

-

最初にレンダラーのシャドウを有効にします。

-
const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+renderer.shadowMap.enabled = true;
-
-

そして、シャドウを落とすためにライトのcastShadowを有効にします。

-
const light = new THREE.DirectionalLight(color, intensity);
-+light.castShadow = true;
-
-

シーン内の各メッシュを見て、シャドウを落とすか受け取るか決めます。

-

下敷きになっているものはあまり気にせず、平面(地面)はシャドウだけを受けるようにしましょう。

-
const mesh = new THREE.Mesh(planeGeo, planeMat);
-mesh.receiveShadow = true;
-
-

立方体と球体はシャドウを落とし受け取るようにしましょう。

-
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-mesh.castShadow = true;
-mesh.receiveShadow = true;
-
-...
-
-const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-mesh.castShadow = true;
-mesh.receiveShadow = true;
-
-

これを実行してみます。

-

- -

-

何が起こったのでしょうか? -なぜ影の一部が欠けているのでしょうか?

-

これはシャドウマップは光の視点でシーンをレンダリングし作成されるからです。 -この場合、DirectionalLight にカメラがあり、ターゲットを見ています。 -以前取り上げたカメラと同じように -ライトのシャドウカメラは影がレンダリングされ、内部の領域を定義します。 -上記の例ではその面積が小さすぎます。

-

その領域を可視化するために、ライトのシャドウカメラを取得して CameraHelper をシーンに追加します。

-
const cameraHelper = new THREE.CameraHelper(light.shadow.camera);
-scene.add(cameraHelper);
-
-

これでシャドウが落とされ受け取れる領域が見えるようになりました。

-

- -

-

ターゲットのX値を前後に調整すると、ライトのシャドウカメラボックスの中にあるものだけが影を描画する場所が明確になります。

-

ライトのシャドウカメラを調整するとその箱の大きさを調整できます。

-

ライトのシャドウカメラボックスを調整するためのGUIを追加してみましょう。 -DirectionLight は全ての光が平行な方向に進むので、DirectionalLight はシャドウカメラに OrthographicCamera を使います。 -以前のカメラの記事OrthographicCamera がどのように動作するかを説明しました。

-

OrthographicCamera は、leftrighttopbottomnearfarzoom プロパティでその箱、または 錐台の視点 を定義してる事を思い出して下さい。

-

ここでもlil-guiのヘルパークラスを作ってみましょう。 -オブジェクトと2つのプロパティを渡す DimensionGUIHelper を作ります。 -lil-guiが調整できるプロパティを追加し、2つのプロパティの正と負の値を設定します。 -これを使い leftrightwidth に、updownheight に設定します。

-
class DimensionGUIHelper {
-  constructor(obj, minProp, maxProp) {
-    this.obj = obj;
-    this.minProp = minProp;
-    this.maxProp = maxProp;
-  }
-  get value() {
-    return this.obj[this.maxProp] * 2;
-  }
-  set value(v) {
-    this.obj[this.maxProp] = v /  2;
-    this.obj[this.minProp] = v / -2;
-  }
-}
-
-

カメラの記事で作成した MinMaxGUIHelper を使い nearfar を調整します。

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 2, 0.01);
-+{
-+  const folder = gui.addFolder('Shadow Camera');
-+  folder.open();
-+  folder.add(new DimensionGUIHelper(light.shadow.camera, 'left', 'right'), 'value', 1, 100)
-+    .name('width')
-+    .onChange(updateCamera);
-+  folder.add(new DimensionGUIHelper(light.shadow.camera, 'bottom', 'top'), 'value', 1, 100)
-+    .name('height')
-+    .onChange(updateCamera);
-+  const minMaxGUIHelper = new MinMaxGUIHelper(light.shadow.camera, 'near', 'far', 0.1);
-+  folder.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-+  folder.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-+  folder.add(light.shadow.camera, 'zoom', 0.01, 1.5, 0.01).onChange(updateCamera);
-+}
-
-

何か値が変更された時は updateCamera 関数を呼び出すようにします。 -ライトやヘルパー、ライトのシャドウカメラやカメラのヘルパーを更新するupdateCamera関数を書いてみましょう。

-
function updateCamera() {
-  // update the light target's matrixWorld because it's needed by the helper
-  light.target.updateMatrixWorld();
-  helper.update();
-  // update the light's shadow camera's projection matrix
-  light.shadow.camera.updateProjectionMatrix();
-  // and now update the camera helper we're using to show the light's shadow camera
-  cameraHelper.update();
-}
-updateCamera();
-
-

これでライトのシャドウカメラにGUIを追加したので値を変更できます。

-

- -

-

widthheight を30ぐらいにすると、シャドウが正しく描画されこのシーンでシャドウにする設定が完全にカバーできました。

-

しかし、ここで疑問が湧いてきます。 -なぜ widthheight に巨大な数値を設定して全てをカバーしないのでしょうか? -widthheight を100にすると、以下のようなものが表示されます。

-
- -

この低解像度のシャドウはどうなっているでしょうか!?

-

この問題はシャドウに関連した設定を意識する必要があります。 -シャドウマップとはシャドウが描かれるテクスチャです。 -このテクスチャはサイズがあります。 -上記で設定したシャドウカメラの領域はその大きさになっています。 -つまり、設定した面積が大きいほどシャドウのブロックが多くなります。

-

シャドウマップのテクスチャの解像度は light.shadow.mapSize.widthlight.shadow.mapSize.height で設定できます。 -デフォルトは512 x 512です。 -大きくするほどメモリを消費し計算が遅くなるので、できるだけ小さく設定しシーンを動作させたいです。 -ライトのシャドウカメラ領域も同様です。 -小さくすると影の見栄えが良くなるので、面積を小さくしてシーンをカバーしましょう。 -各ユーザーのコンピューターには、利用可能な最大テクスチャサイズがある事に注意して下さい。 -renderer.capabilities.maxTextureSizeで利用可能な最大テクスチャサイズがわかります。

- -

SpotLight に切り替えると、ライトのシャドウカメラは PerspectiveCamera になります。 -DirectionalLight のシャドウカメラの設定を手動で行えます。 -ただ、SpotLight のシャドウカメラは SpotLight 自身によって制御されます。 -シャドウカメラの fovSpotLightangle に接続しています。 -aspect はシャドウマップのサイズによって自動的に設定されます。

-
-const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.SpotLight(color, intensity);
-
-

ライトの記事にあった penumbraangle の設定を元に戻しました。

-

- -

- -

そして最後に PointLight でシャドウをつけます。 -PointLight は全方向に光を放つので関連する設定は nearfar だけです。 -それ以外の場合、PointLight のシャドウは、効果的な6つの SpotLight のシャドウになります。 -これは PointLight のシャドウの描画が非常に遅くなります。

-

シーンの周りに箱を置いて、壁や天井にシャドウが見えるようにしてみましょう。 -マテリアルの side プロパティを THREE.BackSide に設定します。 -これで箱の外側ではなく内側をレンダリングしています。 -床のようにシャドウを受けるように設定します。 -また、箱の底が床より少し下になるように箱の位置を設定し、床と箱がズレないようにします。

-
{
-  const cubeSize = 30;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-  const cubeMat = new THREE.MeshPhongMaterial({
-    color: '#CCC',
-    side: THREE.BackSide,
-  });
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.receiveShadow = true;
-  mesh.position.set(0, cubeSize / 2 - 0.1, 0);
-  scene.add(mesh);
-}
-
-

そして、ライトを PointLight に切り替えます。

-
-const light = new THREE.SpotLight(color, intensity);
-+const light = new THREE.PointLight(color, intensity);
-
-....
-
-// so we can easily see where the point light is
-+const helper = new THREE.PointLightHelper(light);
-+scene.add(helper);
-
-

- -

-

GUIの position を使ってライトを移動させると、壁一面にシャドウが落ちます。 -また、nearfar の設定を調整できます。 -near よりも近い時にはシャドウを受け取らず、far よりも遠い時には常にシャドウになっています。

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/textures.html b/manual/ja/textures.html deleted file mode 100644 index 6f14fcca321c46..00000000000000 --- a/manual/ja/textures.html +++ /dev/null @@ -1,542 +0,0 @@ - - - のテクスチャ - - - - - - - - - - - - - -
-
-

のテクスチャ

-
-
-
-

この記事はthree.jsについてのシリーズ記事の一つです。 -最初の記事はThree.jsの基礎知識です。 -まだ読んでない人は、そちらから先に読んでみるといいかもしれません。

-

テクスチャはThree.jsの大きなトピックの一つです。 -どのレベルで説明するといいか100%承知してはいませんが、やってみようと思います。 -Three.jsにはたくさんのトピックがあり、互いに関係しているので、一度に説明するのが難しいのです。 -これがこの記事の内容の早見表です。

- - -

ハロー・テクスチャ

-

テクスチャは一般的にPhotoshopやGIMPのような3rdパーティーのプログラムで最もよく作られる画像です。 -例えば、この画像を立方体に乗せてみましょう。

-
- -
- -

最初の例を修正してみましょう。TextureLoaderを作ることで、必要なことはすべてできます。 -loadを画像のURLを引数にして呼び、colorを設定する代わりに、 -マテリアルのmap属性にその結果を渡してください。

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load( 'resources/images/wall.jpg' );
-+texture.colorSpace = THREE.SRGBColorSpace;
-
-const material = new THREE.MeshBasicMaterial({
--  color: 0xFF8844,
-+  map: texture,
-});
-
-

MeshBasicMaterialを使っているので、光源が必要ないことに注意してください。

-

- -

-

立方体の各面に異なる6つのテクスチャを貼り付ける

-

立方体の各面に貼り付ける、6つのテクスチャはどのようなものでしょうか。

-
-
- - - -
-
- - - -
-
- -

Meshを作るときに、単に6つのマテリアルを作り、配列として渡します。

-
const loader = new THREE.TextureLoader();
--const texture = loader.load( 'resources/images/wall.jpg' );
--texture.colorSpace = THREE.SRGBColorSpace;
-
--const material = new THREE.MeshBasicMaterial({
--  map: texture,
--});
-+const materials = [
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-1.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-2.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-3.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-4.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-5.jpg')}),
-+  new THREE.MeshBasicMaterial({map: loadColorTexture('resources/images/flower-6.jpg')}),
-+];
--const cube = new THREE.Mesh(geometry, material);
-+const cube = new THREE.Mesh(geometry, materials);
-
-+function loadColorTexture( path ) {
-+  const texture = loader.load( path );
-+  texture.colorSpace = THREE.SRGBColorSpace;
-+  return texture;
-+}
-
-

動きました!

-

- -

-

ただし、全ての種類のジオメトリが複数のマテリアルに対応しているわけではないことに注意してください。 -BoxGeometryBoxGeometryは、それぞれの面に6つのマテリアルを使えます。 -ConeGeometryConeGeometryは2つのマテリアルを使うことができ、一つは底面、一つは円錐面に適用されます。 -CylinderGeometryCylinderGeometryは3つのマテリアルを使うことができ、一つは底面、一つは上面、一つは側面に適用されます。 -その他のケースでは、カスタムジオメトリのビルドや読み込み、テクスチャの座標の修正が必要になります。

-

1つのジオメトリに複数の画像を適用したいなら、 -テクスチャアトラスを使うのが、ほかの3Dエンジンでははるかに一般的で、はるかに高性能です。 -テクスチャアトラスは、一つのテクスチャに複数の画像を配置し、ジオメトリの頂点の座標を使って -テクスチャのどの部分がジオメトリのおのおのの三角形に使われるか、選択するものです。

-

テクスチャの座標とはなんでしょうか?ジオメトリ頂点に与えられたデータのことで、 -テクスチャのどの部分がその頂点に対応するか指定するものです。 -カスタムジオメトリの構築を始めるときに説明します。

-

テクスチャの読み込み

-

簡単な方法

-

このサイトのコードのほとんどは、もっとも簡単なテクスチャの読み込み方を使っています。 -TextureLoaderを作り、そのloadメソッドを呼びます。 -これはTextureオブジェクトを返します。

-
const texture = loader.load('resources/images/flower-1.jpg');
-
-

このメソッドを使うと、画像がthree.jsによって非同期的に読み込まれるまで、テクスチャが透明になります。読み込まれた時点で、テクスチャをダウンロードした画像に更新します。

-

この方法では、テクスチャの読み込みを待つ必要がなく、ページをすぐにレンダリングし始めることができるという、大きな利点があります。 -多くのケースでこの方法で問題ありませんが、テクスチャをダウンロードし終えたときにthree.jsに通知してもらうこともできます。

-

テクスチャの読み込みを待つ

-

テクスチャの読み込みを待つために、テクスチャローダーのloadメソッドは、テクスチャの読み込みが終了したときに呼ばれるコールバックを取ります。 -冒頭の例に戻り、このように、Meshを作りシーンに追加する前に、テクスチャの読み込みを待つことができます。

-
const loader = new THREE.TextureLoader();
-loader.load('resources/images/wall.jpg', (texture) => {
-  const material = new THREE.MeshBasicMaterial({
-    map: texture,
-  });
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-});
-
-

ブラウザのキャッシュをクリアし、接続が遅くならない限り、違いが分かることはないと思いますが、 -ちゃんとテクスチャが読み込まれるのを待っているので、安心してください。

-

- -

-

複数テクスチャの読み込みを待つ

-

全てのテクスチャが読み込まれたことを待つために、LoadingManagerを使うことができます。 -TextureLoaderを渡すと、onLoad属性がコールバックに設定されます。

-
+const loadManager = new THREE.LoadingManager();
-*const loader = new THREE.TextureLoader(loadManager);
-
-const materials = [
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-1.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-2.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-3.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-4.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-5.jpg')}),
-  new THREE.MeshBasicMaterial({map: loader.load('resources/images/flower-6.jpg')}),
-];
-
-+loadManager.onLoad = () => {
-+  const cube = new THREE.Mesh(geometry, materials);
-+  scene.add(cube);
-+  cubes.push(cube);  // add to our list of cubes to rotate
-+};
-
-

LoadingManageronProgress属性もあり、 -プログレスインジケーターを表示するためのコールバックを設定できます。

-

まず、HTMLにプログレスバーを追加しましょう。

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="loading">
-+    <div class="progress"><div class="progressbar"></div></div>
-+  </div>
-</body>
-
-

そしてCSSにも追加します。

-
#loading {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-}
-#loading .progress {
-    margin: 1.5em;
-    border: 1px solid white;
-    width: 50vw;
-}
-#loading .progressbar {
-    margin: 2px;
-    background: white;
-    height: 1em;
-    transform-origin: top left;
-    transform: scaleX(0);
-}
-
-

そうすると、コード内でonProgressコールバックのprogressbarのスケールが更新できます。 -これは、最後のアイテムが読み込まれるURL、いま読み込まれているアイテムの数、アイテムの合計数を渡して呼ばれます。

-
+const loadingElem = document.querySelector('#loading');
-+const progressBarElem = loadingElem.querySelector('.progressbar');
-
-loadManager.onLoad = () => {
-+  loadingElem.style.display = 'none';
-  const cube = new THREE.Mesh(geometry, materials);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-};
-
-+loadManager.onProgress = (urlOfLastItemLoaded, itemsLoaded, itemsTotal) => {
-+  const progress = itemsLoaded / itemsTotal;
-+  progressBarElem.style.transform = `scaleX(${progress})`;
-+};
-
-

キャッシュを削除して低速なコネクションを作らない限りは、プログレスバーを見ることできないかもしれません。

-

- -

-

異なるオリジンからのテクスチャの読み込み

-

異なるサーバーの画像を使うため、そのサーバーは正しいヘッダーを送る必要があります。 -そうしないと、three.jsでその画像を使うことができず、エラーを受け取るでしょう。 -もし皆さんが画像を提供するサーバーを運用しているなら、 -正しいヘッダーを送るを確認してください。 -画像をホスティングしているサーバーに手を入れられず、権限用のヘッダーを送ることができないなら、 -そのサーバーからの画像を使うことはできません。

-

例えば、imgurflickr、そして -githubは全て、ホストしている画像を -three.jsで使うことができるようなヘッダーを送っています。

-

メモリ使用

-

多くの場合、テクスチャはthree.jsアプリの中で最もメモリを使っています。 -一般的にテクスチャは幅 * 高さ * 4 * 1.33バイトのメモリを消費していることを理解するのは重要です。

-

圧縮については言及していないことに注意してください。.jpgイメージを作り、超高圧縮することもできます。 -例えば、家のシーンを作っているとしましょう。家の中には、テーブルがあり、上面に木目のテクスチャを置くことに決めました。

-
- - -

このイメージはたった157kなので、比較的速くダウンロードすることができます。しかし、 -ピクセルだと3024 x 3761の大きさです。 -前述した式によると、

-
3024 * 3761 * 4 * 1.33 = 60505764.5
-

となり、three.jsの60メガのメモリ!を消費するでしょう。 -このようなテクスチャがいくつかあるだけで、メモリリークしてしまうでしょう。

-

この例を持ち出したのは、テクスチャを使用することの隠れたコストを知っているのが重要だからです。 -three.jsでテクスチャを使うためには、テクスチャのデータをGPUに渡し、一般的に非圧縮にしておく必要があります。

-

この話の教訓は、テクスチャをファイルサイズだけでなく、次元も小さくすることです。 -ファイルサイズの小ささ = 高速なダウンロードです。次元の小ささ = 省メモリです。 -では、どのように小さくできるのでしょうか? -できるだけ小さく、そして十分見えるくらいです。

-

JPG vs PNG

-

これは通常のHTMLとほぼ同じで、PNGはロスレス圧縮なので、lossy圧縮のJPGよりも -一般的にダウンロードが遅くなります。 -しかし、PNGは透過性があります。PNGは法線マップや後ほど説明する非画像マップのような非画像データにも適したフォーマットです。

-

WebGLにおいて、JPGがPNGよりも省メモリではないことを覚えておいてください。上記を参照してください。

-

フィルタリングとMIP

-

この16x16のテクスチャを

-
- -

立方体に適用してみます。

-
- -

この立方体をとても小さく描画してみましょう。

-
- -

ふーむ、見えにくいです。小さな立方体を拡大してみましょう。

-
- -

GPUは小さな立方体のどのピクセルにどの色を使うか、どうやって知るのでしょうか? -立方体が小さすぎて1、2ピクセルしかないとしたらどうでしょうか?

-

フィルタリングとはこういうものです。

-

もしフォトショップなら近くの全てのピクセルを平均して、1、2ピクセルの色を見つけます。 -これはとても遅い操作です。GPUはミップマップを使ってこの問題を解決します。

-

MIPはテクスチャのコピーで、ピクセルがブレンドされて次の小さいMIPを作られます。そのため、前のMIPの半分の幅と半分の高さになっています。 -MIPは1x1ピクセルのMIPが得られるまで作られます。 -全てのMIP上の画像はこのようになります。

-
- -

さて、立方体が1、2ピクセルの小ささに描かれたとき、どんな色にするか決めるため、GPUは最も小さなMIPレベルか次に小さいMIPか選ぶことができます。

-

three.jsでは、テクスチャが元の大きさより大きく描かれたときと、小さく描かれたときの両方で、処理の設定を選ぶことができます。

-

テクスチャが元の大きさより大きく描かれたときのフィルタ設定として、texture.magFilter属性にTHREE.NearestFilterTHREE.LinearFilterを設定することができます。 -NearestFilterは元のテクスチャから最も近い1ピクセルを使用するということです。 -低解像度のテクスチャでは、マインクラフトのようにピクセル化された見た目になります。

-

LinearFilterはテクスチャから、色を決めたいピクセルに最も近い4ピクセルを選び、 -実際の点が4つのピクセルからどれだけ離れているかに応じて適切な比率で混ぜ合わせます。

-
-
-
-
Nearest
-
-
-
-
Linear
-
-
- -

元の大きさよりもテクスチャが小さく描画された時のフィルタ設定では、 -texture.minFilter属性を6つの値から一つ設定できます。

-
    -
  • THREE.NearestFilter

    -

    上と同様に、テクスチャの最も近いピクセルを選ぶ。

    -
  • -
  • THREE.LinearFilter

    -

    上と同様に、テクスチャから4ピクセルを選んで混ぜ合わせる。

    -
  • -
  • THREE.NearestMipmapNearestFilter

    -

    適切なMIPを選び、ピクセルを一つ選ぶ。

    -
  • -
  • THREE.NearestMipmapLinearFilter

    -

    2つMIPを選び、それぞれからピクセルを選んで、その2つを混ぜる。

    -
  • -
  • THREE.LinearMipmapNearestFilter

    -

    適切なMIPを選び、4ピクセルを選んで混ぜ合わせる。

    -
  • -
  • THREE.LinearMipmapLinearFilter

    -

    2つMIPを選び、それぞれから4ピクセルを選んで、8つ全部を混ぜ合わせて1ピクセルにする。

    -
  • -
-

ここで6つ全ての設定の例を見せましょう。

-
-
-
-
click to
change
texture
-
-
nearest
-
linear
-
nearest
mipmap
nearest
-
nearest
mipmap
linear
-
linear
mipmap
nearest
-
linear
mipmap
linear
-
-
- -

注意することは、左上と中央上はNearestFilterを使っていて、LinearFilterはMIPを使っていないことです。GPUが元のテクスチャからピクセルを選ぶので、遠くはちらついて見えます。 -左側はたった一つのピクセルが選ばれ、中央は4つのピクセルが選ばれて混ぜ合わされます。しかし、 -良い色の表現には至っていません。 -ほかの4つの中では、右下のLinearMipmapLinearFilterが一番良いです。

-

上の画像をクリックすると、上で使用しているテクスチャと、MIPレベルごとに色が異なるテクスチャが切り替わります。

-
-
-
- -

これで、起きていることが分かりやすいでしょう。 -左上と中央上は、最初のMIPがずっと遠くまで使われているのが分かります。 -右上と中央下は、別のMIPが使われているのがよく分かります。

-

元のテクスチャに切り替えると、右下が滑らか、つまり高品質であることが分かります。 -なぜ常にこのモードにしないのか聞きたいかもしれません。 -最も明らかな理由は、レトロ感を出すために、ピクセル化してほしいとかです。 -次の理由は、8ピクセルを読み込んで混ぜ合わせることは、1ピクセルを読んで混ぜ合わせるよりも遅いことです。 -1つのテクスチャの速度では違いが出るように思えないかもしれませんが、 -記事が進むにつれて、最終的に4、5のテクスチャを一度に持つマテリアルが出てくるでしょう。 -4テクスチャ * 8ピクセル(テクスチャごと)は、どのピクセルを描画するにも32ピクセル探すことになります。 -これはモバイルデバイスで考えるときに特に重要になります。

-

テクスチャの繰り返し、オフセット、回転、ラッピング

-

テクスチャは、繰り返し、オフセット、回転の設定があります。

-

three.jsのデフォルトのテクスチャは繰り返されません。 -テクスチャが繰り返されるかどうかの設定には、2つの属性があります。 -水平方向のラッピングにwrapSと、垂直方向のラッピングにwrapTです。

-

以下のどれかが設定されます:

-
    -
  • THREE.ClampToEdgeWrapping

    -

    それぞれの角の最後のピクセルが永遠に繰り返されます。

    -
  • -
  • THREE.RepeatWrapping

    -

    テクスチャが繰り返されます。

    -
  • -
  • THREE.MirroredRepeatWrapping

    -

    テクスチャの鏡像が取られ、繰り返されます。

    -
  • -
-

例えば、両方向にラッピングすると、

-
someTexture.wrapS = THREE.RepeatWrapping;
-someTexture.wrapT = THREE.RepeatWrapping;
-
-

繰り返しはrepeat属性で設定されます。

-
const timesToRepeatHorizontally = 4;
-const timesToRepeatVertically = 2;
-someTexture.repeat.set(timesToRepeatHorizontally, timesToRepeatVertically);
-
-

テクスチャのオフセットはoffset属性でできます。 -テクスチャは1単位 = 1テクスチャの大きさにオフセットされます。 -言い換えると、0 = オフセットなし、1 = テクスチャ全体の大きさということです。

-
const xOffset = .5;   // offset by half the texture
-const yOffset = .25;  // offset by 1/4 the texture
-someTexture.offset.set(xOffset, yOffset);
-
-

テクスチャの回転は、rotation属性で、ラジアンで指定します。 -同様に center属性で回転の中心を指定します。 -デフォルトは0,0で、左下の角で回転します。 -オフセットと同じように、単位はテクスチャの大きさなので、.5, .5に設定すると、 -テクスチャの中心での回転になります。

-
someTexture.center.set(.5, .5);
-someTexture.rotation = THREE.MathUtils.degToRad(45);
-
-

最初に取り上げたサンプルでこれらの値を試してみましょう。

-

最初に、テクスチャを操作できるように参照を保持しておきます。

-
+const texture = loader.load('resources/images/wall.jpg');
-const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg');
-+  map: texture,
-});
-
-

ここでも、簡単なインターフェースを提供するためにlil-guiを使います。

-
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

以前のlil-guiの例でしたように、lil-guiに度数で操作できるオブジェクトを与え、 -ラジアン単位でプロパティを設定する簡単なクラスを使います。

-
class DegRadHelper {
-  constructor(obj, prop) {
-    this.obj = obj;
-    this.prop = prop;
-  }
-  get value() {
-    return THREE.MathUtils.radToDeg(this.obj[this.prop]);
-  }
-  set value(v) {
-    this.obj[this.prop] = THREE.MathUtils.degToRad(v);
-  }
-}
-
-

"123"といった文字列から123といった数値に変換するクラスも必要です。 -これは、three.jsはwrapSwrapTのようなenumの設定として数値が必要ですが、 -lil-guiはenumに文字列のみを使うためです。

-
class StringToNumberHelper {
-  constructor(obj, prop) {
-    this.obj = obj;
-    this.prop = prop;
-  }
-  get value() {
-    return this.obj[this.prop];
-  }
-  set value(v) {
-    this.obj[this.prop] = parseFloat(v);
-  }
-}
-
-

このクラスを使って、上記設定のための簡単なGUIをセットアップできます。

-
const wrapModes = {
-  'ClampToEdgeWrapping': THREE.ClampToEdgeWrapping,
-  'RepeatWrapping': THREE.RepeatWrapping,
-  'MirroredRepeatWrapping': THREE.MirroredRepeatWrapping,
-};
-
-function updateTexture() {
-  texture.needsUpdate = true;
-}
-
-const gui = new GUI();
-gui.add(new StringToNumberHelper(texture, 'wrapS'), 'value', wrapModes)
-  .name('texture.wrapS')
-  .onChange(updateTexture);
-gui.add(new StringToNumberHelper(texture, 'wrapT'), 'value', wrapModes)
-  .name('texture.wrapT')
-  .onChange(updateTexture);
-gui.add(texture.repeat, 'x', 0, 5, .01).name('texture.repeat.x');
-gui.add(texture.repeat, 'y', 0, 5, .01).name('texture.repeat.y');
-gui.add(texture.offset, 'x', -2, 2, .01).name('texture.offset.x');
-gui.add(texture.offset, 'y', -2, 2, .01).name('texture.offset.y');
-gui.add(texture.center, 'x', -.5, 1.5, .01).name('texture.center.x');
-gui.add(texture.center, 'y', -.5, 1.5, .01).name('texture.center.y');
-gui.add(new DegRadHelper(texture, 'rotation'), 'value', -360, 360)
-  .name('texture.rotation');
-
-

最後に特記することは、もしテクスチャのwrapSwrapTを変えるなら、 -three.jsが設定の適用を知るために、texture.needsUpdateも設定しなければならないことです。ほかの設定は自動的に適用されます。

-

- -

-

これはテクスチャのトピックへの第一歩にすぎません。 -ある時点で、テクスチャの座標や、マテリアルが適用できる別の9種のテクスチャについても説明します。

-

今のところは、光源に進みましょう。

- -

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/tips.html b/manual/ja/tips.html deleted file mode 100644 index 208c571fa70139..00000000000000 --- a/manual/ja/tips.html +++ /dev/null @@ -1,342 +0,0 @@ - - - のTips - - - - - - - - - - - - - -
-
-

のTips

-
-
-
-

この記事では個別の記事を持つには小さすぎるため、three.jsで遭遇するかもしれないいくつかの小さな問題をまとめています。

-
-

-

キャンバスのスクリーンショットを撮る

-

ブラウザではスクリーンショットを撮れる機能が2つあります。 -古いやり方は canvas.toDataURL、新しいやり方は canvas.toBlob です。

-

以下のようなコードを追加するだけで簡単にスクリーンショットを撮れると思うはずです。

-
<canvas id="c"></canvas>
-+<button id="screenshot" type="button">Save...</button>
-
-
const elem = document.querySelector('#screenshot');
-elem.addEventListener('click', () => {
-  canvas.toBlob((blob) => {
-    saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`);
-  });
-});
-
-const saveBlob = (function() {
-  const a = document.createElement('a');
-  document.body.appendChild(a);
-  a.style.display = 'none';
-  return function saveData(blob, fileName) {
-     const url = window.URL.createObjectURL(blob);
-     a.href = url;
-     a.download = fileName;
-     a.click();
-  };
-}());
-
-

以下はレスポンシブデザインの記事の例で、上記のコードにボタンを配置するためのCSSを追加したものです。

-

- -

-

試してみるとこのようなスクリーンショットが出てきました。

-
- -

はい、ただの黒い画像です。

-

お使いのブラウザやOSによっては上手く撮れる事もありますが、一般的には上手く撮れない可能性が高いです。

-

この問題はパフォーマンスと互換性の理由から、デフォルトではブラウザがWebGLキャンバスに描画後に描画バッファをクリアしてしまいます。

-

解決策としてはキャプチャの直前にレンダリングのコードを呼び出す事です。

-

このコードはいくつか調整する必要があります。最初にレンダリングのコードを分離してみましょう。

-
+const state = {
-+  time: 0,
-+};
-
--function render(time) {
--  time *= 0.001;
-+function render() {
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
--    const rot = time * speed;
-+    const rot = state.time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
-+function animate(time) {
-+  state.time = time * 0.001;
-+
-+  render();
-+
-+  requestAnimationFrame(animate);
-+}
-+requestAnimationFrame(animate);
-
-

render は実際にレンダリングする事だけに関係しており、キャンバスをキャプチャする直前に呼び出す事ができます。

-
const elem = document.querySelector('#screenshot');
-elem.addEventListener('click', () => {
-+  render();
-  canvas.toBlob((blob) => {
-    saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`);
-  });
-});
-
-

そして上手く機能するはずです。

-

- -

-

別の解決策については次の項目を参照して下さい。

-
-

-

キャンバスのクリアを防ぐ

-

アニメーションオブジェクトを使って、ユーザーにお絵かきさせたいとしましょう。 -WebGLRenderer 作成時に preserveDrawingBuffer: true を渡す必要があります。 -これによりブラウザがキャンバスをクリアできなくなります。また、three.jsでもキャンバスをクリアしないようにする必要があります。

-
const canvas = document.querySelector('#c');
--const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  canvas,
-+  preserveDrawingBuffer: true,
-+  alpha: true,
-+});
-+renderer.autoClearColor = false;
-
-

- -

-

もしお絵かきプログラムを作ろうとしているのであれば、解像度を変更するとブラウザはキャンバスをクリアしてしまうのでこれは解決策にはなりません。 -ディスプレイのサイズに応じて解像度を変えています。ウィンドウのサイズが変わると表示サイズも変わります。 -これにはユーザーが別のタブでファイルをダウンロードし、ブラウザがステータスバーを追加した場合も含まれます。 -また、ユーザーがスマートフォンを回転しブラウザが縦から横に切り替わった時も含まれます。

-

お絵かきプログラムを作りたいのであれば、レンダーターゲットを使用してテクスチャにレンダリングして下さい。

-
-

-

キーボード入力を取得する

-

このチュートリアルではイベントリスナーを canvas にアタッチする事がよくあります。 -多くのイベントが動作しますが、デフォルトでは動作しないキーボードイベントもあります。

-

例えばキーボードイベントを取得するには、キャンバスのtabindexを0以上にします。

-
<canvas tabindex="0"></canvas>
-
-

しかし、これは新たな問題を引き起こします。tabindex が設定されているものはフォーカスがある時にハイライトされます。 -これを修正するにはCSSの擬似クラスであるfocusでoutlineをnoneにします。

-
canvas:focus {
-  outline:none;
-}
-
-

ここに3つのキャンバスがあります。

-
<canvas id="c1"></canvas>
-<canvas id="c2" tabindex="0"></canvas>
-<canvas id="c3" tabindex="1"></canvas>
-
-

最後のキャンバスだけCSSを追加します。

-
#c3:focus {
-    outline: none;
-}
-
-

全てのイベントリスナーに同じイベントリスナーをアタッチしてみましょう。

-
document.querySelectorAll('canvas').forEach((canvas) => {
-  const ctx = canvas.getContext('2d');
-
-  function draw(str) {
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
-    ctx.textAlign = 'center';
-    ctx.textBaseline = 'middle';
-    ctx.fillText(str, canvas.width / 2, canvas.height / 2);
-  }
-  draw(canvas.id);
-
-  canvas.addEventListener('focus', () => {
-    draw('has focus press a key');
-  });
-
-  canvas.addEventListener('blur', () => {
-    draw('lost focus');
-  });
-
-  canvas.addEventListener('keydown', (e) => {
-    draw(`keyCode: ${e.keyCode}`);
-  });
-});
-
-

1つ目のキャンバスがキーボード入力を受け付けない事に注意して下さい。 -2つ目はキーボード入力をうけつけますがハイライトされます。 -3つ目は両方の問題を解決しています。

-

- -

-
-

-

キャンバスを透明にする

-

デフォルトではthree.jsはキャンバスを不透明にします。 -キャンバスを透明にしたい場合は WebGLRenderer 作成時にalpha:trueを指定します。

-
const canvas = document.querySelector('#c');
--const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  canvas,
-+  alpha: true,
-+});
-
-

また、プリマルチプライドアルファを使用しない事を指定したいでしょう。

-
const canvas = document.querySelector('#c');
-const renderer = new THREE.WebGLRenderer({
-  canvas,
-  alpha: true,
-+  premultipliedAlpha: false,
-});
-
-

Three.jsのデフォルトではキャンバスはpremultipliedAlpha: trueで出力されますが、マテリアルはpremultipliedAlpha: falseで出力されます。

-

プリマルチプライドアルファを利用するタイミングの理解を深めたいのであれば、この良い記事を参照して下さい。

-

いずれにしても透明なキャンバスを使った簡単な例で設定してみましょう。

-

レスポンシブデザインの記事の例に上記の設定を適用してみました。 -マテリアルも透明感のあるものにしてみました。

-
function makeInstance(geometry, color, x) {
--  const material = new THREE.MeshPhongMaterial({color});
-+  const material = new THREE.MeshPhongMaterial({
-+    color,
-+    opacity: 0.5,
-+  });
-
-...
-
-

次にHTMLを追加してみましょう。

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="content">
-+    <div>
-+      <h1>Cubes-R-Us!</h1>
-+      <p>We make the best cubes!</p>
-+    </div>
-+  </div>
-</body>
-
-

CSSで文字テキストをキャンバスの前に配置します。

-
body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-+    position: fixed;
-+    left: 0;
-+    top: 0;
-+    z-index: 2;
-+    pointer-events: none;
-}
-+#content {
-+  font-size: 7vw;
-+  font-family: sans-serif;
-+  text-align: center;
-+  width: 100%;
-+  height: 100%;
-+  display: flex;
-+  justify-content: center;
-+  align-items: center;
-+}
-
-

pointer-events: none はマウスやタッチイベントをキャンバスから見えなくするので、その下のテキストを選択できる事に注意して下さい。

-

- -

-
-

-

背景をthree.jsでアニメーションする

-

よくある質問として、three.jsのアニメーションをWebページの背景にするにはどうしたら良いかという事です。

-

明確な2つの方法があります。

-
    -
  • 以下のようにCSSでキャンバスの positionfixed にします。
  • -
-
#c {
- position: fixed;
- left: 0;
- top: 0;
- ...
-}
-
-

先ほどの例でこの正解コードを見る事ができます。z-index を-1にするだけでキューブがテキストの後ろに表示されます。

-

この解決策の小さな欠点はJavaScriptをウェブページと統合する必要があります。 -複雑なウェブページの場合、three.jsの描画部分がページの他の要素と競合しないようにする必要があります。

-
    -
  • iframe を使用する
  • -
-

この解決策はこのサイトのトップページで使用してます。

-

ウェブページへiframeを挿入したとします。例えば

-
<iframe id="background" src="responsive.html">
-<div>
-  Your content goes here.
-</div>
-
-

これは基本的には上記でキャンバスに使用したのと同じコードですが、iframeにはデフォルトでborderがあるので bordernone にする必要があります。

-
#background {
-    position: fixed;
-    width: 100%;
-    height: 100%;
-    left: 0;
-    top: 0;
-    z-index: -1;
-    border: none;
-    pointer-events: none;
-}
-

- -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/transparency.html b/manual/ja/transparency.html deleted file mode 100644 index d7135211732c25..00000000000000 --- a/manual/ja/transparency.html +++ /dev/null @@ -1,377 +0,0 @@ - - - の透過 - - - - - - - - - - - - - -
-
-

の透過

-
-
-
-

Three.jsでの透過は簡単な方法と難しい方法があります。

-

まずは簡単な方法を見ていきましょう。 -2 x 2 x 2のグリッドに8個のキューブを配置したシーンを作ってみましょう。

-

要求されたレンダリングの記事の例から始めて、3個から8個のキューブになるように修正します。 -まず makeInstance 関数の引数に x, y, z を追加しましょう。

-
-function makeInstance(geometry, color) {
-+function makeInstance(geometry, color, x, y, z) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
--  cube.position.x = x;
-+  cube.position.set(x, y, z);
-
-  return cube;
-}
-
-

これで8個のキューブを作れます。

-
+function hsl(h, s, l) {
-+  return (new THREE.Color()).setHSL(h, s, l);
-+}
-
--makeInstance(geometry, 0x44aa88,  0);
--makeInstance(geometry, 0x8844aa, -2);
--makeInstance(geometry, 0xaa8844,  2);
-
-+{
-+  const d = 0.8;
-+  makeInstance(geometry, hsl(0 / 8, 1, .5), -d, -d, -d);
-+  makeInstance(geometry, hsl(1 / 8, 1, .5),  d, -d, -d);
-+  makeInstance(geometry, hsl(2 / 8, 1, .5), -d,  d, -d);
-+  makeInstance(geometry, hsl(3 / 8, 1, .5),  d,  d, -d);
-+  makeInstance(geometry, hsl(4 / 8, 1, .5), -d, -d,  d);
-+  makeInstance(geometry, hsl(5 / 8, 1, .5),  d, -d,  d);
-+  makeInstance(geometry, hsl(6 / 8, 1, .5), -d,  d,  d);
-+  makeInstance(geometry, hsl(7 / 8, 1, .5),  d,  d,  d);
-+}
-
-

カメラの調整もしました。

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 25;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 4;
-+camera.position.z = 2;
-
-

背景を白に設定します。

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-

そして2つ目のライトを追加したので、キューブの全ての側面が照らされるようになりました。

-
-{
-+function addLight(...pos) {
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
--  light.position.set(-1, 2, 4);
-+  light.position.set(...pos);
-  scene.add(light);
-}
-+addLight(-1, 2, 4);
-+addLight( 1, -1, -2);
-
-

キューブを透過するには transparentフラグを設定し、opacityを設定する必要があります。opacityは1は完全な不透明、0は完全な透明です。

-
function makeInstance(geometry, color, x, y, z) {
--  const material = new THREE.MeshPhongMaterial({color});
-+  const material = new THREE.MeshPhongMaterial({
-+    color,
-+    opacity: 0.5,
-+    transparent: true,
-+  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.set(x, y, z);
-
-  return cube;
-}
-
-

8個の透明なキューブになりました。

-

- -

-

上記の動作サンプルの上でドラッグしてビューを回転してみて下さい。

-

簡単に修正できたようですが...よく見て下さい。キューブの裏面がないです。

-
-
no backs
- -

マテリアルの記事でマテリアルのプロパティsideについて学びました。 -THREE.DoubleSide に設定し、各キューブの両面が描画されるようにします。

-
const material = new THREE.MeshPhongMaterial({
-  color,
-  map: loader.load(url),
-  opacity: 0.5,
-  transparent: true,
-+  side: THREE.DoubleSide,
-});
-
-

これが結果です。

-

- -

-

回転させてみて下さい。 -裏面を見ると上手く動作してるように見えますが、時々できない事があります。

-
-
the left back face of each cube is missing
- -

これは3Dオブジェクトの一般的な描画で発生します。 -各ジオメトリの各三角形は一度に1つずつ描画します。 -三角形の各ピクセルが描画されると2つの事が記録されます。 -1つはそのピクセルの色、もう1つはそのピクセルの深さです。 -次の三角形が描画される時、以前に記録された深さよりも各ピクセルの深さが深い場合は描画されません。

-

不透明なものには効果的ですが、透明なものには失敗します。

-

解決策としては、透明なものを並べ替えて手前より奥のものから描画する事です。 -Three.jsでは Mesh のようなオブジェクトに対してこれを行います。 -そうでなければ、最初のサンプルではいくつかのキューブが他のキューブをブロックし、描画に失敗していたでしょう。 -残念ながら、個々の三角形が破綻し非常に遅くなります。

-

キューブには12個の三角形が各面に2個ずつあり、描画される順番はジオメトリで作られた順番と同じです。 -そのため、どちらの方向を見ているかによって、カメラに近い三角形が最初に描画されるかもしれません。 -その場合、裏面の三角形は描画されません。これにより時々裏面が見えない事があります。

-

球体やキューブのような凸状のオブジェクトの場合は、全てのキューブをシーンに2個ずつ追加するのが1つの解決法です。 -裏面の三角形だけを描画するマテリアルで1個、表面の三角形だけを描画するマテリアルで1個です。

-
function makeInstance(geometry, color, x, y, z) {
-+  [THREE.BackSide, THREE.FrontSide].forEach((side) => {
-    const material = new THREE.MeshPhongMaterial({
-      color,
-      opacity: 0.5,
-      transparent: true,
-+      side,
-    });
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.set(x, y, z);
-+  });
-}
-
-

それは 動作してるように見えます

-

- -

-

この方法はThree.jsの並び順が安定している事が前提です。

-

つまり、最初に side. THREE.BackSide のメッシュを描画し、その後に side.THREE.FrontSide のメッシュを描画し、2つとも同じ位置にある場合です。

-

交差する平面を2つ作ってみましょう(キューブに関連するコードを全て削除後)。 -各面にテクスチャを追加します。

-
const planeWidth = 1;
-const planeHeight = 1;
-const geometry = new THREE.PlaneGeometry(planeWidth, planeHeight);
-
-const loader = new THREE.TextureLoader();
-
-function makeInstance(geometry, color, rotY, url) {
-  const texture = loader.load(url, render);
-  const material = new THREE.MeshPhongMaterial({
-    color,
-    map: texture,
-    opacity: 0.5,
-    transparent: true,
-    side: THREE.DoubleSide,
-  });
-
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-
-  mesh.rotation.y = rotY;
-}
-
-makeInstance(geometry, 'pink',       0,             'resources/images/happyface.png');
-makeInstance(geometry, 'lightblue',  Math.PI * 0.5, 'resources/images/hmmmface.png');
-
-

平面は一度に片側しか見れないため、今回は side: THREE.DoubleSide を使えます。 -また、render 関数にテクスチャ読み込み関数を渡し、読み込みの終了時に再レンダリングする事にも注意して下さい。 -このサンプルが連続したレンダリングではなく、要求されたレンダリングになっているためです。

-

- -

-

そしてまたしても同じような問題が発生しています。

-
-
half a face is missing
- -

この解決策は各表面を手動で2つの表面に分割し、交差しないようにします。

-
function makeInstance(geometry, color, rotY, url) {
-+  const base = new THREE.Object3D();
-+  scene.add(base);
-+  base.rotation.y = rotY;
-
-+  [-1, 1].forEach((x) => {
-    const texture = loader.load(url, render);
-+    texture.offset.x = x < 0 ? 0 : 0.5;
-+    texture.repeat.x = .5;
-    const material = new THREE.MeshPhongMaterial({
-      color,
-      map: texture,
-      opacity: 0.5,
-      transparent: true,
-      side: THREE.DoubleSide,
-    });
-
-    const mesh = new THREE.Mesh(geometry, material);
--    scene.add(mesh);
-+    base.add(mesh);
-
--    mesh.rotation.y = rotY;
-+    mesh.position.x = x * .25;
-  });
-}
-
-

どうやって達成するかはあなた次第です。 -Blenderのようなモデリングツールを使用していた場合は、テクスチャ座標を手動で調整すると思います。 -ここでは PlaneGeometry を使用していますが、デフォルトではテクスチャを平面全体に引き伸ばします。 -テクステャの記事で説明したように texture.repeattexture.offset を設定し、 -各平面上の表面のテクスチャから正しい半分が得られるようにテクスチャを拡大縮小したり移動させたりできます。

-

上記のコードでは Object3D を作成し、その親となる2つの平面を作成しています。 -親の Object3D を回転させた方が必要な計算するよりも簡単そうです。

-

- -

-

この解決策は、交点の位置を変えない2つの平面のような単純なものにしか機能しません。

-

テクスチャのあるオブジェクトの場合は、アルファテストを設定するのがもう1つの解決法です。

-

アルファテストでは、指定したアルファの値以下ではピクセルを描画しません。 -ピクセルを全く描画しなければ、上記のような奥行きの問題はなくなります。 -比較的シャープなエッジの効いたテクスチャの場合、これはかなり効果的です。 -例としては、植物や木の葉のテクスチャ、または草のパッチが含まれます。

-

2つの平面で試してみましょう。まずはテクスチャを使い分けてみましょう。 -先ほどのテクスチャは不透明100%でした。この2つは透過を利用しています。

-
-
-
-
- -

交差する2つの平面(分割する前)に戻り、これらのテクスチャを使用して alphaTest を設定してみましょう。

-
function makeInstance(geometry, color, rotY, url) {
-  const texture = loader.load(url, render);
-  const material = new THREE.MeshPhongMaterial({
-    color,
-    map: texture,
--    opacity: 0.5,
-    transparent: true,
-+    alphaTest: 0.5,
-    side: THREE.DoubleSide,
-  });
-
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-
-  mesh.rotation.y = rotY;
-}
-
--makeInstance(geometry, 'pink',       0,             'resources/images/happyface.png');
--makeInstance(geometry, 'lightblue',  Math.PI * 0.5, 'resources/images/hmmmface.png');
-+makeInstance(geometry, 'white', 0,             'resources/images/tree-01.png');
-+makeInstance(geometry, 'white', Math.PI * 0.5, 'resources/images/tree-02.png');
-
-

これを実行する前に小さなUIを追加し、alphaTesttransparent の設定をもっと簡単に操作できるようにしましょう。 -今回はシーングラフの記事で紹介したようにlil-guiを使います。

-

まず、シーン内の全てのマテリアルに値を設定するlil-guiのヘルパーを作ります。

-
class AllMaterialPropertyGUIHelper {
-  constructor(prop, scene) {
-    this.prop = prop;
-    this.scene = scene;
-  }
-  get value() {
-    const {scene, prop} = this;
-    let v;
-    scene.traverse((obj) => {
-      if (obj.material && obj.material[prop] !== undefined) {
-        v = obj.material[prop];
-      }
-    });
-    return v;
-  }
-  set value(v) {
-    const {scene, prop} = this;
-    scene.traverse((obj) => {
-      if (obj.material && obj.material[prop] !== undefined) {
-        obj.material[prop] = v;
-        obj.material.needsUpdate = true;
-      }
-    });
-  }
-}
-
-

そして、guiを追加します。

-
const gui = new GUI();
-gui.add(new AllMaterialPropertyGUIHelper('alphaTest', scene), 'value', 0, 1)
-    .name('alphaTest')
-    .onChange(requestRenderIfNotRequested);
-gui.add(new AllMaterialPropertyGUIHelper('transparent', scene), 'value')
-    .name('transparent')
-    .onChange(requestRenderIfNotRequested);
-
-

もちろん、lil-guiを含める必要があります。

-
import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-+import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
-
-

その結果がこちらです。

-

- -

-

動作していますが、ズームしてみると1つの平面に白い線が入っているのがわかります。

-
- -

これは前と同じ、深さの問題です。 -その平面が先に描画されていたので、後ろの平面は描画されません。 -これに完全な解決策はありません。 -使用例に合った解決策を見つけるために、alphaTest を調整したり transparent をオフにしたりして下さい。

-

この記事から完璧な透過を目指すのは難しいです。 -問題とトレードオフと回避策があります。

-

例えば、あなたが車を持っていると言います。 -車は通常、四方がフロントガラスになっています。 -上記の並び順の問題を回避したいのであれば、各ウィンドウを独自のオブジェクトにして、three.jsがウィンドウを並び替えて正しい順序で描画できるようにする必要があります。

-

一部の植物や草を作っている場合は、アルファテストでの解決が一般的です。

-

どの解決策を選択するかは、あなたのニーズによります。

- -
-
-
- - - - - - - - diff --git a/manual/ja/voxel-geometry.html b/manual/ja/voxel-geometry.html deleted file mode 100644 index 904c25aa1206af..00000000000000 --- a/manual/ja/voxel-geometry.html +++ /dev/null @@ -1,42 +0,0 @@ - - - Voxel(Minecraft Like) Geometry - - - - - - - - - - - - - -
-
-

Voxel(Minecraft Like) Geometry

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/webxr-basics.html b/manual/ja/webxr-basics.html deleted file mode 100644 index f7af921ade6b6d..00000000000000 --- a/manual/ja/webxr-basics.html +++ /dev/null @@ -1,42 +0,0 @@ - - - VR - - - - - - - - - - - - - -
-
-

VR

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/webxr-look-to-select.html b/manual/ja/webxr-look-to-select.html deleted file mode 100644 index 9c011fe92bc2e3..00000000000000 --- a/manual/ja/webxr-look-to-select.html +++ /dev/null @@ -1,42 +0,0 @@ - - - VR - Look to Select - - - - - - - - - - - - - -
-
-

VR - Look to Select

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ja/webxr-point-to-select.html b/manual/ja/webxr-point-to-select.html deleted file mode 100644 index 85b643373559f9..00000000000000 --- a/manual/ja/webxr-point-to-select.html +++ /dev/null @@ -1,42 +0,0 @@ - - - VR - 3DOF Point to Select - - - - - - - - - - - - - -
-
-

VR - 3DOF Point to Select

-
-
-
-

すいません、この記事はまだ翻訳してません. Translations Welcome! 😄

-

ここに元の英語の記事があります.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/align-html-elements-to-3d.html b/manual/ko/align-html-elements-to-3d.html deleted file mode 100644 index d67dc8342abe25..00000000000000 --- a/manual/ko/align-html-elements-to-3d.html +++ /dev/null @@ -1,648 +0,0 @@ - - - HTML 요소를 3D로 정렬하기 - - - - - - - - - - - - - - -
-
-

HTML 요소를 3D로 정렬하기

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, 먼저 Three.js의 기본 구조에 관한 글을 읽고 오길 권장합니다.

-

때로 3D 장면에 텍스트를 넣어야 하는 경우가 있을 겁니다. 방법이야 다양하지만 각기 장단점이 있죠.

-
    -
  • 3D 텍스트를 쓴다.

    -

    원시 모델에 관한 글을 보면 TextGeometry로 3D 텍스트를 만든 예제를 찾을 수 있을 겁니다. 로고에 애니메이션을 준다던가 하는 경우에는 유용하지만 상태, 정보, 이름 등을 붙이는 경우라면 오히려 불편하겠죠.

    -
  • -
  • 2D 텍스트로 텍스처를 만들어 렌더링한다.

    -

    캔버스를 텍스처로 활용하기를 보면 캔버스를 텍스처로 활용하는 방법이 나옵니다. 캔버스에 텍스처를 렌더링하고 이 캔버스를 광고판처럼 렌더링하는 거죠. 이 방법의 장점은 텍스트가 3D 장면 안에 포함된다는 겁니다. 컴퓨터 화면에 나타난 텍스트 등을 렌더링하려면 이 방법이 가장 적당하겠죠.

    -
  • -
  • HTML 요소의 위치를 3D에 맞춘다.

    -

    이 방법의 장점은 HTML의 모든 기능을 사용할 수 있다는 겁니다. HTML에 자식 요소를 얼마든지 추가할 수도 있고, CSS로 스타일을 지정할 수도 있고, 실제 텍스트이니 사용자가 직접 선택할 수도 있죠.

    -
  • -
-

이 글에서는 맨 마지막 방법에 대해 다룰 겁니다.

-

간단한 것부터 시작해보죠. 원시 모델 위에 이름표를 붙인 3D 장면을 구현할 겁니다. 예제는 반응형 디자인에 관한 글의 예제를 수정해 쓰도록 하죠.

-

여기에 OrbitControls를 넣습니다. 조명에 관한 글에서 다뤘었죠.

-
import * as THREE from 'three';
-+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 0, 0);
-controls.update();
-
-

이름표를 담을 HTML 요소도 추가합니다.

-
<body>
--  <canvas id="c"></canvas>
-+  <div id="container">
-+    <canvas id="c"></canvas>
-+    <div id="labels"></div>
-+  </div>
-</body>
-
-

캔버스 요소와 <div id="labels"><div id="container">의 자식으로 둔 뒤 CSS로 서로 겹치게 합니다.

-
#c {
--    width: 100%;
--    height: 100%;
-+    width: 100%;  /* id=container가 사이즈를 결정하도록 합니다. */
-+    height: 100%;
-    display: block;
-}
-+#container {
-+  position: relative;  /* 자식이 이 요소를 기준 삼도록 합니다. */
-+  width: 100%;
-+  height: 100%;
-+  overflow: hidden;
-+}
-+#labels {
-+  position: absolute;  /* 캔버스 위에 자리잡도록 합니다. */
-+  left: 0;             /* id=container 위 왼쪽에 기준하도록 합니다. */
-+  top: 0;
-+  color: white;
-+}
-
-

이름표의 CSS도 작성합니다.

-
#labels > div {
-  position: absolute;  /* 캔버스 위에 자리잡도록 합니다.  */
-  left: 0;             /* 부모의 위 왼쪽에 기준하도록 합니다. */
-  top: 0;
-  cursor: pointer;     /* 포인터가 위에 올라갔을 때 포인터 스타일을 바꿉니다. */
-  font-size: large;
-  user-select: none;   /* 텍스트를 선택할 수 없도록 합니다. */
-  text-shadow:         /* 글자에 검은 테두리를 두릅니다. */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-#labels > div:hover {
-  color: red;
-}
-
-

자바스크립트 쪽은 수정사항이 많지 않습니다. makeInstance라는 함수에서 정육면체를 만들 때 이름표 요소(element)를 같이 만들도록 바꿉니다.

-
+const labelContainerElem = document.querySelector('#labels');
-
--function makeInstance(geometry, color, x) {
-+function makeInstance(geometry, color, x, name) {
-  const material = new THREE.MeshPhongMaterial({ color });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const elem = document.createElement('div');
-+  elem.textContent = name;
-+  labelContainerElem.appendChild(elem);
-
--  return cube;
-+  return { cube, elem };
-}
-
-

이제 각 정육면체를 만들 때 새로운 <div> 요소를 <div id="labels">에 추가할 겁니다. 또한 정육면체(cube)만 반환하는 게 아니라 이름표 요소(label)를 같이 반환합니다.

-

함수를 호출할 때 이름을 같이 넘겨주도록 바꿉니다.

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
-+  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-];
-
-

이제 렌더링 시 이름표의 위치만 정해주면 끝입니다.

-
const tempV = new THREE.Vector3();
-
-...
-
--cubes.forEach((cube, ndx) => {
-+cubes.forEach((cubeInfo, ndx) => {
-+  const { cube, elem } = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-+  // 정육면체의 중심 좌표를 가져옵니다.
-+  cube.updateWorldMatrix(true, false);
-+  cube.getWorldPosition(tempV);
-+
-+  /**
-+   * 정규화(normalize)된 화면 상의 현재 좌표값을 가져옵니다.
-+   * x와 y의 범위는 -1에서 +1까지로, x = -1은 왼쪽, y = -1은 아래쪽입니다.
-+   **/
-+  tempV.project(camera);
-+
-+  // 정규화된 위치값을 CSS 좌표로 바꿉니다.
-+  const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-+  const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-+
-+  // 이름표 요소를 해당 좌표로 옮깁니다.
-+  elem.style.transform = `translate(-50%, -50%) translate(${ x }px,${ y }px)`;
-});
-
-

- -

-

하지만 좀 어색합니다. 몇 가지 개선해야 할 점들이 보이네요.

-

먼저 정육면체들을 돌려 정육면체가 겹치도록 하니 이름표도 겹쳐 보입니다.

-
- -

또 화면을 축소해 정육면체가 절두체(frustum) 밖으로 벗어나게 해도 이름표가 여전히 보입니다.

-

이름표가 겹쳐 보이는 건 피킹에 관한 글에서 썼던 기법을 이용해 해결할 수 있습니다. 이름표 위치에서 RayCaster로 광선을 쏴 처음으로 걸리는 물체가 이름표와 짝이 아니라면 이름표를 보이지 않게 하는 것이죠.

-
const tempV = new THREE.Vector3();
-+const raycaster = new THREE.Raycaster();
-
-...
-
-cubes.forEach((cubeInfo, ndx) => {
-  const {cube, elem} = cubeInfo;
-  const speed = 1 + ndx * .1;
-  const rot = time * speed;
-  cube.rotation.x = rot;
-  cube.rotation.y = rot;
-
-  // 정육면체의 중심 좌표를 가져옵니다.
-  cube.updateWorldMatrix(true, false);
-  cube.getWorldPosition(tempV);
-
-  /**
-   * 정규화(normalize)된 화면 상의 현재 좌표값을 가져옵니다.
-   * x와 y의 범위는 -1에서 +1까지로, x = -1은 왼쪽, y = -1은 아래쪽입니다.
-   **/
-  tempV.project(camera);
-
-+  // raycaster로 이름표의 시점과 만나는 물체를 구합니다.
-+  raycaster.setFromCamera(tempV, camera);
-+  const intersectedObjects = raycaster.intersectObjects(scene.children);
-+  // 짝궁 정육면체가 제일 처음 보이는 물체와 같다면 이름표를 보이게 합니다.
-+  const show = intersectedObjects.length && cube === intersectedObjects[0].object;
-+
-+  if (!show) {
-+    // 이름표를 숨깁니다.
-+    elem.style.display = 'none';
-+  } else {
-+    // 이름표를 보이게 합니다.
-+    elem.style.display = '';
-
-    // 정규화된 위치값을 CSS 좌표로 바꿉니다.
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // 이름표 요소를 해당 좌표로 옮깁니다.
-    elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-+  }
-});
-
-

겹치는 문제를 해결했습니다.

-

절두체 밖으로 나갔을 경우의 문제를 해결해봅시다. tempV.z 값으로 정육면체의 중심이 절두체 밖으로 나갔는지를 확인해 해결할 수 있을 것 같네요.

-
-  if (!show) {
-+  if (!show || Math.abs(tempV.z) > 1) {
-    // 이름표를 숨깁니다.
-    elem.style.display = 'none';
-
-

잘 적용된 것 같지만 뭔가 2% 부족합니다. 이전에 계산했던 정규화된 좌표에는 z값이 있고, 이 값의 -1은 카메라의 near, +1은 far을 의미하거든요.

-

- -

-

위 방법은 물체의 중점을 기준으로 이름표의 노출 여부를 계산하기에 실제로 사용하기 어렵습니다. 큰 물체의 경우 중점이 절두체의 바깥에 있더라도 나머지 반쪽은 절두체 안에 있을 수 있으니까요.

-

더 정확한 방법은 해당 물체가 절두체 안에 있는지 확인하는 겁니다. 물론 더 많은 연산이 필요하겠죠. 정육면체 3개 정도야 크게 부담이 되진 않을지 몰라도 물체가 많아지면 그만큼 연산 부담도 커질 겁니다.

-

Three.js에는 물체의 경계 구체(bounding sphere)가 절두체 안에 있는지 계산해주는 함수가 있습니다.

-
// 초기화 단계
-const frustum = new THREE.Frustum();
-const viewProjection = new THREE.Matrix4();
-
-...
-
-// 좌표 확인 전
-camera.updateMatrix();
-camera.updateMatrixWorld();
-camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
-
-...
-
-// 각 mesh마다 좌표를 업데이트합니다.
-someMesh.updateMatrix();
-someMesh.updateMatrixWorld();
-
-viewProjection.multiplyMatrices(
-    camera.projectionMatrix, camera.matrixWorldInverse);
-frustum.setFromProjectionMatrix(viewProjection);
-const inFrustum = frustum.contains(someMesh));
-
-

지금의 예제는 피킹을 사용하기에 성능이 다소 느립니다. 피킹에 관한 글에서 다뤘듯 GPU 기반 피킹을 쓸 수도 있지만 구현하기가 복잡하죠. 어떤 방법을 적용할지는 상황을 보고 판단해야 합니다.

-

또 이름표가 나타나는 순서에도 문제가 있습니다. 현재 예제의 이름표를 더 길게 바꿔보죠.

-
const cubes = [
--  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
--  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
--  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-+  makeInstance(geometry, 0x44aa88,  0, 'Aqua Colored Box'),
-+  makeInstance(geometry, 0x8844aa, -2, 'Purple Colored Box'),
-+  makeInstance(geometry, 0xaa8844,  2, 'Gold Colored Box'),
-];
-
-

CSS도 바꿔 줄바꿈이 일어나지 않도록 합니다.

-
#labels > div {
-+  white-space: nowrap;
-
-

이러면 아래와 같은 문제가 나타납니다.

-
- -

위 그림에서 보라색 정육면체는 청록색 정육면체의 뒤에 있지만, 보라색 정육면체의 이름표는 청록색 정육면체의 앞에 있습니다.

-

이름표 요소에 z-index 스타일을 지정해 이 문제를 해결할 수 있습니다. 계산된 위치값에는 -1이 앞, 1이 뒤를 의미하는 z값이 있죠. z-index값은 정수이고 값이 클수록 앞에 위치하니 다음과 같이 하면 제대로 정렬될 겁니다.

-
// 정규화된 위치값을 CSS 좌표로 바꿉니다.
-const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-// 이름표 요소를 해당 좌표로 옮깁니다.
-elem.style.transform = `translate(-50%, -50%) translate(${ x }px,${ y }px)`;
-
-+// 정렬을 위해 z-index 값을 설정합니다.
-+elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-
-

z값은 소수점 단위의 값이기에 충분히 큰 숫자를 지정하지 않으면 비슷한 z-index가 지정될 수 있습니다. 또한 이름표가 페이지의 다른 요소를 가리지 않도록 이름표 컨테이너 요소의 z-index를 설정합니다. 이러면 브라우저가 새 쌓임 컨텍스트(stacking context)를 만들어 이름표의 z-index가 아무리 커도 다른 페이지 요소의 위에 올라가지 않도록 할 수 있습니다.

-
#labels {
-  position: absolute;  /* 캔버스 위에 자리잡도록 합니다.  */
-+  z-index: 0;          /* 새 쌓임 컨테스트를 만들어 자식 요소가 페이지의 다른 요소와 엉키지 않도록 합니다. */
-  left: 0;             /* 부모의 위 왼쪽에 기준하도록 합니다. */
-  top: 0;
-  color: white;
-  z-index: 0;
-}
-
-

이제 이름표가 제대로 정렬되어 보일 겁니다.

-

- -

-

여기서 끝낼 수도 있으나 예제를 하나 더 만들어 복잡한 상황에서 발생할 수 있는 문제를 알아보겠습니다. 구글 맵같은 지구본을 만들어 각 나라의 이름을 표시해보도록 하죠.

-

인터넷을 뒤져 각 나라의 영역 데이터를 찾았습니다. 라이선스는 CC-BY-SA네요.

-

개인적으로 코드를 작성해 각 나라의 윤곽선을 만들고 나라의 이름과 위치를 JSON 데이터로 만들었습니다.

-
- -

JSON 데이터는 아래와 같은 형태의 배열입니다.

-
[
-  {
-    "name": "Algeria",
-    "min": [
-      -8.667223,
-      18.976387
-    ],
-    "max": [
-      11.986475,
-      37.091385
-    ],
-    "area": 238174,
-    "lat": 28.163,
-    "lon": 2.632,
-    "population": {
-      "2005": 32854159
-    }
-  },
-  ...
-
-

min, max, lat, lon은 나라의 위도(latitude)와 경도(longitude)를 나타냅니다.

-

데이터를 실제로 사용해봅시다. 다중 요소 렌더링 최적화하기에서 썼던 예제를 기반으로 사용하겠습니다. 물론 많은 요소를 렌더링하는 건 아니지만, 기존 코드에 포함되어 있는 불필요한 렌더링 제거 기법도 그대로 사용할 겁니다.

-

먼저 구체를 만들고 각 나라의 육곽선 텍스처를 입힙니다.

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({ map: texture });
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

다음으로 로더를 만들어 JSON 파일을 불러옵니다.

-
async function loadJSON(url) {
-  const req = await fetch(url);
-  return req.json();
-}
-
-...
-
-let countryInfos;
-async function loadCountryData() {
-  countryInfos = await loadJSON('resources/data/world/country-info.json');
-     ...
-  }
-  requestRenderIfNotRequested();
-}
-loadCountryData();
-
-

불러온 데이터로 각 나라와 이름표를 생성합니다.

-

다중 요소 렌더링 최적화하기에서 씬 그래프를 활용해 지구본의 위도와 경도를 계산했었죠. 이번에도 계산을 단순화하기 위해 이 방법을 그대로 사용합니다. 아래 코드가 어떻게 작동하는가에 대해서는 원본 글을 참고하기 바랍니다.

-
const lonFudge = Math.PI * 1.5;
-const latFudge = Math.PI;
-// 아래 헬퍼 Object3D는 육면체들의 위치 변화를 간단하게 만들어줍니다.
-// lonHelper를 Y축으로 돌려 경도(longitude)를 맞출 수 있습니다.
-const lonHelper = new THREE.Object3D();
-// latHelper를 X축으로 돌려 위도(latitude)를 맞출 수 있습니다.
-const latHelper = new THREE.Object3D();
-lonHelper.add(latHelper);
-// positionHelper는 다른 요소의 기준축을 구체의 끝에 맞추는 역할을 합니다.
-const positionHelper = new THREE.Object3D();
-positionHelper.position.z = 1;
-latHelper.add(positionHelper);
-
-

각 이름표의 좌표를 계산합니다.

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const { lat, lon, name } = countryInfo;
-
-  // 헬퍼가 위도와 경도를 가리키게 바꿉니다.
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // 위도와 경도를 구합니다.
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-  // 각 나라마다 텍스트 요소를 추가합니다.
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-
-

위 코드는 아까와 비슷하게 각 나라마다 텍스트 요소를 만들었습니다. 이전에는 따로 배열을 두었지만 이번에는 각 나라에 대한 정보가 있는 contryInfos가 있죠. 이 요소의 elem 속성에 이름표 요소를, 지구본 위의 위치값을 position 속성에 지정했습니다.

-

또한 정육면체 예제와 마찬가지로 이름표의 위치를 렌더링 시에 업데이트하도록 합니다.

-
const tempV = new THREE.Vector3();
-
-function updateLabels() {
-  // JSON 파일을 아직 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-  for (const countryInfo of countryInfos) {
-    const {position, elem} = countryInfo;
-
-    /**
-     * 정규화(normalize)된 화면 상의 현재 좌표값을 가져옵니다.
-     * x와 y의 범위는 -1에서 +1까지로, x = -1은 왼쪽, y = -1은 아래쪽입니다.
-     **/
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // 정규화된 위치값을 CSS 좌표로 바꿉니다.
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // 이름표 요소를 해당 좌표로 옮깁니다.
-    elem.style.transform = `translate(-50%, -50%) translate(${ x }px,${ y }px)`;
-
-    // 정렬을 위해 z-index 값을 설정합니다.
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

위 코드는 이전 예제와 대체로 비슷합니다. 이름표의 위치를 초기화할 때 미리 계산한다는 것만 다르죠. 지구본이 움직이는 게 아니라 카메라가 움직이기에 이렇게 구현할 수 있습니다.

-

다음으로 렌더링 루프에서 updateLabels 함수를 호출합니다.

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  controls.update();
-
-+  updateLabels();
-
-  renderer.render(scene, camera);
-}
-
-

결과를 보죠.

-

- -

-

이름표가 넘쳐 나네요!

-

문제를 따져보자면 크게 2가지입니다.

-
    -
  1. 카메라 반대편을 바라보는 이름표도 나타난다.

    -
  2. -
  3. 이름표가 너무 많아 읽기가 힘들다.

    -
  4. -
-

문제 #1번은 이전처럼 RayCaster를 사용할 수가 없습니다. 감지할 수 있는 게 구체밖에 없거든요. 대신 특정 나라가 카메라에 보이는지는 확인할 수 있을 겁니다. 지금 예제의 이름표들은 반지름이 1.0인 구체의 바깥면에 있습니다. 이미 구체 단위로 정렬이 된 것이니 계산이 그나마 쉽겠죠.

-
const tempV = new THREE.Vector3();
-+const cameraToPoint = new THREE.Vector3();
-+const cameraPosition = new THREE.Vector3();
-+const normalMatrix = new THREE.Matrix3();
-
-function updateLabels() {
-  // JSON 파일을 아직 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-+  const minVisibleDot = 0.2;
-+  // 카메라의 상대 방향을 나타내는 행렬 좌표를 가져옵니다.
-+  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-+  // 카메라의 위치를 가져옵니다.
-+  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-    const { position, elem } = countryInfo;
-
-+    /**
-+     * 카메라의 방향에 기반해 위치를 조정합니다.
-+     * 구체는 중점에 있고 구체의 반지름이 한 칸이기에 아래는
-+     * 카메라에 상대적인 위치 벡터를 반환합니다.
-+     **/
-+    tempV.copy(position);
-+    tempV.applyMatrix3(normalMatrix);
-+
-+    // 카메라로부터 이 위치까지의 거리를 계산합니다.
-+    cameraToPoint.copy(position);
-+    cameraToPoint.applyMatrix4(camera.matrixWorldInverse).normalize();
-+
-+    /**
-+     * 카메라에서 현재 위치의 방향(벡터)값으로 카메라에서 지구본 위 위치값까지의
-+     * 방향값을 구한 뒤, 이 값들로 스칼라곱을 구합니다.
-+     * 1 = 카메라를 바라봄
-+     * 0 = 카메라가 구체를 바라봤을 때 구체의 탄젠트(tangent) 지점에 있음
-+     * < 0 = 다른 쪽을 바라봄
-+     **/
-+    const dot = tempV.dot(cameraToPoint);
-+
-+    // 카메라를 바라보지 않는다면 이름표를 숨깁니다.
-+    if (dot < minVisibleDot) {
-+      elem.style.display = 'none';
-+      continue;
-+    }
-+
-+    // 이름표 요소에 기존 display 스타일이 적용되도록 합니다.
-+    elem.style.display = '';
-
-    /**
-     * 정규화(normalize)된 화면 상의 현재 좌표값을 가져옵니다.
-     * x와 y의 범위는 -1에서 +1까지로, x = -1은 왼쪽, y = -1은 아래쪽입니다.
-     **/
-    tempV.copy(position);
-    tempV.project(camera);
-
-    // 정규화된 위치값을 CSS 좌표로 바꿉니다.
-    const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-    const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-    // 이름표 요소를 해당 좌표로 옮깁니다.
-    elem.style.transform = `translate(-50%, -50%) translate(${ x }px,${ y }px)`;
-
-    // 정렬을 위해 z-index 값을 설정합니다.
-    elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-  }
-}
-
-

위 코드는 위치값을 방향(벡터)값으로 써 카메라에 상대적인 위치값을 구합니다. 그리고 카메라에서 지구본 위 해당 위치값까지의 방향값을 구해 이걸로 스칼라곱(dot product)을 구하죠. 이 스칼라곱은 각 벡터 사이의 각도의 코사인값입니다. 이 값이 -1이면 이름표가 카메라를 바라본다는 것이고, 0은 완벽하게 구체 가장자리에 있다는 것, 0보다 크면 구체의 뒤에 있다는 것을 의미하죠.

-
-
-
-
-
- -

위 그림에서 이름표(label)가 바라보는 방향과 카메라가 이름표를 바라보는 방향의 스칼라곱을 확인할 수 있습니다. GUI로 이름표를 돌리면 스칼라곱이 -1.0일 때는 이름표가 완벽히 카메라를 바라보고, 0.0일 때는 두 화살표가 서로 완전히 수직이 됩니다. 90도, 그러니까 스칼라곱이 0보다 클 때는 이름표가 구체 뒤로 가죠.

-

다음으로 #2번 문제, 이름표가 너무 많이 뭉쳐 있는 문제를 해결해봅시다. 일단 이름표의 노출 여부를 결정할 방법을 마련해야 합니다. 한 방법은 땅덩어리가 큰 나라만 우선 보여주는 겁니다. 아까 불러온 데이터에 나라가 차지하는 영역에 대한 min, max 값이 있었죠. 이를 이용해 각 나라의 영역 크기을 계산하면 어떤 나라를 우선적으로 보여줄지 결정할 수 있을 겁니다.

-

먼저 초기화 시에 미리 영역 크기를 계산합니다.

-
const labelParentElem = document.querySelector('#labels');
-for (const countryInfo of countryInfos) {
-  const { lat, lon, min, max, name } = countryInfo;
-
-  // 헬퍼가 위도와 경도를 가리키게 바꿉니다.
-  lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-  latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-  // 위도와 경도를 구합니다.
-  positionHelper.updateWorldMatrix(true, false);
-  const position = new THREE.Vector3();
-  positionHelper.getWorldPosition(position);
-  countryInfo.position = position;
-
-+  // 각 나라의 영영 크기를 계산합니다.
-+  const width = max[0] - min[0];
-+  const height = max[1] - min[1];
-+  const area = width * height;
-+  countryInfo.area = area;
-
-  // 각 나라마다 텍스트 요소를 추가합니다.
-  const elem = document.createElement('div');
-  elem.textContent = name;
-  labelParentElem.appendChild(elem);
-  countryInfo.elem = elem;
-}
-
-

그리고 렌더링 루프에서 영역 크기를 기반으로 이름표의 노출 여부를 결정합니다.

-
+const large = 20 * 20;
-const maxVisibleDot = 0.2;
-// 카메라의 상대 방향을 나타내는 행렬 좌표를 가져옵니다.
-normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-// 카메라의 위치를 가져옵니다.
-camera.getWorldPosition(cameraPosition);
-for (const countryInfo of countryInfos) {
--  const { position, elem } = countryInfo;
-+  const { position, elem, area } = countryInfo;
-+  // 영역이 특정 값보다 작다면 이름표를 표시하지 않습니다.
-+  if (area < large) {
-+    elem.style.display = 'none';
-+    continue;
-+  }
-
-  ...
-
-

마지막으로 어떤 값이 적당한지 알기 어려우니 이 값을 조정할 수 있도록 GUI를 추가합니다.

-
import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-
+const settings = {
-+  minArea: 20,
-+  maxVisibleDot: -0.2,
-+};
-+const gui = new GUI({ width: 300 });
-+gui.add(settings, 'minArea', 0, 50).onChange(requestRenderIfNotRequested);
-+gui.add(settings, 'maxVisibleDot', -1, 1, 0.01).onChange(requestRenderIfNotRequested);
-
-function updateLabels() {
-  if (!countryInfos) {
-    return;
-  }
-
--  const large = 20 * 20;
--  const maxVisibleDot = -0.2;
-+  const large = settings.minArea * settings.minArea;
-  // 카메라의 상대 방향을 나타내는 행렬 좌표를 가져옵니다.
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // 카메라의 위치를 가져옵니다.
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
-
-    ...
-
-    // 카메라를 바라보지 않는다면 이름표를 숨깁니다.
--   if (dot > maxVisibleDot) {
-+   if (dot > settings.maxVisibleDot) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-

이제 결과를 보죠.

-

- -

-

지구본을 돌려보면 뒤로 간 이름표가 사라지는 걸 확인할 수 있습니다. minVisibleDot 값을 조정하면 사라지는 지점이 변하고, minArea 값을 조정하면 영역이 더 작은/큰 나라를 볼 수 있죠.

-

작업을 진행할수록 구글 맵을 구현하는 데 굉장히 많은 노력이 들어갔겠구나 하는 생각이 들었습니다. 아마 구글 팀도 여러 기준을 사용했을 겁니다. 사용자의 현재 위치나 기본 언어 설정, 로그인되어 있다면 계정 설정, 또는 인기도나 임의의 우선 순위를 설정해서 보여주는 등 기준으로 삼을 수 있는 건 무궁무진하죠.

-

모든 상황을 다 가정할 수는 없지만, 이 글이 HTML 요소를 3D 요소에 맞춰 정렬하는 데 도움이 되었으면 합니다. 아마 몇 가지 내용은 나중에 바뀔 수도 있으니 참고해주세요.

-

다음 글에서는 더 나아가 지구본 위의 나라를 선택하고 강조해보겠습니다.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/backgrounds.html b/manual/ko/backgrounds.html deleted file mode 100644 index 557334b3593fc5..00000000000000 --- a/manual/ko/backgrounds.html +++ /dev/null @@ -1,256 +0,0 @@ - - - 배경과 하늘 상자 - - - - - - - - - - - - - - -
-
-

배경과 하늘 상자

-
-
-
-

이 시리즈의 예제 대부분은 단색 배경을 사용했습니다.

-

Three.js에서 단순한 배경을 넣는 건 CSS만큼이나 쉽습니다. 반응형 디자인에 관한 -글의 예제에서 2가지만 바꿔주면 되죠.

-

먼저 CSS로 canvas에 배경을 추가합니다.

-
<style>
-body {
-    margin: 0;
-}
-#c {
-    width: 100%;
-    height: 100%;
-    display: block;
-+    background: url(resources/images/daikanyama.jpg) no-repeat center center;
-+    background-size: cover;
-}
-</style>
-
-

그리고 WebGLRendereralpha 옵션을 켜 아무것도 없는 공간은 투명하게 -보이도록 설정합니다.

-
function main() {
-  const canvas = document.querySelector('#c');
--  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const renderer = new THREE.WebGLRenderer({
-+    antialias: true,
-+    canvas,
-+    alpha: true,
-+  });
-
-

간단하지 않나요?

-

- -

-

배경이 후처리 효과의 영향을 받게 하려면 -Three.js로 배경을 렌더링해야 합니다.

-

간단히 장면의 배경에 텍스처를 입혀주기만 하면 되죠.

-
const loader = new THREE.TextureLoader();
-const bgTexture = loader.load('resources/images/daikanyama.jpg');
-bgTexture.colorSpace = THREE.SRGBColorSpace;
-scene.background = bgTexture;
-
-

- -

-

배경이 지정되긴 했지만, 화면에 맞춰 늘어났네요.

-

이미지의 일부만 보이도록 repeatoffset 속성을 조정해 문제를 해결해봅시다.

-
function render(time) {
-
-   ...
-+  /**
-+   * 배경 텍스처의 repeat과 offset 속성을 조정해 이미지의 비율이 깨지지
-+   * 않도록 합니다.
-+   * 이미지를 불러오는 데 시간이 걸릴 수 있으니 감안해야 합니다.
-+   **/
-+  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
-+  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
-+  const aspect = imageAspect / canvasAspect;
-+
-+  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
-+  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
-+
-+  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
-+  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

이제 Three.js가 배경을 렌더링합니다. 그냥 보기에 CSS와 큰 차이는 없지만, -후처리 효과의 영향을 받는다는 점이 다릅니다.

-

- -

-

물론 3D 장면을 만들 때 단순한 배경을 자주 사용하진 않습니다. 대신 주로 일종의 -하늘 상자(skybox)를 사용하죠. 하늘 상자란 말 그대로 하늘을 그려놓은 상자로써, -상자 안에 카메라를 놓으면 마치 배경에 하늘이 있는 것처럼 보이는 효과를 줍니다.

-

일반적으로 육면체에 텍스처를 입히고 안쪽을 렌더링하도록 설정해 하늘 상자를 -구현합니다. 각 면에 수평선처럼 보이는 이미지를 텍스처로 배치하는 거죠(텍스처 -좌표를 이용해). 하늘 구체(sky sphere)나 하늘 돔(sky dom)도 자주 사용하는 -방식입니다. 다시 말해 육면체나 구체를 만들고, 텍스처를 입힌 -뒤, 바깥 면이 아닌 안쪽 면을 렌더링하도록 THREE.BackSide 값을 넣어주면 -됩니다. 그리고 바로 장면(scene)에 추가하거나, 하늘 상자/구체/돔을 담당할 -장면 하나, 다른 요소를 담당할 장면 하나 이렇게 총 2개를 만들 수도 있죠. -OrthographicCamera를 쓸 필요는 없으니 PerspectiveCamera를 그대로 -사용하면 됩니다.

-

다른 방법 중 하나는 큐브맵(Cubemap)입니다. 큐브맵은 정육면체의 한 면 당 -하나, 총 6개의 면을 가진 텍스처로, 텍스처 좌표 대신 중앙에서 바깥쪽을 가리키는 -방향으로 색상값을 결정합니다.

-

아래 6개의 이미지는 캘리포니아 마운틴 뷰에 있는 컴퓨터 역사 박물관에서 찍은 -사진입니다.

-
- - - -
-
- - - -
- -

이들을 CubeTextureLoader로 불러와 장면의 배경으로 설정합니다.

-
{
-  const loader = new THREE.CubeTextureLoader();
-  const texture = loader.load([
-    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
-    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
-    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
-  ]);
-  scene.background = texture;
-}
-
-

이 텍스처는 별도 조정이 필요 없으니 위에서 작성했던 코드를 삭제합니다.

-
function render(time) {
-
-   ...
-
--  /**
--   * 배경 텍스처의 repeat과 offset 속성을 조정해 이미지의 비율이 깨지지
--   * 않도록 합니다.
--   * 이미지를 불러오는 데 시간이 걸릴 수 있으니 감안해야 합니다.
--   **/
--  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
--  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
--  const aspect = imageAspect / canvasAspect;
--
--  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
--  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
--
--  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
--  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
-
-  ...
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

카메라도 조작이 가능하도록 만듭니다.

-
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // canvas 기본값
-const near = 0.1;
--const far = 5;
-+const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 3;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

예제를 드래그하면 큐브맵이 주위를 둘러싼 게 보일 겁니다.

-

- -

-

다른 방법은 등장방형도법(Equirectangular map)을 이용하는 겁니다. 이런 사진은 -주로 360도 카메라로 촬영합니다.

-

다음 사진이 사이트에서 -가져온 사진입니다.

-
- -

등장방형도법의 사용법은 별로 다르지 않습니다. 먼저 등장방형도법 이미지를 텍스처로 불러온 뒤, 콜백에서 불러온 이미지 텍스처를 WebGLCubeRenderTarget.fromEquirectangularTexture를 호출할 때 넘겨주면 큐브맵(정육면체를 펼친 모양의 텍스처)를 만들 수 있습니다. WebGLCubeRenderTarget을 생성할 때 큐브맵의 크기를 지정해주기만 하면 되죠. 예제의 경우 등장방형도법 이미지의 높이를 넘겨주면 될 겁니다.

-
{
--  const loader = new THREE.CubeTextureLoader();
--  const texture = loader.load([
--    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-x.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-y.jpg',
--    'resources/images/cubemaps/computer-history-museum/pos-z.jpg',
--    'resources/images/cubemaps/computer-history-museum/neg-z.jpg',
--  ]);
--  scene.background = texture;
-+  const loader = new THREE.TextureLoader();
-+  const texture = loader.load(
-+    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
-+    () => {
-+      texture.mapping = THREE.EquirectangularReflectionMapping;
-+      texture.colorSpace = THREE.SRGBColorSpace;
-+      scene.background = texture;
-+    });
-}
-
-

어렵지 않게 등장방형도법 텍스처를 구현했습니다.

-

- -

-

등장방형도법은 복잡한 쉐이더를 사용하기에 큐브맵보다 성능이 떨어집니다. -다행히 등장방형도법 이미지를 큐브맵으로 바꾸는 건 그다지 어려운 일이 아니죠. -이 사이트를 이용하면 쉽게 -이미지를 변경할 수 있을 겁니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/billboards.html b/manual/ko/billboards.html deleted file mode 100644 index 5450dbac1666e3..00000000000000 --- a/manual/ko/billboards.html +++ /dev/null @@ -1,282 +0,0 @@ - - - 빌보드(Billboards) - - - - - - - - - - - - - - -
-
-

빌보드(Billboards)

-
-
-
-

이전 글에서는 CanvasTexture를 이용해 캐릭터에 이름표/명찰을 붙이는 법을 알아봤습니다. 때로는 이 이름표가 항상 카메라를 향하게 해야 할 경우도 있겠죠. Three.js의 SpriteSpriteMaterial을 사용하면 이걸 쉽게 구현할 수 있습니다.

-

캔버스 텍스처에 관한 글의 명찰 예제를 가져와 여기에 SpriteSpriteMaterial을 사용해봅시다.

-
function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // 텍스처용 캔버스는 2D이므로 픽셀이 모자랑 경우 대략적으로
-  // 필터링하게끔 설정합니다.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-
--  const labelMaterial = new THREE.MeshBasicMaterial({
-+  const labelMaterial = new THREE.SpriteMaterial({
-    map: texture,
--    side: THREE.DoubleSide,
-    transparent: true,
-  });
-
-  const root = new THREE.Object3D();
-  root.position.x = x;
-
-  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-  root.add(body);
-  body.position.y = bodyHeight / 2;
-
-  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-  root.add(head);
-  head.position.y = bodyHeight + headRadius * 1.1;
-
--  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  const label = new THREE.Sprite(labelMaterial);
-  root.add(label);
-  label.position.y = bodyHeight * 4 / 5;
-  label.position.z = bodyRadiusTop * 1.01;
-
-

이제 명찰이 항상 카메라를 바라봅니다.

-

- -

-

하지만 특정 각도에서 보니 명찰이 사람과 겹쳐 보입니다.

-
- -

간단히 명찰의 위치를 옮겨버리면 문제를 해결할 수 있겠죠.

-
+// 명찰의 크기를 조정합니다.
-+const labelBaseScale = 0.01;
-const label = new THREE.Sprite(labelMaterial);
-root.add(label);
--label.position.y = bodyHeight * 4 / 5;
--label.position.z = bodyRadiusTop * 1.01;
-+label.position.y = head.position.y + headRadius + size * labelBaseScale;
-
--// 명찰의 크기를 조정합니다.
--const labelBaseScale = 0.01;
-label.scale.x = canvas.width  * labelBaseScale;
-label.scale.y = canvas.height * labelBaseScale;
-
-

- -

-

추가로 이 빌보드(billboard, 광고판)*에 파사드를 적용할 수 있습니다.

-
-

※ 맥락상 명찰이 갑자기 빌보드가 되는 게 이상하지만, 원문의 흐름 자체를 수정할 수 없어 그대로 번역합니다. 또한 광고판으로 번역할 수도 있으나, 우리나라 사람들에게 광고판이라는 게 잘 와닿지 않을 것이기에 그냥 영문을 그대로 옮겨 표기하였습니다. 역주.

-
-

3D 물체를 그리는 대신 3D 물체의 이미지로 2D 평면을 렌더링하는 기법입니다. 꽤 많은 경우 3D 물체를 그냥 렌더링하는 것보다 빠르죠.

-

예제로 나무가 그리드 형태로 배치된 장면(scene)을 만들어봅시다. 각 나무의 줄기는 원통, 윗부분은 원뿔로 만들겠습니다.

-

먼저 모든 나무가 공통으로 사용할 원뿔, 원통의 geometry와 재질(material)을 만듭니다.

-
const trunkRadius = .2;
-const trunkHeight = 1;
-const trunkRadialSegments = 12;
-const trunkGeometry = new THREE.CylinderGeometry(
-    trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments);
-
-const topRadius = trunkRadius * 4;
-const topHeight = trunkHeight * 2;
-const topSegments = 12;
-const topGeometry = new THREE.ConeGeometry(
-    topRadius, topHeight, topSegments);
-
-const trunkMaterial = new THREE.MeshPhongMaterial({ color: 'brown' });
-const topMaterial = new THREE.MeshPhongMaterial({ color: 'green' });
-
-

다음으로 함수를 하나 만듭니다. 이 함수는 나무 줄기 Mesh와 윗부분 Mesh를 만들고 이 둘을 Object3D의 자식으로 넣는 역할입니다.

-
function makeTree(x, z) {
-  const root = new THREE.Object3D();
-  const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
-  trunk.position.y = trunkHeight / 2;
-  root.add(trunk);
-
-  const top = new THREE.Mesh(topGeometry, topMaterial);
-  top.position.y = trunkHeight + topHeight / 2;
-  root.add(top);
-
-  root.position.set(x, 0, z);
-  scene.add(root);
-
-  return root;
-}
-
-

그리고 반복문을 돌려 나무를 그리드 형태로 배치합니다.

-
for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
-    makeTree(x, z);
-  }
-}
-
-

땅 역할을 할 평면도 배치합니다.

-
// 땅을 추가합니다.
-{
-  const size = 400;
-  const geometry = new THREE.PlaneGeometry(size, size);
-  const material = new THREE.MeshPhongMaterial({ color: 'gray' });
-  const mesh = new THREE.Mesh(geometry, material);
-  mesh.rotation.x = Math.PI * -0.5;
-  scene.add(mesh);
-}
-
-

배경은 하늘색으로 바꿔줍니다.

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('white');
-+scene.background = new THREE.Color('lightblue');
-
-

- -

-

나무는 11x11, 총 121그루입니다. 각 나무는 12각형 원뿔과 48각형 원통으로 이루어졌으니, 나무 하나 당 삼각형이 60개인 셈입니다. 121 * 60이면 총 삼각형 7260개네요. 물론 그다지 많은 수는 아니지만 더 세밀한 3차원 나무는 하나당 1000-3000개의 삼각형이 필요할 겁니다. 나무 하나당 3000개면 총 36300개의 삼각형을 그려야 하는 셈이죠.

-

파사드(facade)를 이용하면 삼각형의 양을 줄일 수 있습니다.

-

그래픽 프로그램으로 파사드를 만들 수도 있지만, 코드를 작성해 직접 하나를 만들어봅시다.

-

RenderTarget을 이용해 3D 물체를 텍스처로 바꾸는 코드를 작성합니다. RenderTarget에 렌더링하는 법은 이전 글에서 다루었으니 참고 바랍니다.

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  camera.position.copy(boxCenter);
-  camera.position.z += distance;
-
-  // 절두체가 육면체를 포함하도록 near와 far 값을 조정합니다.
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-}
-
-function makeSpriteTexture(textureSize, obj) {
-  const rt = new THREE.WebGLRenderTarget(textureSize, textureSize);
-
-  const aspect = 1;  // 렌더 타겟이 정사각형이므로
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-  scene.add(obj);
-
-  // 물체를 감싼 육면체를 계산합니다.
-  const box = new THREE.Box3().setFromObject(obj);
-
-  const boxSize = box.getSize(new THREE.Vector3());
-  const boxCenter = box.getCenter(new THREE.Vector3());
-
-  // 카메라가 육면체를 감싸도록 설정합니다.
-  const fudge = 1.1;
-  const size = Math.max(...boxSize.toArray()) * fudge;
-  frameArea(size, size, boxCenter, camera);
-
-  renderer.autoClear = false;
-  renderer.setRenderTarget(rt);
-  renderer.render(scene, camera);
-  renderer.setRenderTarget(null);
-  renderer.autoClear = true;
-
-  scene.remove(obj);
-
-  return {
-    position: boxCenter.multiplyScalar(fudge),
-    scale: size,
-    texture: rt.texture,
-  };
-}
-
-

위 예제에서 주의 깊게 봐야하는 부분:

-

위 예제는 코드 밖에서 선언한 시야각 (field of view, fov)을 사용했습니다.

-

.obj 파일 불러오기에서 썼던 방법을 약간 수정해 나무를 감싼 육면체를 계산했습니다.

-

.obj 파일 불러오기에서 썼던 frameArea도 가져왔습니다. 이번에는 주어진 시아갹에 해당 물체가 포함되게 하려면 얼마나 떨어져야 하는지 계산할 때 사용했죠. 그리고 이 결과값으로 카메라를 물체를 감싼 육면체 중심에서 -z축 방향으로 옮겼습니다.

-

절두체의 크기를 1.1 (fudge(속임수))만큼 키워 나무가 렌더 타겟에 완전히 들어가도록 했습니다. 물체가 절두체 안에 있는지 계산한 결과는 물체의 가장자리를 포함하지 않기에 그대로 뒀다면 물체가 카메라 밖으로 벗어나 보였을 겁니다. 카메라가 완전히 물체를 담는 값을 계산할 수도 있지만, 그건 공간 낭비이기도 하기에 단순히 속임수를 사용한 것이죠.

-

그리고 렌더 타겟에 장면을 렌더링한 뒤 나무를 장면에서 제거했습니다.

-

여기서 중요한 건 조명은 따로 넣어야 하나, 다른 요소는 없도록 해야 한다는 겁니다.

-

일단 장면에서 배경색도 제거합니다.

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('lightblue');
-
-

마지막으로 함수에서 받은 텍스처의 위치와 스케일을 조정해 파사드가 같은 위치에 나타나도록 해야 합니다.

-

먼저 나무를 만들어 위에서 만든 함수에 넘겨줍니다.

-
// 빌보드 텍스처를 만듭니다.
-const tree = makeTree(0, 0);
-const facadeSize = 64;
-const treeSpriteInfo = makeSpriteTexture(facadeSize, tree);
-
-

다음으로 나무 대신 파사드를 그리드 형태로 배치합니다.

-
+function makeSprite(spriteInfo, x, z) {
-+  const { texture, offset, scale } = spriteInfo;
-+  const mat = new THREE.SpriteMaterial({
-+    map: texture,
-+    transparent: true,
-+  });
-+  const sprite = new THREE.Sprite(mat);
-+  scene.add(sprite);
-+  sprite.position.set(
-+      offset.x + x,
-+      offset.y,
-+      offset.z + z);
-+  sprite.scale.set(scale, scale, scale);
-+}
-
-for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
--    makeTree(x, z);
-+    makeSprite(treeSpriteInfo, x, z);
-  }
-}
-
-

위 코드에서는 파사드에 위치값과 스케일값을 지정해 원래 나무가 있어야할 위치에 파사드가 나타나도록 했습니다.

-

이제 파사드가 제자리에 위치했으니 배경색을 다시 지정합니다.

-
scene.background = new THREE.Color('lightblue');
-
-

나무 파사드로 이루어진 장면을 완성했습니다.

-

- -

-

아까 만들었던 예제와 비교해보면 꽤 비슷할 겁니다. 예제에서는 저-해상도 텍스처, 64x64 픽셀 텍스처를 사용했기에 파사드가 각져 보입니다. 해상도를 높일 수도 있지만, 파사드는 대게 먼 거리에서 작게 보이는 물체에 사용하기에 저-해상도로 사용해도 그다지 문제가 없습니다. 게다가 몇 픽셀되지도 않는 나무를 렌더링하는 데 낭비되는 자원을 절약할 수 있죠.

-

다른 문제는 나무를 한 각도에서 밖에 볼 수 없다는 겁니다. 이 문제는 대게 더 많은 파사드를 렌더링해 해결할 수 있죠. 예를 들어 8개의 파사드를 만들어 카메라가 물체를 바라보는 각도에 따라 다른 파사드를 보여줄 수 있을 겁니다.

-

파사드를 쓸 지는 전적으로 선택이지만, 이 글이 파사드의 활용에 도움이 되었으면 합니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/cameras.html b/manual/ko/cameras.html deleted file mode 100644 index 8118485e47812b..00000000000000 --- a/manual/ko/cameras.html +++ /dev/null @@ -1,536 +0,0 @@ - - - 카메라(Cameras) - - - - - - - - - - - - - - -
-
-

카메라(Cameras)

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글을 -읽고 오길 권장합니다.

-

이번 장에서는 카메라(cameras)에 대해 알아보겠습니다. 첫 번째 장에서 -일부 다루긴 했지만, 중요 요소인 만큼 더 자세히 살펴볼 필요가 있습니다.

-

Three.js에서 가장 자주 사용하는 카메라는 여태까지 썼던 PerspectiveCamera(원근 카메라)입니다. -이 카메라는 멀리 있는 물체를 가까이 있는 것보다 상대적으로 작게 보이도록 해주죠.

-

PerspectiveCamera절두체(frustum)를 만듭니다. 절두체(frustum)는 입체(보통 원뿔이나 각뿔)를 -절단하는 하나나 두 평행면 사이의 부분을 -의미하죠. 여기서 입체란 정육면체, 원뿔, 구, 원통, 절두체 등의 3D 요소입니다.

-
-
정육면체(cube)
-
원뿔(cone)
-
구(sphere)
-
원통(cylinder)
-
절두체(frustum)
-
- -

이걸 굳이 언급하는 이유는 글을 쓰는 저도 몇 년 동안 이를 몰랐기 때문입니다. 책이든 인터넷 글이든, -절두체라는 단어를 봤다면 눈이 뒤집어졌을 겁니다. 입체의 이름을 알면 이해하기도, 기억하기도 훨씬 -쉽죠 😅.

-

PerspectiveCamera는 4가지 속성을 바탕으로 절두체를 만듭니다. near는 절두체가 어디서 시작할지 -결정하는 속성이고, far는 절두체의 끝입니다. fov는 시아갹(field of view)으로, near와 카메라의 -거리에 따라 절두체의 높이를 계산해 적용합니다. aspect는 절두체의 너비에 관여하는 비율으로, 절두체의 -너비는 절두체의 높이에 이 비율을 곱한 값입니다.

-

-

이전 장에서 썼던 바닥면, 구체, 정육면체로 이루어진 예제를 다시 사용해 -카메라의 속성을 조정할 수 있도록 만들겠습니다.

-

near 속성은 항상 far 속성보다 커야 하니, 이를 제어할 MinMaxGUIHelper 헬퍼 클래스를 -만들겠습니다. 이 클래스는 lil-gui가 제어할 minmax 속성이 있고, lil-gui가 이를 조정할 -때 지정한 두 가지 속성을 동시에 변경합니다.

-
class MinMaxGUIHelper {
-  constructor(obj, minProp, maxProp, minDif) {
-    this.obj = obj;
-    this.minProp = minProp;
-    this.maxProp = maxProp;
-    this.minDif = minDif;
-  }
-  get min() {
-    return this.obj[this.minProp];
-  }
-  set min(v) {
-    this.obj[this.minProp] = v;
-    this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-  }
-  get max() {
-    return this.obj[this.maxProp];
-  }
-  set max(v) {
-    this.obj[this.maxProp] = v;
-    this.min = this.min;  // min setter로 작동
-  }
-}
-
-

이제 GUI를 만들어보죠.

-
function updateCamera() {
-  camera.updateProjectionMatrix();
-}
-
-const gui = new GUI();
-gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-

카메라의 속성을 변경할 때마다 카메라의 updateProjectionMatrix -메서드를 호출해야 하므로, updateCamera라는 함수를 만들어 값이 변경될 때마다 함수를 호출하도록 -합니다.

-

- -

-

값을 조정하며 카메라가 어떤 식으로 작동하는지 확인해보세요. aspect는 창의 비율을 그대로 사용하도록 -설정되어 있으므로, 이를 바꾸고 싶다면 예제를 새 창에서 열어 코드를 직접 수정해야 합니다.

-

아직도 카메라가 어떤 식으로 작동하는지 보기 어려운가요? 까짓것 그럼 카메라를 하나 더 만들어보죠. -하나는 위의 예제와 같은 방식의 카메라이고, 다른 하나는 이 카메라의 시야와 절두체를 렌더링해 -카메라가 어떻게 움직이는지 관찰할 수 있도록 만들겠습니다.

-

Three.js의 가위 함수(scissor function)을 이용하면 쉽습니다. 가위 함수를 사용해 양쪽에 -장면 두 개, 카메라 두 개를 렌더링하겠습니다.

-

먼저 HTML과 CSS로 양쪽에 div 요소를 배치합니다. 이러면 각각의 카메라에 OrbitControls를 -두어 이벤트 처리하기도 훨씬 간단합니다.

-
<body>
-  <canvas id="c"></canvas>
-+  <div class="split">
-+     <div id="view1" tabindex="1"></div>
-+     <div id="view2" tabindex="2"></div>
-+  </div>
-</body>
-
-

CSS로 두 div 요소가 canvas 위 양쪽에 자리하게 합니다.

-
.split {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-}
-.split > div {
-  width: 100%;
-  height: 100%;
-}
-
-

카메라의 절두체를 시각화할 CameraHelper를 추가합니다.

-
const cameraHelper = new THREE.CameraHelper(camera);
-
-...
-
-scene.add(cameraHelper);
-
-

다음으로 두 div 요소를 참조합니다.

-
const view1Elem = document.querySelector('#view1');
-const view2Elem = document.querySelector('#view2');
-
-

그리고 기존 OrbitControls가 왼쪽 div 요소의 이벤트에만 반응하도록 설정합니다.

-
-const controls = new OrbitControls(camera, canvas);
-+const controls = new OrbitControls(camera, view1Elem);
-
-

다음으로 PerspectiveCamera와 두 번째 OrbitControls를 추가합니다. 이 OrbitControls를 -두 번째 카메라에 종속시키고, 오른쪽 div 요소의 이벤트에만 반응하도록 합니다.

-
const camera2 = new THREE.PerspectiveCamera(
-  60,  // 시야각(fov)
-  2,   // 비율(aspect)
-  0.1, // near
-  500, // far
-);
-camera2.position.set(40, 10, 30);
-camera2.lookAt(0, 5, 0);
-
-const controls2 = new OrbitControls(camera2, view2Elem);
-controls2.target.set(0, 5, 0);
-controls2.update();
-
-

끝으로 가위 함수를 사용해 화면을 분할하겠습니다. 카메라 각각의 시점에 따라 -장면을 canvas의 양쪽에 나눠 렌더링하게끔 할 것입니다.

-

아래의 함수는 canvas 위에 덮어 씌운 요소의 사각 좌표(rectangle)를 구합니다. -그리고 해당 사각 좌표로 renderer의 화면(viewport)과 가위(scissor)의 값을 -정의한 뒤, 사각 좌표의 가로세로 비율을 반환합니다.

-
function setScissorForElement(elem) {
-  const canvasRect = canvas.getBoundingClientRect();
-  const elemRect = elem.getBoundingClientRect();
-
-  // canvas에 대응하는 사각형을 구하기
-  const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
-  const left = Math.max(0, elemRect.left - canvasRect.left);
-  const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
-  const top = Math.max(0, elemRect.top - canvasRect.top);
-
-  const width = Math.min(canvasRect.width, right - left);
-  const height = Math.min(canvasRect.height, bottom - top);
-
-  // canvas의 일부분만 렌더링하도록 scissor 적용
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  // 비율 반환
-  return width / height;
-}
-
-

이제 이 함수를 사용해 render 함수에서 장면을 두 번 렌더링할 수 있습니다.

-
  function render() {
-
--    if (resizeRendererToDisplaySize(renderer)) {
--      const canvas = renderer.domElement;
--      camera.aspect = canvas.clientWidth / canvas.clientHeight;
--      camera.updateProjectionMatrix();
--    }
-
-+    resizeRendererToDisplaySize(renderer);
-+
-+    // 가위 활성화
-+    renderer.setScissorTest(true);
-+
-+    // 기존 화면 렌더링
-+    {
-+      const aspect = setScissorForElement(view1Elem);
-+
-+      // 비율에 따라 카메라 조정
-+      camera.aspect = aspect;
-+      camera.updateProjectionMatrix();
-+      cameraHelper.update();
-+
-+      // 기존 화면에서 가이드라인(CameraHelper)이 노출되지 않도록 설정
-+      cameraHelper.visible = false;
-+
-+      scene.background.set(0x000000);
-+
-+      // 렌더링
-+      renderer.render(scene, camera);
-+    }
-+
-+    // 두 번째 카메라 렌더링
-+    {
-+      const aspect = setScissorForElement(view2Elem);
-+
-+      // 비율에 따라 카메라 조정
-+      camera2.aspect = aspect;
-+      camera2.updateProjectionMatrix();
-+
-+      // 가이드라인 활성화
-+      cameraHelper.visible = true;
-+
-+      scene.background.set(0x000040);
-+
-+      renderer.render(scene, camera2);
-+    }
-
--    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-

위 예제에서는 분할된 두 화면을 구별하기 쉽두록 두 번째 화면의 배경을 진한 -파란색으로 칠했습니다.

-

또한 render 함수 안에서 모든 것을 처리하기에, updateCamera 함수도 -제거하였습니다.

-
-function updateCamera() {
--  camera.updateProjectionMatrix();
--}
-
-const gui = new GUI();
--gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-+gui.add(camera, 'fov', 1, 180);
-const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
--gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
--gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
-+gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-
-

이제 두 번째 화면에서 첫 번째 카메라의 절두체를 확인할 수 있습니다.

-

- -

-

왼쪽은 기존의 화면과 같고 오른쪽에 왼쪽 카메라의 절두체가 보입니다. -패널에서 near, far, fov 값을 조정하거나 마우스로 화면을 움직여보면, -오른쪽 화면의 절두체 안에 있는 물체만 왼쪽 화면에 노출됨을 확인할 수 -있을 겁니다.

-

누군가 이렇게 물을지도 모르겠네요. 그냥 near를 0.0000000001로 설정하고 far를 -10000000000000로 설정해버리면요? 이러면 모든 게 항상 다 보이지 않나요? 이유를 -설명하자면, GPU는 어떤 물체가 앞에 있거나 다른 물체의 뒤에 있을 때만 정밀도가 -높기 때문입니다. 정밀도는 일정량이 nearfar 사이에 퍼져 있는데, 기본적으로 -카메라에 가까울 수록 정밀도가 높고 멀수록 정밀도가 낮아집니다.

-

현상을 직접 확인해보죠. 위의 예제를 수정해 20개의 구체를 한 줄로 세우겠습니다.

-
{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const numSpheres = 20;
-  for (let i = 0; i < numSpheres; ++i) {
-    const sphereMat = new THREE.MeshPhongMaterial();
-    sphereMat.color.setHSL(i * .73, 1, 0.5);
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, i * sphereRadius * -2.2);
-    scene.add(mesh);
-  }
-}
-
-

near 속성을 0.00001로 설정합니다.

-
const fov = 45;
-const aspect = 2;  // canvas 기본값
--const near = 0.1;
-+const near = 0.00001;
-const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

그리고 기존의 GUI 코드를 수정해 0.00001의 작은 단위도 설정할 수 있도록 합니다.

-
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-+gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-
-

어떤 결과가 나올 것 같나요?

-

- -

-

이는 z-파이팅(z-fighting, Stitching)의 한 예입니다. 컴퓨터의 GPU가 어떤 픽셀이 -앞이고 어떤 픽셀을 뒤로 보내야할지 결정할 정밀도가 모자를 때 발생하는 현상이죠.

-

위 예제가 어떻게 해도 정상적으로 보인다면, 아래 이미지를 보기 바랍니다.

-
- -

한 가지 해결책은 Three.js에게 픽셀의 앞 뒤를 결정할 때 다른 방법을 쓰도록 설정하는 -것입니다. WebGLRenderer를 생성할 때 logarithmicDepthBuffer 속성을 활성화해주면 -되죠.

-
-const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+const renderer = new THREE.WebGLRenderer({
-+  antialias: true,
-+  canvas,
-+  logarithmicDepthBuffer: true,
-+});
-
-

대게의 경우 정상적으로 보일 겁니다.

-

- -

-

문제가 그대로라면 이 해결책을 쓸 수 없는 건가?라는 의문에 빠질 수 있습니다. -이 해결책이 먹히지 않은 이유는 일부 GPU만 이 기능을 지원하기 때문이죠. 2018년 -9월 기준으로 거의 모든 데스크탑 GPU가 이 기능을 지원하나, 모바일 기기는 대부분 -이 기능을 지원하지 않습니다.

-

이 기능을 쓰지 말아야 하는 또 다른 이유는, 이 기능이 일반적인 해결책보다 훨씬 -성능이 나쁘기 때문입니다.

-

게다가 이 기능을 활성화해도, near를 더 작게, far를 더 멀게 설정하다보면 -결국 같은 현상을 만나게 될 겁니다.

-

이는 항상 nearfar를 설정하는데 많은 공을 들여야 한다는 의미입니다. -near는 대상이 보이는 한 가장 멀게, far도 대상이 보이는 한 카메라와 가장 -가깝게 설정하는 것이 좋죠. 만약 거대한 공간을 렌더링하는 경우, 예를 들어 사람의 -속눈썹과 50km 떨어진 산을 동시에 보이게 하려면 다른 해결책-나중에 다룰지도 모르는-을 -찾아야 합니다. 당장은 nearfar를 적절하게 설정하는 게 중요하다는 것만 -알아둡시다.

-

두 번째로 자주 사용하는 카메라는 OrthographicCamera(정사영 카메라)입니다. -절두체 대신 left, right, top, bottom, near, far로 육면체를 -정의해 사용하죠. 육면체로 화면을 투사하기에 원근 효과가 없습니다.

-

2분할 화면 예제를 수정해 첫 번째 화면을 OrthographicCamera로 바꾸겠습니다.

-

먼저 OrthographicCamera를 만들어보죠.

-
const left = -1;
-const right = 1;
-const top = 1;
-const bottom = -1;
-const near = 5;
-const far = 50;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 0.2;
-
-

먼저 leftbottom을 -1로, righttop을 1로 설정했습니다. 이러면 육면체는 -기본적으로 너비 2칸, 높이 2칸이 되겠죠. 그리고 육면체의 비율을 조정해 lefttop의 -값을 조정할 수 있도록, zoom 속성을 이용해 카메라에 보이는 범위를 조정할 수 있도록 -했습니다.

-

다음으로 zoom 속성을 조정할 GUI를 추가합니다.

-
const gui = new GUI();
-+gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
-
-

listen 메서드를 호출하면 lil-gui가 변화를 감지합니다. 이렇게 한 이유는 OrbitControls이 -마우스 휠 스크롤을 감지해 zoom 속성을 변경하기 때문이죠.

-

끝으로 왼쪽 화면을 렌더링할 때 OrthographicCamera를 업데이트하도록 설정합니다.

-
{
-  const aspect = setScissorForElement(view1Elem);
-
-  // 요소의 비율에 맞춰 카메라 업데이트
--  camera.aspect = aspect;
-+  camera.left   = -aspect;
-+  camera.right  =  aspect;
-  camera.updateProjectionMatrix();
-  cameraHelper.update();
-
-  // 기존 화면에서 가이드라인(CameraHelper)이 노출되지 않도록 설정
-  cameraHelper.visible = false;
-
-  scene.background.set(0x000000);
-  renderer.render(scene, camera);
-}
-
-

이제 OrthographicCamera가 어떻게 작동하는지 확인할 차례입니다.

-

- -

-

Three.js에서 OrthographicCamera는 주로 2D 요소를 표현하기 위해 사용합니다. -카메라에 얼마나 많은 요소를 보여줄지만 결정하면 되죠. 만약 canvas의 1픽셀을 -카메라의 한 칸과 같은 크기로 지정하고 싶다면...

-

중점을 장면의 중심에 두고 1 픽셀을 Three.js의 한 칸으로 만들 수 있습니다.

-
camera.left = -canvas.width / 2;
-camera.right = canvas.width / 2;
-camera.top = canvas.height / 2;
-camera.bottom = -canvas.height / 2;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

2D canvas처럼 중점을 상단 왼쪽에 두려면 다음과 같이 설정할 수 있죠.

-
camera.left = 0;
-camera.right = canvas.width;
-camera.top = 0;
-camera.bottom = canvas.height;
-camera.near = -1;
-camera.far = 1;
-camera.zoom = 1;
-
-

중점이 상단 왼쪽에 있을 경우의 좌표는 2D canvas처럼 0, 0입니다.

-

한 번 만들어보죠! 먼저 카메라를 설정합니다.

-
const left = 0;
-const right = 300;  // canvas 기본 크기
-const top = 0;
-const bottom = 150;  // canvas 기본 크기
-const near = -1;
-const far = 1;
-const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-camera.zoom = 1;
-
-

다음으로 평면(plane) 6개를 만들어 각각 다른 텍스처를 적용하겠습니다. -각 평면마다 THREE.Object3D 인스턴스를 만들어 평면의 부모로 설정합니다. -이러면 중점을 0, 0, 상단 좌측으로 지정해 좌표를 지정하기가 쉽습니다.

-
const loader = new THREE.TextureLoader();
-const textures = [
-  loader.load('resources/images/flower-1.jpg'),
-  loader.load('resources/images/flower-2.jpg'),
-  loader.load('resources/images/flower-3.jpg'),
-  loader.load('resources/images/flower-4.jpg'),
-  loader.load('resources/images/flower-5.jpg'),
-  loader.load('resources/images/flower-6.jpg'),
-];
-const planeSize = 256;
-const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planes = textures.map((texture) => {
-  const planePivot = new THREE.Object3D();
-  scene.add(planePivot);
-  texture.magFilter = THREE.NearestFilter;
-  const planeMat = new THREE.MeshBasicMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  planePivot.add(mesh);
-  // 평면을 움직여 상단 좌측이 중점이 되도록 설정
-  mesh.position.set(planeSize / 2, planeSize / 2, 0);
-  return planePivot;
-});
-
-

그리고 render 함수 안에 canvas의 사이즈가 변경되었을 때 카메라를 업데이트하는 -코드를 추가합니다.

-
function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    camera.right = canvas.width;
-    camera.bottom = canvas.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

planesTHREE.Mesh, 평면의 배열입니다. 시간값을 기반으로 이 평면이 따로 -움직이도록 하겠습니다.

-
function render(time) {
-  time *= 0.001;  // 초 단위로 변경
-
-  ...
-
-  const distAcross = Math.max(20, canvas.width - planeSize);
-  const distDown = Math.max(20, canvas.height - planeSize);
-
-  // total distance to move across and back
-  const xRange = distAcross * 2;
-  const yRange = distDown * 2;
-  const speed = 180;
-
-  planes.forEach((plane, ndx) => {
-    // compute a unique time for each plane
-    const t = time * speed + ndx * 300;
-
-    // get a value between 0 and range
-    const xt = t % xRange;
-    const yt = t % yRange;
-
-    // set our position going forward if 0 to half of range
-    // and backward if half of range to range
-    const x = xt < distAcross ? xt : xRange - xt;
-    const y = yt < distDown   ? yt : yRange - yt;
-
-    plane.position.set(x, y, 0);
-  });
-
-  renderer.render(scene, camera);
-
-

이미지가 완벽하게 가장자리에서 튕기는 것을 확인할 수 있을 겁니다. 2D canvas에서 -픽셀값을 이용해 구현할 때와 같은 방식이죠.

-

- -

-

OrthographicCamera는 게임 엔진 에디터 등에서처럼 3D 모델링 결과물의 상, 하, 좌, 우, -앞, 뒤를 렌더링할 때도 사용합니다.

-
- -

위 스크린샷의 1개의 화면만 원근(perspective) 카메라이고 나머지 3개는 정사영(orthographic) -카메라입니다.

-

여기까지 카메라의 기초에 대해 살펴보았습니다. 카메라를 움직이는 방법에 대해서는 다른 -글에서 좀 더 상세히 설명할 거예요. 다음은 장에서는 그림자(shadows)에 -대해 먼저 살펴보겠습니다.

-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/canvas-textures.html b/manual/ko/canvas-textures.html deleted file mode 100644 index bc8b1eb044a2d3..00000000000000 --- a/manual/ko/canvas-textures.html +++ /dev/null @@ -1,385 +0,0 @@ - - - 캔버스 텍스처 - - - - - - - - - - - - - - -
-
-

캔버스 텍스처

-
-
-
-

※ 이 글은 텍스처에 관한 글에서 이어집니다. 이전 글을 읽지 않았다면 먼저 읽고 오기 바랍니다.

-

이전 글에서 텍스처를 다룰 때는 주로 이미지 파일로 텍스처를 만들었습니다. 하지만 경우에 따라서는 런타임에 텍스처를 만들어야 할 수도 있죠. CanvasTexture를 사용하면 캔버스를 텍스처로 활용할 수 있습니다.

-

캔버스 텍스처는 <canvas> 요소를 인자로 받습니다. 2D 캔버스 API에 대해 잘 모른다면 MDN의 튜토리얼을 참고하세요.

-

간단한 2D 캔버스 앱을 만들어봅시다. 아래는 크기, 색, 위치 모두 무작위인 점을 반복해서 렌더링하는 예제입니다.

-
const ctx = document.createElement('canvas').getContext('2d');
-document.body.appendChild(ctx.canvas);
-ctx.canvas.width = 256;
-ctx.canvas.height = 256;
-ctx.fillStyle = '#FFF';
-ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-
-function randInt(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min | 0;
-}
-
-function drawRandomDot() {
-  ctx.fillStyle = `#${ randInt(0x1000000).toString(16).padStart(6, '0') }`;
-  ctx.beginPath();
-
-  const x = randInt(256);
-  const y = randInt(256);
-  const radius = randInt(10, 64);
-  ctx.arc(x, y, radius, 0, Math.PI * 2);
-  ctx.fill();
-}
-
-function render() {
-  drawRandomDot();
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

- -

-

이제 위 캔버스를 텍스처로 만들어봅시다. 이전 글에서 정육면체에 텍스처를 입혔던 예제를 가져오겠습니다. 이미지를 불러오는 코드를 제거하고 대신 CanvasTexture에 방금 만든 캔버스를 넘겨 인스턴스를 생성합니다.

-
const cubes = [];  // 정육면체를 회전시키기 위한 배열입니다.
--const loader = new THREE.TextureLoader();
--
-+const ctx = document.createElement('canvas').getContext('2d');
-+ctx.canvas.width = 256;
-+ctx.canvas.height = 256;
-+ctx.fillStyle = '#FFF';
-+ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-+const texture = new THREE.CanvasTexture(ctx.canvas);
-
-const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg'),
-+  map: texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-cubes.push(cube);  // 정육면체 배열에 추가해 애니메이션이 적용되도록 합니다.
-
-

그리고 렌더링 루프에서 무작위 점을 찍도록 합니다.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  drawRandomDot();
-+  texture.needsUpdate = true;
-
-  cubes.forEach((cube, ndx) => {
-    const speed = .2 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

추가로 CanvasTexture가 변경되었을 때 Three.js가 텍스처를 업데이트하도록 needsUpdate 속성을 true로 설정합니다.

-

이제 정육면체에 캔버스 텍스처가 적용되었을 겁니다.

-

- -

-

Three.js가 캔버스 텍스처를 렌더링할 때는 이전에 별도의 글에서 설명했던 RenderTarget을 쓰는 게 더 좋습니다.

-

캔버스 텍스처는 주로 장면에 텍스트를 삽입할 때 사용합니다. 예를 들어 캐릭터의 명찰에 이름을 표기하는 경우 캔버스 텍스처를 명찰의 텍스처로 사용할 수 있겠죠.

-

한 번 3명의 사람이 있는 장면을 만들어 각 사람에게 명찰을 달아봅시다.

-

위 예제를 그대로 가져와 정육면체 관련 코드를 지웁니다. 배경은 하얀색으로 바꾸고 두 개의 조명을 넣습니다.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-+
-+function addLight(position) {
-+  const color = 0xFFFFFF;
-+  const intensity = 1;
-+  const light = new THREE.DirectionalLight(color, intensity);
-+  light.position.set(...position);
-+  scene.add(light);
-+  scene.add(light.target);
-+}
-+addLight([-3, 1, 1]);
-+addLight([ 2, 1, .5]);
-
-

2D 캔버스를 이용해 명찰을 만드는 함수를 작성합니다.

-
+function makeLabelCanvas(size, name) {
-+  const borderSize = 2;
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  const font =  `${ size }px bold sans-serif`;
-+  ctx.font = font;
-+  // 이름의 길이를 예측합니다.
-+  const doubleBorderSize = borderSize * 2;
-+  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const height = size + doubleBorderSize;
-+  ctx.canvas.width = width;
-+  ctx.canvas.height = height;
-+
-+  // 캔버스 크기를 바꿨을 때 폰트를 다시 설정해줘야 합니다.
-+  ctx.font = font;
-+  ctx.textBaseline = 'top';
-+
-+  ctx.fillStyle = 'blue';
-+  ctx.fillRect(0, 0, width, height);
-+  ctx.fillStyle = 'white';
-+  ctx.fillText(name, borderSize, borderSize);
-+
-+  return ctx.canvas;
-+}
-
-

다음으로 원통이 몸, 구체가 머리, 평면이 명찰인 간단한 사람을 만들어야 합니다.

-

먼저 공통으로 사용할 geometry를 만듭니다.

-
+const bodyRadiusTop = .4;
-+const bodyRadiusBottom = .2;
-+const bodyHeight = 2;
-+const bodyRadialSegments = 6;
-+const bodyGeometry = new THREE.CylinderGeometry(
-+    bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-+
-+const headRadius = bodyRadiusTop * 0.8;
-+const headLonSegments = 12;
-+const headLatSegments = 5;
-+const headGeometry = new THREE.SphereGeometry(
-+    headRadius, headLonSegments, headLatSegments);
-+
-+const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-

다음으로 이 geometry들을 이용해 사람을 만드는 함수를 만듭니다.

-
+function makePerson(x, size, name, color) {
-+  const canvas = makeLabelCanvas(size, name);
-+  const texture = new THREE.CanvasTexture(canvas);
-+  // 텍스처용 캔버스는 2D이므로 픽셀이 모자랑 경우 대략적으로
-+  // 필터링하게끔 설정합니다.
-+  texture.minFilter = THREE.LinearFilter;
-+  texture.wrapS = THREE.ClampToEdgeWrapping;
-+  texture.wrapT = THREE.ClampToEdgeWrapping;
-+
-+  const labelMaterial = new THREE.MeshBasicMaterial({
-+    map: texture,
-+    side: THREE.DoubleSide,
-+    transparent: true,
-+  });
-+  const bodyMaterial = new THREE.MeshPhongMaterial({
-+    color,
-+    flatShading: true,
-+  });
-+
-+  const root = new THREE.Object3D();
-+  root.position.x = x;
-+
-+  const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-+  root.add(body);
-+  body.position.y = bodyHeight / 2;
-+
-+  const head = new THREE.Mesh(headGeometry, bodyMaterial);
-+  root.add(head);
-+  head.position.y = bodyHeight + headRadius * 1.1;
-+
-+  const label = new THREE.Mesh(labelGeometry, labelMaterial);
-+  root.add(label);
-+  label.position.y = bodyHeight * 4 / 5;
-+  label.position.z = bodyRadiusTop * 1.01;
-+
-+  // 명찰의 크기를 조정합니다.
-+  const labelBaseScale = 0.01;
-+  label.scale.x = canvas.width  * labelBaseScale;
-+  label.scale.y = canvas.height * labelBaseScale;
-+
-+  scene.add(root);
-+  return root;
-+}
-
-

위 코드에서는 몸, 머리, 명찰을 하나의 Object3D에 넣고 위치를 조정했습니다. 이러면 Object3D만 움직여 해당 사람을 움직일 수 있겠죠. 몸은 2칸으로, 캔버스 사이즈가 픽셀 단위이고 거의 수십 픽셀이기에 여기에 0.01을 곱해 사이즈를 적당한 크기로 조정했습니다.

-

이제 사람과 명찰을 만듭니다.

-
+makePerson(-3, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 32, 'Green Machine', 'green');
-+makePerson(+3, 32, 'Red Menace', 'red');
-
-

마지막으로 OrbitControls를 넣어 카메라를 움직일 수 있도록 합니다.

-
import * as THREE from 'three';
-+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-
const fov = 75;
-const aspect = 2;  // 캔버스 기본값
-const near = 0.1;
--const far = 5;
-+const far = 50;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.set(0, 2, 5);
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 2, 0);
-+controls.update();
-
-

사람 위에 간단한 명찰이 붙었습니다.

-

- -

-

나쁘지 않은 예제이지만 몇 가지 짚고 넘어가야 할 것들이 있습니다.

-
    -
  • 명찰을 확대했을 때 해상도가 낮아 보인다.
  • -
-

이 문제를 해결하는 건 생각보다 까다롭습니다. 고급 폰트 렌더링 기법이 있긴 하나 제가 아는 한 플러그인으로 구현되어 있진 않습니다. 거기다 폰트 데이터를 다운 받아야 하니 상대적으로 느리겠죠.

-

다른 방법은 명찰의 해상도를 높이는 겁니다. 텍스처용 캔버스의 사이즈를 두 배로 설정하고 labelBaseScale을 반으로 낮추면 지금과 같은 크기에 해상도만 높일 수 있겠죠.

-
    -
  • 이름의 길이가 길수록 명찰도 길어진다.
  • -
-

이 문제를 해결하려면 명찰 크기를 고정하고 텍스트를 우겨넣으면 됩니다.

-

이건 상대적으로 구현하기 쉽습니다. 명찰의 넓이를 넘겨주고 텍스트의 스케일을 해당 넓이에 맞춰 조정하면 되죠.

-
-function makeLabelCanvas(size, name) {
-+function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
-  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${ size }px bold sans-serif`;
-  ctx.font = font;
-  // 이름의 길이를 예측합니다.
-+  const textWidth = ctx.measureText(name).width;
-
-  const doubleBorderSize = borderSize * 2;
--  const width = ctx.measureText(name).width + doubleBorderSize;
-+  const width = baseWidth + doubleBorderSize;
-  const height = size + doubleBorderSize;
-  ctx.canvas.width = width;
-  ctx.canvas.height = height;
-
-  // 캔버스 크기를 바꿨을 때 폰트를 다시 설정해줘야 합니다.
-  ctx.font = font;
--  ctx.textBaseline = 'top';
-+  ctx.textBaseline = 'middle';
-+  ctx.textAlign = 'center';
-
-  ctx.fillStyle = 'blue';
-  ctx.fillRect(0, 0, width, height);
-
-+  // 명찰의 크기에 맞춰 조정하되 늘어나지 않도록 합니다.
-+  const scaleFactor = Math.min(1, baseWidth / textWidth);
-+  ctx.translate(width / 2, height / 2);
-+  ctx.scale(scaleFactor, 1);
-  ctx.fillStyle = 'white';
-  ctx.fillText(name, borderSize, borderSize);
-
-  return ctx.canvas;
-}
-
-

사람을 만들 때 명찰의 넓이도 같이 받도록 바꿉니다.

-
-function makePerson(x, size, name, color) {
--  const canvas = makeLabelCanvas(size, name);
-+function makePerson(x, labelWidth, size, name, color) {
-+  const canvas = makeLabelCanvas(labelWidth, size, name);
-
-...
-
-}
-
--makePerson(-3, 32, 'Purple People Eater', 'purple');
--makePerson(-0, 32, 'Green Machine', 'green');
--makePerson(+3, 32, 'Red Menace', 'red');
-+makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-+makePerson(-0, 150, 32, 'Green Machine', 'green');
-+makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-

이제 명찰의 텍스트가 크기에 맞춰지고 가운데 정렬됩니다.

-

- -

-

위 예제에서는 텍스처마다 캔버스를 따로 썼습니다. 텍스처마다 캔버스를 따로 쓸지는 여러분의 선택에 달렸습니다. 만약 캔버스를 자주 업데이트해야 한다면 텍스처마다 캔버스를 따로 두는 게 좋겠죠. 반대로 아예, 또는 가끔 업데이트할 거라면 하나의 캔버스를 돌려 쓰는 게 더 나을 겁니다. 명찰은 업데이트할 일이 없으니 위 코드를 고쳐 하나의 캔버스를 쓰도록 해보죠.

-
+const ctx = document.createElement('canvas').getContext('2d');
-
-function makeLabelCanvas(baseWidth, size, name) {
-  const borderSize = 2;
--  const ctx = document.createElement('canvas').getContext('2d');
-  const font =  `${ size }px bold sans-serif`;
-
-  ...
-
-}
-
-+const forceTextureInitialization = function() {
-+  const material = new THREE.MeshBasicMaterial();
-+  const geometry = new THREE.PlaneGeometry();
-+  const scene = new THREE.Scene();
-+  scene.add(new THREE.Mesh(geometry, material));
-+  const camera = new THREE.Camera();
-+
-+  return function forceTextureInitialization(texture) {
-+    material.map = texture;
-+    renderer.render(scene, camera);
-+  };
-+}();
-
-function makePerson(x, labelWidth, size, name, color) {
-  const canvas = makeLabelCanvas(labelWidth, size, name);
-  const texture = new THREE.CanvasTexture(canvas);
-  // 텍스처용 캔버스는 2D이므로 픽셀이 모자랑 경우 대략적으로
-  // 필터링하게끔 설정합니다.
-  texture.minFilter = THREE.LinearFilter;
-  texture.wrapS = THREE.ClampToEdgeWrapping;
-  texture.wrapT = THREE.ClampToEdgeWrapping;
-+  forceTextureInitialization(texture);
-
-  ...
-
-

- -

-

아직 언급하지 않은 다른 문제점이 있습니다. 카메라를 사람 뒤로 돌리면 명찰이 뒤집혀 보인다는 거죠. 만약 명찰을 배지 형태로 사용할 거라면 크게 문제될 일은 없습니다. 하지만 명찰을 3D 게임 캐릭터의 이름표로 사용할 거라면 이름표가 항상 카메라를 향해야 하겠죠. 이 방법에 대해서는 빌보드와 파사드에서 다루겠습니다.

-

단순히 이름표를 구현하는 경우라면 HTML을 이용한 방법을 사용할 수도 있습니다. 다만 HTML 이름표는 항상 3D 요소 위에 있죠. 예제의 명찰은 3차원 세계 안에 있기에 다른 물체에 의해 가려지길 원할 경우 유용합니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/cleanup.html b/manual/ko/cleanup.html deleted file mode 100644 index 50bc61c717dd4b..00000000000000 --- a/manual/ko/cleanup.html +++ /dev/null @@ -1,391 +0,0 @@ - - - 메모리 해제하기 - - - - - - - - - - - - - - -
-
-

메모리 해제하기

-
-
-
-

Three.js 앱은 생각보다 많은 메모리를 사용합니다. 3D 모델의 정점 데이터는 보통 1MB에서 20MB 정도의 메모리를 차지하죠. 텍스처로 JPG 파일을 사용하는 모델은 텍스처를 사용하기 위해 JPG 파일의 압축을 완전히 풀어야 하는데, 이 텍스처는 1024x1024당 약 4에서 6MB 정도의 메모리를 사용합니다.

-

대다수의 Three.js 앱은 자원을 한 번 불러오면 페이지가 닫히기 전까지 해당 자원을 버릴 일이 없습니다. 하지만 시간이 지남에 따라 데이터를 바꿔야 한다면 어떨까요?

-

Three.js는 자바스크립트와 달리 할당한 메모리를 알아서 비우지 못합니다. 페이지를 전환하는 경우야 브라우저가 알아서 해당 자원을 메모리에서 지우겠지만, 그 밖의 경우 메모리 해제는 전적으로 개발자에게 달렸습니다.

-

Three.js에서는 textures, geometries, materialsdispose 메서드를 호출해 메모리를 해제할 수 있습니다.

-

가장 간단한 방법은 일일이 호출하는 겁니다. 초기화 시에 아래와 같이 지원을 메모리에 할당하고

-
const boxGeometry = new THREE.BoxGeometry(...);
-const boxTexture = textureLoader.load(...);
-const boxMaterial = new THREE.MeshPhongMaterial({ map: texture });
-
-

아래와 같이 직접 메서드를 호출해 메모리를 해제할 수 있죠.

-
boxGeometry.dispose();
-boxTexture.dispose();
-boxMaterial.dispose();
-
-

하지만 자원이 많아질수록 코드는 지저분해질 겁니다.

-

자원을 추적하는 클래스를 하나 만드는 게 좋겠네요. 클래스에 자원을 지정하고 한 번에 버리도록 해보겠습니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (resource.dispose) {
-      this.resources.add(resource);
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
-      resource.dispose();
-    }
-    this.resources.clear();
-  }
-}
-
-

텍스처에 관한 글의 첫 번째 예제에 이 클래스를 써 봅시다. 먼저 클래스의 인스턴스를 만듭니다.

-
const resTracker = new ResourceTracker();
-
-

좀 더 간단한 형태로 쓰기 위해 track 메서드를 함수로 만듭니다.

-
const resTracker = new ResourceTracker();
-+const track = resTracker.track.bind(resTracker);
-
-

그리고 각 geometry, 텍스처, 재질(material)에 track 함수를 호출합니다.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
--const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-+const geometry = track(new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth));
-
-const cubes = [];  // 정육면체를 회전시키기 위한 배열
-const loader = new THREE.TextureLoader();
-
--const material = new THREE.MeshBasicMaterial({
--  map: loader.load('resources/images/wall.jpg'),
--});
-+const material = track(new THREE.MeshBasicMaterial({
-+  map: track(loader.load('resources/images/wall.jpg')),
-+}));
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-cubes.push(cube);  // 회전 애니메이션을 위해 배열에 추가
-
-

자원을 해제할 때 정육면체를 장면에서 제거하고 resTracker.dispose 메서드를 호출하도록 합니다.

-
for (const cube of cubes) {
-  scene.remove(cube);
-}
-cubes.length = 0;  // 정육면체 배열을 비웁니다
-resTracker.dispose();
-
-

하지만 실제로 테스트해보니 귀찮은 작업을 추가해야 합니다. ResourceTracker에 코드를 추가하겠습니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
--    if (resource.dispose) {
-+    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
--      resource.dispose();
-+      if (resource instanceof THREE.Object3D) {
-+        if (resource.parent) {
-+          resource.parent.remove(resource);
-+        }
-+      }
-+      if (resource.dispose) {
-+        resource.dispose();
-+      }
-+    }
-    this.resources.clear();
-  }
-}
-
-

이제 정육면체를 추적할 수 있습니다.

-
const material = track(new THREE.MeshBasicMaterial({
-  map: track(loader.load('resources/images/wall.jpg')),
-}));
-const cube = track(new THREE.Mesh(geometry, material));
-scene.add(cube);
-cubes.push(cube);  // 회전 애니메이션을 위해 배열에 추가
-
-

별도로 정육면체를 제거해야할 필요가 없으니 코드를 삭제합니다.

-
-for (const cube of cubes) {
--  scene.remove(cube);
--}
-cubes.length = 0;  // 정육면체 배열을 비웁니다
-resTracker.dispose();
-
-

코드를 정리해 정육면체, 텍스처, 재질을 다시 추가할 수 있도록 만들고

-
const scene = new THREE.Scene();
-*const cubes = [];  // 정육면체를 회전시키기 위한 배열
-
-+function addStuffToScene() {
-  const resTracker = new ResourceTracker();
-  const track = resTracker.track.bind(resTracker);
-
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = track(new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth));
-
-  const loader = new THREE.TextureLoader();
-
-  const material = track(new THREE.MeshBasicMaterial({
-    map: track(loader.load('resources/images/wall.jpg')),
-  }));
-  const cube = track(new THREE.Mesh(geometry, material));
-  scene.add(cube);
-  cubes.push(cube);  // 회전 애니메이션을 위해 배열에 추가
-+  return resTracker;
-+}
-
-

시간에 지남에 따라 물체들을 사라지고 나타나게 합니다.

-
function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-}
-
-async function process() {
-  for (;;) {
-    const resTracker = addStuffToScene();
-    await wait(2);
-    cubes.length = 0;  // 정육면체 배열을 비웁니다
-    resTracker.dispose();
-    await wait(1);
-  }
-}
-process();
-
-

아래 예제는 정육면체, 텍스처, 재질을 렌더링한 뒤 2초 후에 해당 자원을 버리고, 다시 1초 후에 생성하기를 반복합니다.

-

- -

-

딱히 오류는 없네요.

-

불러온 파일을 해제하려면 코드를 좀 더 추가해야 합니다. Three.js의 로더는 대부분 최상위 Object3D만을 반환하기에 어떤 자원을 사용했는지 체크하려면 일일이 하위 요소를 뒤져봐야 합니다.

-

ResourceTracker를 업데이트해 저 역할을 맡겨보죠.

-

먼저 자원이 Object3D인지 확인해 해당 요소의 geometry, 재질, 하위 요소를 추적하도록 합니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-+    if (resource instanceof THREE.Object3D) {
-+      this.track(resource.geometry);
-+      this.track(resource.material);
-+      this.track(resource.children);
-+    }
-    return resource;
-  }
-  ...
-}
-
-

그리고 resource.geometry, resource.material, resource.children이 null이나 undefined일 수 있으므로 track 메서드 상단에서 체크해줍니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-+    if (!resource) {
-+      return resource;
-+    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
-    }
-    return resource;
-  }
-  ...
-}
-
-

resource.children이나 resource.material은 배열 형식일 수 있습니다. 배열일 경우 배열의 요소를 추적하도록 합니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (!resource) {
-      return resource;
-    }
-
-+    // 하위 요소 또는 재질이 배열일 경우
-+    if (Array.isArray(resource)) {
-+      resource.forEach(resource => this.track(resource));
-+      return resource;
-+    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
-    }
-    return resource;
-  }
-  ...
-}
-
-

그리고 재질의 속성 중 텍스처와 균등 변수(uniform)를 처리해줍니다.

-
class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (!resource) {
-      return resource;
-    }
-
-*    // 하위 요소 또는 재질이 배열일 경우,
-*    // 균등 변수가 텍스처 배열일 경우
-    if (Array.isArray(resource)) {
-      resource.forEach(resource => this.track(resource));
-      return resource;
-    }
-
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
--    }
-+    } else if (resource instanceof THREE.Material) {
-+      // 재질에 텍스처가 있는지 검사해 추적합니다.
-+      for (const value of Object.values(resource)) {
-+        if (value instanceof THREE.Texture) {
-+          this.track(value);
-+        }
-+      }
-+      // 균등 변수가 텍스처 또는 텍스처의 배열인지 체크합니다.
-+      if (resource.uniforms) {
-+        for (const value of Object.values(resource.uniforms)) {
-+          if (value) {
-+            const uniformValue = value.value;
-+            if (uniformValue instanceof THREE.Texture ||
-+                Array.isArray(uniformValue)) {
-+              this.track(uniformValue);
-+            }
-+          }
-+        }
-+      }
-+    }
-    return resource;
-  }
-  ...
-}
-
-

수정한 클래스를 glTF 파일 불러오기에서 썼던 예제에 적용해 무료 glTF 파일을 불러와보도록 합시다.

-
const gltfLoader = new GLTFLoader();
-function loadGLTF(url) {
-  return new Promise((resolve, reject) => {
-    gltfLoader.load(url, resolve, undefined, reject);
-  });
-}
-
-function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-}
-
-const fileURLs = [
-  'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf',
-  'resources/models/3dbustchallange_submission/scene.gltf',
-  'resources/models/mountain_landscape/scene.gltf',
-  'resources/models/simple_house_scene/scene.gltf',
-];
-
-async function loadFiles() {
-  for (;;) {
-    for (const url of fileURLs) {
-      const resMgr = new ResourceTracker();
-      const track = resMgr.track.bind(resMgr);
-      const gltf = await loadGLTF(url);
-      const root = track(gltf.scene);
-      scene.add(root);
-
-      // 해당 요소의 모든 하위 물체를 포함하는 육면체를 계산합니다.
-      const box = new THREE.Box3().setFromObject(root);
-
-      const boxSize = box.getSize(new THREE.Vector3()).length();
-      const boxCenter = box.getCenter(new THREE.Vector3());
-
-      // 카메라가 화면을 전부 담도록 설정합니다.
-      frameArea(boxSize * 1.1, boxSize, boxCenter, camera);
-
-      await waitSeconds(2);
-      renderer.render(scene, camera);
-
-      resMgr.dispose();
-
-      await waitSeconds(1);
-
-    }
-  }
-}
-loadFiles();
-
-

- -

-

코드에 대해 몇 가지 설명하고 끝내겠습니다.

-

만약 2개 이상의 파일을 한 번에 불러오고 나중에 따로 해제하려면 ResourceTracker를 파일별로 생성하면 됩니다.

-

위 예제에서는 gltf.scene에만 track 메서드를 사용했습니다. 이것만으로 지금 ResourceTracker는 포함된 모든 요소를 추적하겠죠. 화면에 뭔가를 더 추가하려면 해당 자원을 추적할지 말지를 먼저 결정해야 합니다.

-

특정 도구를 캐릭터의 자식 요소로 추가해 손에 쥐어 주는 경우를 예로 들 수 있습니다. 그냥 도구만 추가해서는 해당 요소를 추적할 수 없을 테니까요. 모르긴 해도 꽤나 흔한 경우일 거라 생각합니다.

-

처음에 ResourceTracker를 작성했을 때는 모든 것을 track이 아니라 dispose 메서드 안에서 해결하려고 했습니다. 하지만 캐릭터의 손에 도구를 쥐어 주는 경우를 생각해보니 track을 통해 등록한 자원을 해제하는 게 확장성 면에서도 그렇고 더 나은 방법 같더군요. 씬 그래프 전체를 해제시키는 것보다는 불러온 파일만 해제시키는 게 나을 테니까요.

-

ResourceTracker를 만들긴 했지만 100% 만족스럽진 않습니다. 3D 엔진에서 자원을 이런 식으로 관리하는 건 흔한 일이 아니거든요. 어떤 자원이 올라올지 추측하는 게 아니라 미리 알고 있어야 하는 쪽이 맞습니다. Three.js의 파일 로더가 불러온 자원의 주소값을 전부 반환하도록 바뀐다면 좋겠지만, 지금은 장면(scene)을 불러올 때 다른 선택지가 없기에 이 해결책이 최선이겠죠.

-

이 예시가 Three.js에서 자원을 해제하는 데 조금이나마 도움이 되었으면 합니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/custom-buffergeometry.html b/manual/ko/custom-buffergeometry.html deleted file mode 100644 index 843a18640b1092..00000000000000 --- a/manual/ko/custom-buffergeometry.html +++ /dev/null @@ -1,431 +0,0 @@ - - - 사용자 지정 BufferGeometry - - - - - - - - - - - - - - -
-
-

사용자 지정 BufferGeometry

-
-
-
-

BufferGeometry는 Three.js 내의 모든 geometry를 나타냅니다(r125에서부터 Geometry가 제거되었습니다). 좀 더 자세히 말하면 특정 BufferAttribute라고 부르는 속성의 집합이죠.

-

BufferAttribute는 -위치(positions), 법선(normals), 색(colors), uv 데이터의 배열이고, 이들을 모으면 각 꼭지점에 -대한 평행 배열 형식의 데이터가 됩니다.

-
- -

그림을 보면 총 4개의 속성(attribute), position, normal, color, uv가 있습니다. -이들은 평행 배열로 각 속성의 N 번째 데이터 묶음이 한 꼭지점의 데이터를 나타냅니다. 표시한 -index = 4 위치의 꼭지점 데이터를 보세요. 이 묶음이 하나의 꼭지점을 정의합니다.

-

이해를 돕기 위해 정육면체의 한 모서리를 강조해보겠습니다.

-
- -

이 경우 맞닿은 면의 색이 다르기에, 이 모서리는 각 면에 다른 법선을 제공해야 합니다. -마찬가지로 UV도 달라야 하죠. -하나의 꼭지점은 위 4개 속성의 묶음이고, 때문에 속성이 달라진다면 그건 다른 꼭지점이 -되는 것이죠.

-

이전과 마찬가지로 BufferGeometry로 정육면체를 만들어보겠습니다. 굳이 정육면체를 쓰는 -이유는 모서리의 꼭지점을 공유하는 듯해도 사실 그렇지 않기 때문이죠. 필요한 꼭지점을 -전부 생성한 후, 꼭지점 데이터를 평행 배열로 변환해 BufferAttribute를 만들고, 이를 -BufferGeometry에 추가해야 합니다.

-

먼저 정육면체를 만드는 데 필요한 데이터를 정렬합니다. -아까 말했듯 꼭지점의 속성 중 하나라도 다르다면 별도의 꼭지점으로 분리해야 합니다. 정육면체의 -경우는 총 꼭지점 36개가 필요하죠. 면 6개, 면 하나당 삼각형 2개, 삼각형 하나 당 꼭지점 3개, -총 36개입니다.

-
const vertices = [
-  // 앞쪽
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], },
-  // 오른쪽
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], },
-  // 뒤쪽
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], },
-  // 왼쪽
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], },
-  // 상단
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], },
-  // 하단
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], },
-];
-
-

다음으로 이 배열을 3개의 평행 배열로 변환합니다.

-
const positions = [];
-const normals = [];
-const uvs = [];
-for (const vertex of vertices) {
-  positions.push(...vertex.pos);
-  normals.push(...vertex.norm);
-  uvs.push(...vertex.uv);
-}
-
-

이제 BufferGeometry를 만듭니다. 그리고 각 배열로 BufferAttribute 인스턴스를 생성한 -뒤 BufferGeometry에 추가합니다.

-
  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-
-

이때 정확히 Three.js가 원하는 속성 이름을 써야 합니다(사용자 지정 쉐이더를 만들 때와는 -달리). 이 경우에는 position, normal, uv이죠. 꼭지점 색을 지정하려면 color 속성을 -지정해야 합니다.

-

아까 positions, normals, uvs, 3개의 자바스크립트 순수 배열을 생성했습니다. -그리고 위에서 해당 배열을 형식화 배열, -Float32Array로 변환했죠. BufferAttribute는 순수 배열이 아니라 형식화 배열을 -인자로 받습니다. 또한 하나의 꼭지점에 몇 개의 요소를 사용할 지 지정해줘야 하죠. -위치(position)과 법선(normal)의 경우 x, y, z 총 3개이고, UV는 u, v 총 2개입니다.

-

- -

-

데이터가 너무 많네요. 크게 구조를 바꾸긴 어렵지만, 꼭지점을 인덱스로 참조하게끔 바꾸면 -조금 나을 듯합니다. 정육면체 데이터를 다시 봅시다. 각 면은 2개의 삼각형, 삼각형 하나에는 -꼭지점이 3개 있으므로 면 하나에는 총 6개의 꼭지점이 있습니다. 하지만 이 중 꼭지점 2개는 -완전히 같죠(같은 위치, 같은 법선, 같은 uv). 중복된 꼭지점을 제거하고 인덱스로 데이터를 -불러오도록 바꿀 수 있겠네요. 먼저 중복된 꼭지점을 제거하겠습니다.

-
const vertices = [
-  // 앞쪽
-  { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
-  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
-  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], }, // 2
--
--  { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
--  { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], }, // 3
-  // 오른쪽
-  { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], }, // 4
-  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], }, // 5
--
--  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
--  { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], }, // 6
-  { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], }, // 7
-  // 뒤쪽
-  { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], }, // 8
-  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], }, // 9
--
--  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
--  { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-  { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], }, // 10
-  { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], }, // 11
-  // 왼쪽
-  { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], }, // 12
-  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], }, // 13
--
--  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-  { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], }, // 14
-  { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], }, // 15
-  // 상단
-  { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], }, // 16
-  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], }, // 17
--
--  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
--  { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-  { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], }, // 18
-  { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], }, // 19
-  // 하단
-  { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], }, // 20
-  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], }, // 21
--
--  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
--  { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-  { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
-  { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
-];
-
-

이제 꼭지점 24개만 남았습니다. 중복되는 꼭지점은 없죠. 이제 BufferGeometry.setIndex -메서드에 각 꼭지점 데이터의 인덱스값 36개-삼각형이 12개이므로-를 넘겨줍니다.

-
geometry.setAttribute(
-    'position',
-    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
-    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-+geometry.setIndex([
-+   0,  1,  2,   2,  1,  3,  // 앞쪽
-+   4,  5,  6,   6,  5,  7,  // 오른쪽
-+   8,  9, 10,  10,  9, 11,  // 뒤쪽
-+  12, 13, 14,  14, 13, 15,  // 왼쪽
-+  16, 17, 18,  18, 17, 19,  // 상단
-+  20, 21, 22,  22, 21, 23,  // 하단
-+]);
-
-

- -

-

BufferGeometry에 법선을 지정하지 않았다면 computeVertexNormals -메서드를 호출해 자동으로 법선을 지정할 수 있습니다. 다만 데이터가 조금이라도 다르다면 -꼭지점을 공유할 수 없기에 구체나 원통 같은 물체를 만들려 하는 경우에는 이음새가 보일 수 있어요.

-
-
-
-
BufferGeometry
-
-
-
-
Geometry
-
-
- -

위 두 원통은 computeVertexNormals 메서드를 호출해 법선을 생성했습니다. 자세히 보면 -왼쪽 원통에 이음매가 있는 게 보일 텐데, 이는 원통의 끝과 시작점의 UV가 달라 꼭지점을 -공유할 수 없기 때문입니다. 그다지 큰 문제는 아니지만, 알아두어 나쁠 건 없죠. 이를 해결하려면 -법선을 직접 지정해야 합니다.

-

아까는 처음에 순수 배열을 썼지만, 처음부터 형식화 배열을 -사용할 수도 있습니다. 다만 형식화 배열은 초기화할 때 미리 크기를 지정해줘야 합니다. -그렇게 어려운 일은 아니지만, 순수 배열은 push 메서드로 요소를 추가하고 바뀐 -길이를 length 속성으로 확인할 수 있습니다. 하지만 형식화 배열을 사용하면 어디서 -요소를 추가했는지 직접 일일이 기록해야 하죠.

-

예제의 경우는 사전에 정해진 데이터를 사용하기에 배열 길이를 미리 구하는 게 어렵지 -않습니다.

-
-const positions = [];
--const normals = [];
--const uvs = [];
-+const numVertices = vertices.length;
-+const positionNumComponents = 3;
-+const normalNumComponents = 3;
-+const uvNumComponents = 2;
-+const positions = new Float32Array(numVertices * positionNumComponents);
-+const normals = new Float32Array(numVertices * normalNumComponents);
-+const uvs = new Float32Array(numVertices * uvNumComponents);
-+let posNdx = 0;
-+let nrmNdx = 0;
-+let uvNdx = 0;
-for (const vertex of vertices) {
--  positions.push(...vertex.pos);
--  normals.push(...vertex.norm);
--  uvs.push(...vertex.uv);
-+  positions.set(vertex.pos, posNdx);
-+  normals.set(vertex.norm, nrmNdx);
-+  uvs.set(vertex.uv, uvNdx);
-+  posNdx += positionNumComponents;
-+  nrmNdx += normalNumComponents;
-+  uvNdx += uvNumComponents;
-}
-
-geometry.setAttribute(
-    'position',
--    new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-+    new THREE.BufferAttribute(positions, positionNumComponents));
-geometry.setAttribute(
-    'normal',
--    new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-+    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setAttribute(
-    'uv',
--    new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-+    new THREE.BufferAttribute(uvs, uvNumComponents));
-
-geometry.setIndex([
-   0,  1,  2,   2,  1,  3,  // 앞쪽
-   4,  5,  6,   6,  5,  7,  // 오른쪽
-   8,  9, 10,  10,  9, 11,  // 뒤쪽
-  12, 13, 14,  14, 13, 15,  // 왼쪽
-  16, 17, 18,  18, 17, 19,  // 상단
-  20, 21, 22,  22, 21, 23,  // 하단
-]);
-
-

- -

-

꼭지점의 일부를 수정하고 싶다면 형식화 배열을 사용하는 게 좋습니다.

-

뭔가 꼭지점을 동적으로 수정하는 예제를 찾아보려고 노력했는데, 찾기가 어렵네요. -그냥 구체를 만들고 구체의 각 사분면(quad)을 중심으로부터 안팎으로 움직여보겠습니다.

-

아래는 구체의 위치값과 인덱스를 생성하는 코드입니다. 사분면 내의 꼭지점은 서로 -공유할 수 있지만, 사분면은 각각 움직여야 하므로 사분면끼리는 공유하지 않도록 -합니다.

-

구체의 정점을 구하기 위해 좀 더 복잡한 방법을 쓸 수도 있지만, 귀찮으니 그냥 -Object3D 3개를 계층 구조로 배열해 쓰겠습니다. 이 방식에 대해서는 많은 물체를 -최적화하는 방법에서 더 자세히 다루겠습니다.

-
function makeSpherePositions(segmentsAround, segmentsDown) {
-  const numVertices = segmentsAround * segmentsDown * 6;
-  const numComponents = 3;
-  const positions = new Float32Array(numVertices * numComponents);
-  const indices = [];
-
-  const longHelper = new THREE.Object3D();
-  const latHelper = new THREE.Object3D();
-  const pointHelper = new THREE.Object3D();
-  longHelper.add(latHelper);
-  latHelper.add(pointHelper);
-  pointHelper.position.z = 1;
-  const temp = new THREE.Vector3();
-
-  function getPoint(lat, long) {
-    latHelper.rotation.x = lat;
-    longHelper.rotation.y = long;
-    longHelper.updateMatrixWorld(true);
-    return pointHelper.getWorldPosition(temp).toArray();
-  }
-
-  let posNdx = 0;
-  let ndx = 0;
-  for (let down = 0; down < segmentsDown; ++down) {
-    const v0 = down / segmentsDown;
-    const v1 = (down + 1) / segmentsDown;
-    const lat0 = (v0 - 0.5) * Math.PI;
-    const lat1 = (v1 - 0.5) * Math.PI;
-
-    for (let across = 0; across < segmentsAround; ++across) {
-      const u0 = across / segmentsAround;
-      const u1 = (across + 1) / segmentsAround;
-      const long0 = u0 * Math.PI * 2;
-      const long1 = u1 * Math.PI * 2;
-
-      positions.set(getPoint(lat0, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long0), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat0, long1), posNdx);  posNdx += numComponents;
-      positions.set(getPoint(lat1, long1), posNdx);  posNdx += numComponents;
-
-      indices.push(
-        ndx, ndx + 1, ndx + 2,
-        ndx + 2, ndx + 1, ndx + 3,
-      );
-      ndx += 4;
-    }
-  }
-  return { positions, indices };
-}
-
-

만든 함수를 다음처럼 호출합니다.

-
const segmentsAround = 24;
-const segmentsDown = 16;
-const { positions, indices } = makeSpherePositions(segmentsAround, segmentsDown);
-
-

여기서 반환된 위치값(positions)은 구체의 위치값을 기반으로 합니다. 이는 법선의 값(normals)과 -같으니 법선을 따로 구할 필요 없이 위치값을 복사해서 쓰면 됩니다.

-
const normals = positions.slice();
-
-

다음으로 각 속성을 지정합니다.

-
const geometry = new THREE.BufferGeometry();
-const positionNumComponents = 3;
-const normalNumComponents = 3;
-
-+const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents);
-+positionAttribute.setUsage(THREE.DynamicDrawUsage);
-geometry.setAttribute(
-    'position',
-+    positionAttribute);
-geometry.setAttribute(
-    'normal',
-    new THREE.BufferAttribute(normals, normalNumComponents));
-geometry.setIndex(indices);
-
-

예제에서 차이점이 있는 부분을 표시해 두었습니다. 위치 속성에 참조값을 넘겨주었고, 이 -속성이 동적이라고 명시했습니다. 이는 Three.js에게 해당 속성을 자주 변경될 수 있음을 -알려주는 역할이죠.

-

이제 render 함수에서 매 프레임마다 법선을 기준으로 위치값을 변경해줍니다.

-
const temp = new THREE.Vector3();
-
-...
-
-for (let i = 0; i < positions.length; i += 3) {
-  const quad = (i / 12 | 0);
-  const ringId = quad / segmentsAround | 0;
-  const ringQuadId = quad % segmentsAround;
-  const ringU = ringQuadId / segmentsAround;
-  const angle = ringU * Math.PI * 2;
-  temp.fromArray(normals, i);
-  temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5));
-  temp.toArray(positions, i);
-}
-positionAttribute.needsUpdate = true;
-
-

마지막으로 positionAttribute.needsUpdate 속성을 활성화해 변화를 감지하도록 합니다.

-

- -

-

이 글이 BufferGeometry로 사용자 지정 geometry를 만들고, BufferAttribute를 다루는 -데 도움이 되었으면 좋겠습니다.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/debugging-glsl.html b/manual/ko/debugging-glsl.html deleted file mode 100644 index aedf886464ea5c..00000000000000 --- a/manual/ko/debugging-glsl.html +++ /dev/null @@ -1,77 +0,0 @@ - - - GLSL 디버깅 - - - - - - - - - - - - - - -
-
-

GLSL 디버깅

-
-
-
-

이 사이트에서 자바스크립트 자체에 대해 다루지 않듯, 아직까지 이 사이트에는 GLSL에 대한 글이 없습니다. GLSL은 간단히 다루기 어려운 주제이기에 GLSL을 배우고 싶다면 이 시리즈를 참고하기 바랍니다.

-

GLSL에 대해 어느 정도 안다면 이 글이 GLSL 디버깅에 도움이 될 겁니다.

-

GLSL 쉐이더를 만들었는데 아무것도 나타나지 않을 때, 저는 보통 쉐이더를 fragment 쉐이더로 바꾼 뒤 특정 색상만 반환하게 합니다. 예를 들어 쉐이더의 가장 마지막에 다음과 같은 코드를 넣는 것이죠.

-
void main() {
-
-  ...
-
-  gl_FragColor = vec4(1, 0, 0, 1);  // 빨강
-}
-
-

만약 저렇게 해서 요소가 보인다면 fragment 쉐이더에 문제가 있는 겁니다. 텍스처가 깨진 건지, 균등 변수(uniform)를 지정하지 않은 건지, 균등 변수에 잘못된 값을 지정한 건지는 알 수 없지만 적어도 어디서 문제를 찾아야 할지는 알 수 있죠.

-

어디가 틀렸는지 확인하기 위해 몇 가지 요소를 실제로 렌더링해볼 수 있습니다. 예를 들어 fragment 쉐이더의 법선(normal)을 사용한다면 저는 다음과 같은 코드를 추가할 겁니다.

-
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
-
-

법선의 값은 -1 에서 +1 사이이기에 0.5를 곱한 뒤 0.5를 더하면 값을 0.0 에서 0.1로 만들어 색으로 표현할 수 있습니다.

-

실행이 잘 된 예제에 이 쉐이더를 적용해보면 법선이 보통(normally) 어떻게 생겼는지 알 수 있습니다. 만약 법선이 정상적으로 보이지 않는다면 그게 다음 문제를 찾을 단서가 되겠죠. fragment 쉐이더에서 법선의 값을 변경하는 경우 같은 방법을 이용해 결과값을 렌더링할 수 있습니다.

-
- -

마찬가지로 텍스처를 사용하는 경우에는 텍스처 좌표가 있으니 그걸로 다음과 같이 활용할 수 있습니다.

-
gl_FragColor = vec4(fract(vUv), 0, 1);
-
-

텍스처 좌표를 사용하는 경우, fract를 실행한 값은 0부터 1 사이의 값이 아닐 수 있습니다. 대상 물체가 텍스처보다 크고 texture.repeat을 사용한 경우 1보다 큰 숫자가 나올 수 있겠죠.

-
- -

fragment 쉐이더의 다른 값으로도 비슷한 방법을 사용할 수 있습니다. 해당 값의 범위를 알아낸 뒤 해당 값을 0.0부터 1.0 사이의 값으로 변환해 gl_FragColor에 지정하는 거죠.

-

텍스처를 확인하려면 CanvasTextureDataTexture를 사용해보기 바랍니다.

-

만약 gl_FragColor에 빨간색을 지정했는데도 아무것도 보이지 않는다면, vertex 쉐이더 관련 물체의 방향 문제일 수 있습니다. 특정 행렬 좌표(matrix)가 잘못되었거나 어떤 속성의 값이 잘못되었거나 설정이 이상할 수 있죠.

-

그럼 먼저 행렬 좌표를 살펴봐야 합니다. renderer.render(scene, camera)를 한 번만 호출한 뒤 콘솔에서 객체를 펼쳐 보는 것이죠. 카메라의 전역 행렬 좌표나 투사 행렬 좌표에 NaN이 있는 걸까요? 장면 객체를 펼쳐 children 속성을 확인하니 전역 행렬 좌표는 멀쩡해 보입니다(NaN이 없음). 또한 다른 행렬 좌표의 4가지 값들도 모두 멀쩡해 보입니다. 만약 장면의 크기가 50x50x50인데 어떤 좌표값이 552352623.123이라면 확실히 뭔가 잘못된 겁니다.

-
- -

fragment 쉐이더와 마찬가지로 vertex 쉐이더에서도 값을 fragment 쉐이더에 넘겨주는 방식으로 값을 시각화할 수 있습니다. 양 쉐이더에 동일하게 변수를 생성한 뒤, 의심되는 값을 넘겨주는 거죠. 저라면 fragment 쉐이더가 그 값을 표시하도록 의심되는 값을 vNormal에 0.0에서 1.0 사이의 값으로 바꿔 지정할 겁니다. 그런 다음 결과를 보고 예상과 일치하는지 확인하는 것이죠.

-

이 방법이 통하지 않는다면 어떤 vertex 쉐이더가 geometry를 가장 간단하게 표시할 수 있을까요? 아주 간단하게 다음처럼 할 수 있을 겁니다.

-
gl_Position = projection * modelView * vec4(position.xyz, 1);
-
-

저 코드가 잘 작동한다면 변경사항을 조금씩 적용해보기 바랍니다.

-

추가로 크롬의 확장 프로그램 중 쉐이더 에디터나 다른 브라우저의 비슷한 프로그램을 찾아 사용하는 방법도 있습니다. 이는 다른 쉐이더가 어떻게 작동하는지 볼 때도 유용하죠. 또한 위 변경 사항을 바로 적용해볼 수 있다는 것도 장점입니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/debugging-javascript.html b/manual/ko/debugging-javascript.html deleted file mode 100644 index 51d267dda6a848..00000000000000 --- a/manual/ko/debugging-javascript.html +++ /dev/null @@ -1,369 +0,0 @@ - - - 자바스크립트 디버깅 - - - - - - - - - - - - - - -
-
-

자바스크립트 디버깅

-
-
-
-

이 글은 Three.js에 한정된 글이 아닙니다. 보다는 자바스크립트를 디버깅하는 일반적인 방법이라고 하는 편이 적당하죠. Three.js를 배우려는 분들 중에는 자바스크립트도 처음 접하는 분들이 더러 있는데, 이 글이 그런 분들에게 도움이 되었으면 좋겠네요.

-

디버깅은 방대한 주제라 여기서 모든 부분을 다루기는 어렵습니다. 이 글에서는 자바스크립트 입문자의 경우를 가정해 몇 가지 중요한 부분을 짚고 넘어갈 겁니다. 디버깅은 나중에 무엇을 배우든 도움이 되니 시간을 들여 꼭 살펴보기 바랍니다.

-

브라우저 개발자 도구

-

크롬, 파이어폭스, 사파리, 엣지 등 모든 브라우저에는 개발자 도구가 있습니다.

-

크롬에서는 아이콘을 클릭해 "도구 더보기 -> 개발자 도구"를 선택하면 개발자 도구를 열 수 있습니다. 기본 단축키도 거기에 같이 표시되죠.

-
- -

파이어폭스에서는 아이콘을 클린한 뒤 "웹 개발자 -> 도구 표시/숨기기"를 선택하면 됩니다.

-
- -

사파리는 먼저 고급 설정에서 개발자 메뉴를 활성화해야 합니다.

-
- -

그리고 개발자 메뉴에서 "Show/Connect Web Inspector"를 선택하면 되죠.

-
- -

크롬의 경우는 PC 버젼 크롬을 이용해 안드로이드 기기의 크롬을 디버깅할 수 있습니다. 사파리에서도 macOS 컴퓨터에서 아이폰이나 아이패드의 사파리를 디버깅할 수 있죠.

-

저는 크롬이 더 익숙하기에 크롬을 기준으로 설명하겠습니다. 다른 브라우저들도 다 비슷한 기능이 있으니 그다지 어렵지 않게 배운 걸 써먹을 수 있을 거예요.

-

캐시 끄기

-

브라우저는 내려 받은 데이터를 재사용합니다. 사용자 입장에서는 사이트를 두 번 이상 방문했을 때 파일을 다시 다운 받지 않아도 되니 환영할 일이죠.

-

하지만 개발자의 입장에서는 이 기능이 불편할 수 있습니다. 파일을 수정한 뒤 페이지를 새로고침해도 브라우저가 캐시로 저장된 파일을 사용해 수정된 내용이 반영되지 않기 때문이죠.

-

웹 개발을 하는 동안 캐싱을 비활성화 하면 이 문제를 해결할 수 있습니다. 이러면 브라우저가 항상 파일의 최신 버젼을 받아 사용하죠.

-

먼저 개발자 도구의 메뉴에서 설정을 선택한 뒤

-
- -

"Disable Cache (while DevTools is open)"을 선택합니다(개발자 도구가 열렸을 때 캐시 비활성화).

-
- -

자바스크립트 콘솔

-

개발자 도구에는 console이라는 탭이 있습니다. 여기에 각종 경고나 오류 메시지가 출력되죠.

-

Three.js를 사용하는 경우 1개 내지 2개의 메시지가 보이는 게 정상입니다.

-
- -

다른 메시지가 보인다면 이를 확인해봐야 합니다. 예를 들어 아래와 같은 경우

-
- -

오타가 났습니다. "three"를 "threee"로 잘못 썼죠.

-

뿐만 아니라 console.log로 직접 메시지를 출력할 수도 있습니다.

-
console.log(someObject.position.x, someObject.position.y, someObject.position.z);
-
-

살펴보고 싶은 객체를 출력할 수도 있습니다. 예를 들어 glTF 불러오기의 예제에서 root 장면(scene) 요소를 출력해보죠.

-
  {
-    const gltfLoader = new GLTFLoader();
-    gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-      const root = gltf.scene;
-      scene.add(root);
-+      console.log(root);
-
-

이제 자바스크립트 콘솔에서 해당 객체를 펼쳐 볼 수 있습니다.

-
- -

이외에도 console.error를 이용해 빨간 에러 메시지, console.warn을 이용해 노란 경고 메시지 등을 띄울 수 있습니다.

-

화면에 데이터 띄우기

-

이는 아주 간단하지만 사람들이 쉽게 떠올리지 못하는 방법입니다. <div><pre> 태그를 이용해 데이터를 화면에 출력하는 것이죠.

-

가장 쉬운 방법은 HTML 요소를 몇 개 만들고

-
<canvas id="c"></canvas>
-+<div id="debug">
-+  <div>x:<span id="x"></span></div>
-+  <div>y:<span id="y"></span></div>
-+  <div>z:<span id="z"></span></div>
-+</div>
-
-

캔버스 위에 올라가도록 스타일을 지정하는 겁니다(캔버스가 화면을 꽉 채웠다고 가정합니다).

-
<style>
-#debug {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-  padding: 1em;
-  background: rgba(0, 0, 0, 0.8);
-  color: white;
-  font-family: monospace;
-}
-</style>
-
-

그런 다음 요소들을 참조해 각 요소에 텍스트를 지정합니다.

-
// 초기화 시
-const xElem = document.querySelector('#x');
-const yElem = document.querySelector('#y');
-const zElem = document.querySelector('#z');
-
-// 렌더링 루프나 업데이트 시
-xElem.textContent = someObject.position.x.toFixed(3);
-yElem.textContent = someObject.position.y.toFixed(3);
-zElem.textContent = someObject.position.z.toFixed(3);
-
-

런타임에 값을 체크할 때 유용합니다.

-

- -

-

일회용 로그 버퍼(one-time log buffer)*를 만드는 것도 한 방법입니다. 일회용 로그 버퍼라는 이름은 제가 대충 지은 것이지만, 많은 게임들이 이 방법을 사용합니다. 일회용이라는 말처럼 이 방법은 지정한 메시지를 한 프레임 동안만 보여줍니다. 데이터를 출력할 부분에서 직접 매 프레임마다 메시지를 버퍼에 추가해야 하죠. 메시지마다 HTML 요소를 따로 만들었던 위 방법에 비하면 훨씬 경제적입니다.

-

※ 일회용 로그 버퍼: 원문에서는 clearing logger라고 썼습니다. 역주.

-

먼저 위 HTML 예제를 아래처럼 수정합니다.

-
<canvas id="c"></canvas>
-<div id="debug">
-  <pre></pre>
-</div>
-
-

그리고 버퍼의 추가/초기화를 관리하는 간단한 클래스를 만듭니다.

-
class ClearingLogger {
-  constructor(elem) {
-    this.elem = elem;
-    this.lines = [];
-  }
-  log(...args) {
-    this.lines.push([...args].join(' '));
-  }
-  render() {
-    this.elem.textContent = this.lines.join('\n');
-    this.lines = [];
-  }
-}
-
-

간단한 예제를 하나 만들어봅시다. 화면을 클릭했을 때 포인터 위치에 mesh를 만들고 2초 동안 무작위 방향으로 움직인 후 사라지도록 하겠습니다. 먼저 반응형 디자인에서 썼던 예제를 가져옵니다.

-

아래는 화면을 클릭할 때마다 Mesh를 추가하는 코드입니다.

-
const geometry = new THREE.SphereGeometry();
-const material = new THREE.MeshBasicMaterial({ color: 'red' });
-
-const things = [];
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min;
-}
-
-function createThing() {
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  things.push({
-    mesh,
-    timer: 2,
-    velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
-  });
-}
-
-canvas.addEventListener('click', createThing);
-
-

아래는 생성한 mesh를 움직이고, 메시지를 출력한 뒤 일정 시간이 지났을 때 해당 요소를 제거하는 코드입니다.

-
const logger = new ClearingLogger(document.querySelector('#debug pre'));
-
-let then = 0;
-function render(now) {
-  now *= 0.001;  // 초 단위로 변환
-  const deltaTime = now - then;
-  then = now;
-
-  ...
-
-  logger.log('fps:', (1 / deltaTime).toFixed(1));
-  logger.log('num things:', things.length);
-  for (let i = 0; i < things.length;) {
-    const thing = things[i];
-    const mesh = thing.mesh;
-    const pos = mesh.position;
-    logger.log(
-        'timer:', thing.timer.toFixed(3),
-        'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
-    thing.timer -= deltaTime;
-    if (thing.timer <= 0) {
-      // 해당 요소를 제거합니다. i를 증가시키지 않았다는 점에 유의하세요.
-      things.splice(i, 1);
-      scene.remove(mesh);
-    } else {
-      mesh.position.addScaledVector(thing.velocity, deltaTime);
-      ++i;
-    }
-  }
-
-  renderer.render(scene, camera);
-  logger.render();
-
-  requestAnimationFrame(render);
-}
-
-

예제를 빠르게 클릭하면 많은 데이터가 한 번에 나타날 겁니다.

-

- -

-

쿼리 파라미터(Query Parameters)

-

웹에서는 쿼리 파라미터(?, &)나 앵커(#)로 데이터를 넘겨줄 수 있습니다. 이들은 search, 해시(hash)라고 불리기도 하죠.

-
    https://domain/path/?query#anchor
-
-

예를 들어 이전 예제를 URL에 ?debug=true가 있을 때만 디버깅 요소가 보이도록 해보겠습니다.

-

먼저 쿼리를 파싱하는 코드를 만듭니다.

-
/**
-  * 쿼리 파라미터를 키/값 객체로 반환합니다.
-  * 예를 들어 쿼리 파라미터가 다음과 같다면
-  *
-  *    abc=123&def=456&name=gman
-  *
-  * `getQuery()`는 다음과 같은 객체를 반환합니다.
-  *
-  *    {
-  *      abc: '123',
-  *      def: '456',
-  *      name: 'gman',
-  *    }
-  */
-function getQuery() {
-  return Object.fromEntries(new URLSearchParams(window.location.search).entries());
-}
-
-

다음으로 디버깅 요소가 미리 보이지 않도록 합니다.

-
<canvas id="c"></canvas>
-+<div id="debug" style="display: none;">
-  <pre></pre>
-</div>
-
-

앞서 작성했던 예제에서 쿼리 파라미터를 읽어 ?debug=true일 때만 디버깅 요소가 보이도록 합니다.

-
const query = getQuery();
-const debug = query.debug === 'true';
-const logger = debug
-   ? new ClearingLogger(document.querySelector('#debug pre'))
-   : new DummyLogger();
-if (debug) {
-  document.querySelector('#debug').style.display = '';
-}
-
-

?debug=true가 아닐 때 사용할 DummyLogger도 만듭니다.

-
class DummyLogger {
-  log() {}
-  render() {}
-}
-
-

아래와 같은 url로 접근하면 아무것도 보이지 않습니다.

-

debug-js-params.html

-

대신 아래 url을 쓰면

-

debug-js-params.html?debug=true

-

디버깅 요소가 제대로 보입니다.

-

파라미터를 여러 개 전달할 때는 아무페이지.html?키=값&다른키=다른값처럼 각 항목을 '&'로 구분하면 됩니다. 파라미터를 사용하면 다양한 값을 지정할 수 있습니다. speed=0.01을 넘겨 받아 앱의 속도를 느리게 할 수도 있고 showHelpers=true 같은 값을 넘겨 받아 다른 글에서 다뤘던 조명, 그림자, 카메라의 절두체 등의 헬퍼 객체를 보이게 할 수도 있죠.

-

디버거 사용법을 익혀라

-

브라우저에는 전부 디버거가 있어 프로그램을 줄 단위로 실행하며 모든 변수를 검사할 수 있습니다.

-

디버거의 사용법은 너무 큰 주제이기에 이 글에서 전부 설명하기 어려우니 아래 링크를 참고하시기 바랍니다.

- -

디버거 등에서 NaN을 확인해라

-

NaN은 Not a Number(숫자가 아님)의 줄임말입니다. 자바스크립트가 수학적으로 연산할 수 없는 식이 주어졌을 때 반환하는 값이죠.

-

아래는 간단한 예입니다.

-
- -

저도 무언가를 만들다 화면에 아무것도 보이는 게 없으면 NaN이 있는지 확인합니다. 만약 NaN이 있다면 해당 부분부터 다시 살펴 보기 시작하죠.

-

glTF 파일 불러오기에서 처음 패스를 그렸을 때 SplineCurve 클래스로 2D 곡선을 만들었던 것, 기억하나요?

-

처음에 이 곡선을 이용해 자동차를 움직였었죠.

-
curve.getPointAt(zeroToOnePointOnCurve, car.position);
-
-

이때 curve.getPointAt은 내부적으로 두 번째 인자로 넘겨준 객체의 set 메서드를 호출합니다. 이 경우 인자로 넘겨준 객체는 car.position, Vector3이죠. Vector3set 메서드에는 x, y, z 세 가지 인자를 넘겨줘야 합니다. 하지만 SplineCurve는 2D이기에 car.position.set 메서드에 x와 y 값만 넘겨줍니다.

-

이러면 x, y의 값은 넘겨 받은 값으로 지정되나, z는 undefined로 지정될 겁니다.

-

디버거에서 자동차의 matrixWorld를 살펴 보니 NaN으로 지정된 값이 많이 보입니다.

-
- -

행렬 좌표(matrix)에 NaN이 있다는 것은 position, rotation, scale 등의 속성이나 행렬 좌표에 영향을 미치는 함수에 잘못된 데이터가 지정되었다는 것을 의미합니다. 여기서부터 추적해 올라가면 어디가 문제인지 쉽게 찾을 수 있겠죠.

-

자바스크립트 숫자에는 NaN뿐만 아니라 Infinity라는 값도 있습니다. 이 역시 많은 버그의 주범이 될 수 있죠.

-

코드를 까봐라!

-

Three.js는 오픈 소스입니다. 두려워 말고 코드를 한 번 까보세요! 깃허브에서 소스 코드를 살펴 보거나, 디버거에서 함수를 차례대로 추적해 볼 수도 있습니다. 이때 개발 단계에서는 three.min.js가 아닌 three.js를 쓰는 것을 추천합니다. 왜냐하면 three.min.js는 용량을 줄이기 위해 난독화와 압축이 적용된 형태거든요. three.js가 용량이 더 크긴 하지만 디버깅에는 훨씬 유리합니다. 저도 문제가 있을 때는 대부분 three.js를 사용해 코드를 단계별로 살펴보는 편입니다.

-

requestAnimationFrame을 렌더링 가장 마지막에 넣어라

-

다른 사람의 코드를 보다보면 아래와 같은 형식을 자주 봅니다.

-
function render() {
-   requestAnimationFrame(render);
-
-   // -- 주절주절 --
-
-   renderer.render(scene, camera);
-}
-requestAnimationFrame(render);
-
-

하지만 저는 이 시리즈의 처음에서부터 requestAnimationFrame을 아래에 배치했습니다.

-
function render() {
-   // -- 주절주절 --
-
-   renderer.render(scene, camera);
-
-   requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

이런 방식을 사용한 가장 중요한 이유는, 이래야 에러가 났을 때 코드를 멈출 수 있기 때문입니다. requestAnimationFrame을 상단에서 실행하면 에러가 나기 전에 이미 다른 프레임을 요청한 것이므로, 에러가 반복해 나타날 수 있습니다. 개인적인 생각이긴 하지만, 에러를 단순히 무시해버리는 것보다 문제를 찾아 고치는 게 훨씬 나을 겁니다. 에러 때문에 뭔가 제대로 실행되지 않는데 프로그램이 멈추지 않는다면 문제가 있는지조차 모를 수 있으니까요.

-

단위를 확인하라!

-

이는 예를 들어 언제 도(degree)를 사용해야 하는지, 언제 라디안(호도, radian)을 사용해야 하는지 알아야 한다는 의미입니다. 아쉽게도 Three.js는 모든 부분에서 같은 단위를 사용하지 않습니다. 당장 생각나기로는 카메라의 시야각(fov, field of view)이 도를 사용하는군요. 나머지 각도는 전부 라디안을 사용합니다.

-

길이 단위도 중요한 요소입니다. 최근까지도 3D 앱은 길이 단위를 자유롭게 선택할 수 있었습니다. 어떤 앱은 1칸 = 1cm를 썼고 어떤 앱은 1칸 = 1피트를 썼죠. 물론 지금도 길이 단위를 얼마든지 자유롭게 설정할 수 있습니다. Three.js는 기본적으로 1칸 = 1미터로 가정하는데, 물리 기반 렌더링 같은 경우는 조명의 세기를 미터로 설정하니 특히 더 신경을 써야 합니다. 증강현실(AR)이나 가상현실(VR) 같은 경우에도 사용자와 컨트롤러 사이의 거리를 알아야 하니 실제 세계의 단위를 잘 적용해야 하죠.

-

질문할 때 최소한으로, 완성된, 테스트할 수 있는 예제를 만들어라

-

Three.js에 관해 질문할 때는 MCVE에 맞춰 최소한으로(Minimal), 완성된(Complete), 테스트할 수 있는(Verifiable) 예제(Example)를 포함해야 합니다.

-

최소한으로 만드는 게 가장 중요합니다. 예를 들어 여러분이 glTF 파일 불러오기에서 경로를 자동차를 따라가게 하는 데 어려움을 겪는다고 해보죠. 이 예제에는 아주 많은 요소가 있습니다. 대충 목록을 만들어보죠.

-
    -
  1. HTML 한 묶음
  2. -
  3. CSS 약간
  4. -
  5. 조명
  6. -
  7. 그림자
  8. -
  9. 그림자를 조작하는 lil-gui
  10. -
  11. .gltf 파일을 불러오는 코드
  12. -
  13. 캔버스를 리사이징하는 코드
  14. -
  15. 자동차가 경로를 따라 움직이도록 하는 코드
  16. -
-

꽤 많은 양의 코드네요. 만약 오로지 경로를 따라가는 부분에 대해서만 질문할 거라면 <canvas><script>를 제외한 나머지 HTML은 없어도 될 겁니다. .gltf 파일도 마찬가지로 불필요하죠. 조명과 그림자를 없애고 MeshBasicMaterial을 사용할 수도, lil-gui를 제거할 수도 있습니다. 차라리 GridHelper를 쓰는 게 훨씬 간단하겠네요. 마지막으로 물체가 경로를 따라 움직이는 부분만 질문하니 자동차 대신 육면체를 써도 될 겁니다.

-

아래는 위 요소를 모두 고려한 예제입니다. 원래 271줄이었던 코드를 135줄로 줄였죠. 21개 점으로 이루어진 복잡한 경로 대신 3개 혹은 4개의 점만 사용하는 간단한 경로를 사용해 코드를 더 줄일 수도 있을 겁니다.

-

- -

-

OrbitController를 그대로 둔 건 카메라를 움직이는 등 단순히 다른 사람의 편의를 위해서지만, 경우에 따라서는 저것도 제거할 수 있을 겁니다.

-

MCVE의 장점은 이렇게 예제를 만들다 문제가 해결되기도 한다는 겁니다. 불필요한 요소를 제거하고 에러를 재현할 수 있는 가장 작은 코드를 짜다 보면 문제의 원인이 밝혀지는 경우가 꽤 많거든요.

-

거기다 MCVE는 답변자에 대한 예의이기도 합니다. 최소한의 예제를 만들어 다른 사람이 여러분의 문제 해결을 돕기 쉽도록 배려하는 것이죠. 이 과정에서 배우는 것도 많고요.

-

또한 스택 오버플로우에서 질문글을 올릴 때 코드의 일부분(snippet)을 올리는 것도 굉장히 중요합니다. 물론 JSFiddle이나 Codepen 또는 비슷한 사이트를 써 여러분이 만든 MVCE를 테스트하게끔 할 수도 있죠. 하지만 스택 오버플로우에서 글 쓰기를 눌러보면 질문 자체에 코드 일부를 붙여넣는 게 필수 조건라는 것을 알 수 있습니다. 코드의 일부분을 집어 넣어야만 해당 조건이 만족되죠.

-

혹시나 해서 말해두지만, 이 사이트의 예제들로 질문할 때는 코드의 모든 부분을 확인해야 합니다. HTML, CSS, 자바스크립트를 전부 스니펫(snippet) 에디터에 넣으면 되죠. 추가로 궁금한 부분과 관련된 코드만 남기고 나머지는 없애 코드를 최소한으로 만드는 것만 기억하기 바랍니다.

-

이 정도만 따르면 질문에 대한 답변을 받는 게 그다지 어렵지 않을 겁니다.

-

MeshBasicMaterial을 사용하라

-

MeshBasicMaterial은 조명의 영향을 받지 않습니다. 때문에 재질(material)을 이걸로 바꾸면 보이지 않았던 물체가 보이는 경우가 있죠. 만약 어떤 물체가 MeshBasicMaterial을 적용했을 때는 잘 나타나는데 다른 재질로 바꾸면 나타나지 않는다면, 해당 문제는 재질이나 조명 또는 다른 외부 요소 때문일 겁니다.

-

카메라의 nearfar 설정을 확인하라

-

카메라에 관한 글에서 다뤘듯, PerspectiveCamera에는 nearfar 설정이 있습니다. 다른 것보다 먼저 장면 요소를 전부 담을 수 있도록 이 값들을 설정하세요. 임시로라도 near를 0.001, far를 1000000 등 임의의 큰 값으로 설정한다면 깊이에 따른 해상도 문제가 나타날 겁니다. 오직 카메라에 가까운 물체만 제대로 보이겠죠.

-

장면이 카메라 앞에 있는지 확인하라

-

장면이 화면에 나타나지 않는 경우, 장면이 카메라 앞에 없는 게 원인일 때도 있습니다. 만약 카메라를 조작할 수 없다면 OrbitController 같은 액션을 추가해 카메라를 돌려 보기 바랍니다. 또는 제가 이 글에서 다뤘던 것처럼 카메라가 장면 전체를 담도록 해보세요. 제가 저 글에서 쓴 코드는 장면의 요소를 찾아 해당 요소를 전부 담도록 카메라의 위치와 near, far 값을 조정합니다. 저 코드에서 디버거를 사용하거나, console.log를 추가해 요소의 크기나 장면의 중점을 출력해 볼 수도 있죠.

-

뭐든 카메라 앞에 배치해봐라

-

이건 문제가 생겼는데 어떤 점이 문제일지 모를 때, 하나씩 천천히 요소를 추가해보라는 말입니다. 만약 코드를 실행했는데 장면에 아무것도 보이지 않는다면 카메라 바로 앞에 간단한 요소를 배치해보세요. 구체나 육면체를 만들어 MeshBasicMaterial 같이 단순한 재질을 지정해 화면에 제대로 뜨는지 확인하는 겁니다. 그런 다음 시간을 들여 다른 요소들을 하나하나 추가해 나가는 거죠. 이러다보면 버그가 다시 나타나거나 어떤 게 문제인지 알 수 있을 겁니다.

-
-

여기까지 자바스크립트를 디버깅하는 몇 가지 팁을 살펴봤습니다. 다음 글에서는 GLSL을 디버깅하는 몇 가지 팁에 대해 알아보겠습니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/fog.html b/manual/ko/fog.html deleted file mode 100644 index 30847d540ce113..00000000000000 --- a/manual/ko/fog.html +++ /dev/null @@ -1,269 +0,0 @@ - - - 안개(Fog) - - - - - - - - - - - - - - -
-
-

안개(Fog)

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글을 -읽고 오길 권장합니다.

-

※ 카메라에 대해 잘 모른다면, 먼저 카메라에 관한 글을 -먼저 읽기 바랍니다.

-

3D 엔진에서 안개란, 일반적으로 카메라로부터의 거리에 따라 특정 색상으로 -점차 변화하는 것을 말합니다. Three.js에서는 FogFogExp2 객체를 -생성한 뒤, 장면(scene)의 fog 속성에 지정해 안개를 사용합니다.

-

Fog는 인자로 nearfar값을 받는데, 이는 카메라로부터의 거리값입니다. -near값보다 가까운 공간은 안개의 영향이 전혀 없고, far값보다 먼 공간은 -완전히 안개에 뒤덮입니다. nearfar 사이의 공간에 있는 물체 또는 물체의 -일부는 점차 안개의 색으로 변화하죠.

-

FogExp2는 카메라에서 멀어질수록 안개의 강도가 강해집니다.

-

두 가지 안개 모두 마찬가지로, 안개를 사용하려면 장면의 속성에 지정해야 합니다.

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;  // 하양
-  const near = 10;
-  const far = 100;
-  scene.fog = new THREE.Fog(color, near, far);
-}
-
-

FogExp2의 경우는 다음처럼 쓸 수 있죠.

-
const scene = new THREE.Scene();
-{
-  const color = 0xFFFFFF;
-  const density = 0.1;
-  scene.fog = new THREE.FogExp2(color, density);
-}
-
-

FogExp2가 더 현실적이긴 하나, 보통 안개의 범위를 특정하기 쉬운 -Fog를 더 많이 사용합니다.

-
-
-
-
THREE.Fog
-
-
-
-
THREE.FogExp2
-
-
- -

한 가지 알아둬야 하는 건 안개는 렌더링되는 물체라는 점입니다. -안개는 물체의 픽셀을 렌더링할 때 같이 렌더링되는데, 이 말은 장면에 -특정 색상의 안개 효과를 주려면 안개와 배경색 둘 다 같은 색으로 -지정해야 한다는 겁니다. 배경색은 scene.background -속성을 THREE.Color 인스턴스로 지정해 바꿀 수 있습니다.

-
scene.background = new THREE.Color('#F00');  // 빨강
-
-
-
-
-
파란 안개, 빨간 배경
-
-
-
-
파란 안개, 파란 배경
-
-
- -

아래는 이전에 사용했던 예제에 안개를 추가한 것입니다. 장면을 생성한 뒤 -안개를 추가하고, 장면의 배경색을 바꾸기만 했죠.

-
const scene = new THREE.Scene();
-
-+{
-+  const near = 1;
-+  const far = 2;
-+  const color = 'lightblue';
-+  scene.fog = new THREE.Fog(color, near, far);
-+  scene.background = new THREE.Color(color);
-+}
-
-

아래 예제의 카메라는 near값이 0.1, far값이 5입니다. 카메라의 위치는 -z = 2이죠. 정육면체의 크기는 1칸이고, z축의 원점에 있습니다. 여기서 -안개를 near = 1, far = 2로 설정하면 정육면체가 중간부터 사라지기 -시작하겠죠.

-

- -

-

인터페이스를 추가해 안개를 조정할 수 있도록 하겠습니다. 이번에도 lil-gui를 -사용할 거예요. lil-gui는 객체와 객체의 속성 키값을 받아 자동으로 인터페이스를 -생성합니다. 단순히 안개의 nearfar 제어하도록 설정할 수도 있지만, near값이 -far값보다 큰 경우는 없기에 헬퍼를 만들어 near값을 항상 far보다 같거나 -작게, far값을 항상 near보다 같거나 크게 설정하도록 하겠습니다.

-
/**
- * 이 클래스의 인스턴스를 lil-gui에 넘겨
- * near나 far 속성을 조정할 때 항상
- * near는 never >= far, far는 never <= near가 되도록 합니다
- **/
-class FogGUIHelper {
-  constructor(fog) {
-    this.fog = fog;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-}
-
-

방금 만든 클래스를 아래처럼 활용합니다.

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-+
-+  const fogGUIHelper = new FogGUIHelper(scene.fog);
-+  gui.add(fogGUIHelper, 'near', near, far).listen();
-+  gui.add(fogGUIHelper, 'far', near, far).listen();
-}
-
-

nearfar 인자는 각 안개 속성의 최솟값과 최댓값입니다.

-

마지막 2줄의 .listen() 메서드를 호출하면 lil-gui가 변화를 감지합니다. -near 속성을 바꿀 때 동시에 far 속성을 재할당하고, far 속성을 바꿀 때도 -동시에 near를 재할당하는데, 이 메서드를 호출하면 조작한 속성 외의 다른 -속성의 변화도 UI에 업데이트됩니다.

-

여기에 안개의 색까지 조정할 수 있으면 금상첨화겠네요. 하지만 아까 설명했듯 -안개의 색을 바꾸려면 배경색도 같이 바꿔야 합니다. 헬퍼 클래스에 가상 속성을 -하나 만들어 lil-gui가 이 속성을 변경할 때 배경색과 안개색을 같은 값으로 -바꿔주면 어떨까요?

-

lil-gui의 색상 타입은 4가지입니다. 하나는 CSS의 6자리 16진수 문자열(hex string, 예: #f8f8f8)이고, -하나는 hue(색상), saturation(채도), value 객체(예: { h: 60, s: 1, v: 0 }), -하나는 RGB 배열(예: [ 255, 128, 64 ]) 또는 RGBA 색상 배열(예: [ 127, 200, 75, 0.3 ])이죠.

-

lil-gui가 하나의 값만 조작하도록 하는 게 제일 간단하니, 16진수 문자열을 사용하겠습니다. -다행히 THREE.Color에는 getHexString 메서드가 있어 색상을 -문자열로 쉽게 바꿀 수 있죠. 앞에 '#'만 덧붙이면 됩니다.

-
/**
- * 이 클래스의 인스턴스를 lil-gui에 넘겨
- * near나 far 속성을 조정할 때 항상
- * near는 never >= far, far는 never <= near가 되도록 합니다
- **/
-+// 또 lil-gui가 color 속성을 조작할 때 안개와 배경색을 동시에 변경합니다
-class FogGUIHelper {
-*  constructor(fog, backgroundColor) {
-    this.fog = fog;
-+    this.backgroundColor = backgroundColor;
-  }
-  get near() {
-    return this.fog.near;
-  }
-  set near(v) {
-    this.fog.near = v;
-    this.fog.far = Math.max(this.fog.far, v);
-  }
-  get far() {
-    return this.fog.far;
-  }
-  set far(v) {
-    this.fog.far = v;
-    this.fog.near = Math.min(this.fog.near, v);
-  }
-+  get color() {
-+    return `#${this.fog.color.getHexString()}`;
-+  }
-+  set color(hexString) {
-+    this.fog.color.set(hexString);
-+    this.backgroundColor.set(hexString);
-+  }
-}
-
-

이번에는 gui.addColor 메서드를 호출합니다. 색상 UI를 생성하는 메서드로, -방금 추가한 가상 속성을 조작하도록 설정합니다.

-
{
-  const near = 1;
-  const far = 2;
-  const color = 'lightblue';
-  scene.fog = new THREE.Fog(color, near, far);
-  scene.background = new THREE.Color(color);
-
-*  const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
-  gui.add(fogGUIHelper, 'near', near, far).listen();
-  gui.add(fogGUIHelper, 'far', near, far).listen();
-+  gui.addColor(fogGUIHelper, 'color');
-}
-
-

- -

-

near를 1.9 정도, far를 2.0 정도로 설정하면 안개의 경계가 굉장히 -선명해질 겁니다. 정육면체들이 카메라에서 2칸 떨어져 있으므로 near를 -1.1, far를 2.9 정도로 설정하면 경계가 가장 부드러운 것이라고 할 수 -있죠.

-

추가로 재질(material)에는 불린 타입의 fog 속성이 있습니다. -해당 재질로 렌더링되는 물체가 안개의 영향을 받을지의 여부를 결정하는 속성이죠. -"안개 효과를 없애버리면 그만 아닌가?" 생각할 수 있지만, 3D 운전 시뮬레이터를 -만드는 경우를 상상해봅시다. 차 밖은 안개가 자욱하더라도 차 안에서 볼 때 차 내부는 -깔끔해야 할 수도 있죠.

-

안개가 짙은 날, 집 안에서 창 밖을 바라보는 장면이 더 와닿을지도 모르겠네요. -안개가 카메라로부터 2미터 이후부터 끼기 시작하고(near = 2), 4미터 이후에는 -완전히 안개에 덮히도록(far = 4) 설정합니다. 방은 2미터이고, 집은 최소 4미터입니다. -여기서 집 안의 재질이 안개의 영향을 받도록 놔둔다면 방 끝에서 창 밖을 바라볼 -때 방 안도 안개가 낀 것처럼 보이겠죠.

-
-
-
-
모든 재질의 fog: true
-
-
- -

방 끝 쪽 천장과 벽에 안개가 낀 것이 보일 겁니다. 집 내부 재질의 fog 옵션을 끄면 -안개를 없앨 수 있죠.

-
-
-
-
집 밖 물체의 재질만 fog: true
-
-
- -

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/fundamentals.html b/manual/ko/fundamentals.html deleted file mode 100644 index 20e551e487caaf..00000000000000 --- a/manual/ko/fundamentals.html +++ /dev/null @@ -1,406 +0,0 @@ - - - Three.js란? - - - - - - - - - - - - - - -
-
-

Three.js란?

-
-
-
-

Three.js 입문하신 것을 환영합니다! -Three.js는 웹페이지에 3D 객체를 쉽게 -렌더링하도록 도와주는 자바스크립트 3D 라이브러리입니다.

-

대부분의 경우 Three.js는 3D 객체를 렌더링하는 데 WebGL을 사용합니다. -때문에 Three.js = WebGL이라고 착각하기 쉽죠. -하지만 WebGL은 점, 선, 삼각형만을 그리는 아주 단순한 시스템입니다. -WebGL로 직접 무언가를 만들려면 상당히 많은 양의 코드를 짜야 하죠. -만약 씬(scenes), 광원, 그림자, 물체, 텍스처 등 3차원 세계를 구현한다면 머리도 꽤 복잡하겠거니와 -코드 자체도 굉장히 복잡할 겁니다. -Three.js는 이런 3D 요소들의 처리를 도와 직관적인 코드를 짤 수 있도록 해줍니다.

-

본 튜토리얼은 ES2015 문법을 적극적으로 사용할 것이므로, -여러분이 이미 최신 자바스크립트에 능숙하다는 가정 아래에 진행합니다. -자세한 내용에 대해서는 먼저 알아야 할 것을 참고하세요. -대부분의 모던 브라우저가 자동 업데이트 기능을 사용하므로, -특이한 환경이 아니라면 예시에 나온 코드를 실행하는 데 문제가 없을 것입니다. -만약 구형 브라우저에서도 코드가 실행되길 원한다면, 바벨(Babel) -같은 트랜스파일러를 찾아보세요. 물론 너무 오래된 엔진을 사용하는 브라우저에서는 -Three.js를 아예 구동하지 못할 수 있습니다.

-

새로운 프로그래밍 언어를 배울 때, "Hello World!"를 출력하며 시작했던 것을 기억하나요? -Three.js는 3차원 세계를 다루므로, 우리는 정육면체(cube)를 3차원으로 구현하는 것으로 튜토리얼을 -시작하고자 합니다. 이른바 "Hello Cube"라는 것이죠!

-

하지만 먼저 Three.js 앱의 구조부터 간략히 살펴보죠. Three.js 앱을 만들려면 -다양한 객체를 생성해 연결해야 합니다. 아래는 Three.js 앱의 구조를 도식화한 것입니다.

-
- -

위 도표에서 중요한 것들을 추려보죠.

-
    -
  • 먼저 Renderer가 있습니다. Three.js의 핵심 객체이죠. Renderer는 -SceneCamera 객체를 넘겨 받아 카메라의 절두체(frustum) -안 3D 씬의 일부를 평면(2차원) 이미지로 렌더링합니다.

    -
  • -
  • 씬 그래프(Scene graph)Scene 또는 -다수의 Mesh, Light, Group, Object3D, Camera로 이루어진 -트리 구조와 유사합니다. Scene은 씬 그래프의 최상위 노드로서 배경색(background color), -안개(fog) 등의 요소를 포함합니다. Scene에 포함된 객체들 또한 부모/자식의 -트리 구조로 이루어지며, 이는 각 객체의 유래와 방향성을 나타냅니다. 쉽게 말해 자식 객체의 -위치(position)와 방향(orientation)이 부모 기준이라는 거죠. 예를 들어 자동차의 바퀴가 -자동차 객체의 자식 객체라면, 자동차 객체의 방향을 움직일 때, 바퀴 객체의 방향 또한 같이 -움직입니다(더 자세한 내용은 씬 그래프에 관한 글에서 확인할 수 있습니다)

    -

    Camera가 도표에서 반쯤 나간 것이 보이나요? 이는 의도된 것으로, 다른 객체와 달리 -Camera는 굳이 씬 그래프에 포함될 필요가 없음을 보여주기 위함입니다. 물론 다른 -객체와 마찬가지로 Camera 또한 다른 객체의 자식 객체가 될 수 있습니다. 이러면 -부모 객체에 따라 Camera 또한 움직이겠죠. 씬 그래프에 관한 글 -마지막에 여러개의 Camera를 넣는 예제가 있으니 참고하시기 바랍니다.

    -
  • -
  • Mesh는 어떤 Material로 하나의 Geometry를 그리는 객체입니다. -Material, Geometry는 재사용이 가능하여 여러개의 Mesh가 하나의 -Material 또는 Geometry를 동시에 참조할 수 있습니다. 파란색 정육면체 2개를 -그린다고 해보죠. 일단 두 정육면체의 위치가 달라야 하니, 2개의 Mesh가 -필요합니다. 그리고 정점(vertex, 꼭지점) 데이터를 가진 한 개의 Geometry와 -채색을 위한 하나의 Material이 필요하겠죠. 이때 각 Mesh는 객체를 복사할 -필요 없이, 같은 Geometry 그리고 Material을 참조할 수 있습니다.

    -
  • -
  • Geometry는 기하학 객체의 정점 데이터입니다. 구(sphere), 정육면체(cube), -면(plane), 개, 고양이, 사람, 나무, 건물 등 아주 다양한 것이 될 수 있죠. Three.js는 -기본적으로 몇 가지의 내장(built-in) 기하학 객체를 제공합니다. -물론 직접 기하학 객체를 만들 수도 있고, -파일에서 기하학 객체를 불러올 수도 있죠.

    -
  • -
  • Material은 기하학 객체를 그리는 데 사용하는 표면 속성입니다. -색이나 밝기 등을 지정할 수 있죠. 하나의 Material는 여러개의 Texture를 사용할 수 -있습니다. 기하학 객체의 표면을 이미지로 덮어씌울 때 주로 사용하죠.

    -
  • -
  • Texture는 이미지나 파일에서 로드한 이미지, -canvas로 생성한 이미지 -또는 다른 Scene 객체에서 렌더링한 결과물에 해당합니다.

    -
  • -
  • Light여러 종류의 광원에 해당합니다.

    -
  • -
-

이제 기본적인 구조에 대해 배웠으니 아래와 같은 구조의 "Hello Cube"를 만들어 봅시다.

-
- -

먼저, Three.js를 로드합니다.

-
<script type="module">
-import * as THREE from 'three';
-</script>
-
-

type="module" 속성을 지정하는 것을 잊지 마세요. 이러면 import 키워드를 -통해 Three.js 모듈을 불러올 수 있습니다. 다른 방법으로 로드할 수도 있지만 -모듈 로드가 r106 이후 빌드에서 추천하는 방식입니다. 모듈로 로드하면 다른 의존성 -스크립트를 알아서 로드하기 때문에 <script> 태그를 일일이 작성하는 수고를 덜 -수 있습니다.

-

그리고 <canvas> 태그를 작성합니다.

-
<body>
-  <canvas id="c"></canvas>
-</body>
-
-

이제 Three.js에게 렌더링을 맡겨보죠.

-
<script type="module">
-import * as THREE from 'three';
-
-+function main() {
-+  const canvas = document.querySelector('#c');
-+  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  ...
-</script>
-
-

canvas 요소(element)를 참조한 이후 WebGLRenderer를 생성했습니다. -이 렌더러(renderer)는 여러분이 입력한 데이터를 실제로 canvas에 그려주는

-

만약 Three.js에 canvas 요소를 넘겨주지 않으면, Three.js는 canvas 요소를 -자동으로 생성합니다. 그리고 여러분이 직접 이 canvas 요소를 문서(document) -에 삽입해야 하죠. 어디에 canvas 요소를 넣을지는 경우에 따라 다를 테니, -예제에서는 자바스크립트에서 요소를 참조하도록 하는 편이 호환성 면에서 -더 낫다고 판단했습니다. 만약 canvas 요소를 동적으로 삽입한다면 여러분이 -직접 코드를 고쳐야 할 테니까요.

-

다음으로 카메라가 필요하니 PerspectiveCamera(원근 카메라) 객체를 생성해봅시다.

-
const fov = 75;
-const aspect = 2;  // the canvas default
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-
-

fovfield of view(시야각)의 줄임말입니다. 예제의 경우 수직면 75도로 -설정했습니다. 알아둬야 할 건 Three.js의 대부분이 각도 단위로 호도(radians)를 -사용하는데, 원근 카메라만 특이하게 도(degrees)를 인자로 받는다는 점입니다.

-

aspect는 canvas의 가로 세로 비율입니다. 이는 다른 글 -에서 자세히 다루겠지만, 기본 설정으로 canvas의 크기는 300x150이니 비율도 -300/150, 2로 설정했습니다.

-

nearfar는 카메라 앞에 렌더링되는 공간 범위를 지정하는 요소입니다. -이 공간 바깥에 있는 요소는 화면에서 잘려나가며, 렌더링되지 않을 것입니다.

-

위에서 살펴본 4가지 속성은 하나의 "절두체"를 만듭니다. "절두체"는 -끝부분이 잘려나간 피라미드처럼 생긴 3차원 모양인데, 구, 정육면체, -각기둥(prism)처럼 3차원 모양의 하나로 생각하면 됩니다.

-

-

nearfar 평면의 높이는 시야각(fov), 너비는 시야각과 aspect에 의해 -결정됩니다.

-

그리고 앞서 말했듯 절두체 안에 있는 요소만 렌더링되며, 바깥에 있는 요소는 -렌더링되지 않습니다.

-

기본 설정으로 카메라는 -Z 축 +Y 축, 즉 아래를 바라봅니다. 정육면체를 원점에 -놓을 예정이니 카메라를 조금 뒤로 움직여 화면 안에 들어오도록 해보죠.

-
camera.position.z = 2;
-
-

우리가 원하는 결과물을 다음처럼 그려볼 수 있습니다.

-

-

카메라는 z = 2 위치에서 -Z 방향을 바라봅니다. 절두체는 카메라 앞 0.1 칸에서 -5칸까지를 차지하죠. 또한 아래를 바라보는 형태이기 때문에, 시야각은 canvas -크기의 영향을 받습니다. 앞서 만든 canvas는 두 배 더 크기 때문에 실제로는 시야각이 -위에서 정의한 75도 보다는 훨씬 넓을 것입니다.

-

이제 Scene을 만듭니다. Three.js에서 Scene이란 씬 그래프에서 가장 상단에 -위치한 요소입니다. 뭔가를 화면에 렌더링하고 싶다면 먼저 Scene에 추가해야 하죠. -여기서는 간단하게 다룰 것이므로 자세한 내용은 이 글을 -참고하세요.

-
const scene = new THREE.Scene();
-
-

다음으로 간단한 정육면체를 만들어보죠. Three.js에서 렌더링되는 대부분의 3D 요소는 -정점 데이터가 정의된 기하학 객체를 필요로 합니다. 지금은 정육면체를 만들어야 하니 -BoxGeometry 생성자를 호출하겠습니다.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-

다음으로 Material을 만들고 색을 지정합니다. 색을 지정할 때는 CSS처럼 -숫자 형태의 hex 코드를 이용합니다(# 대신 0x. 역주).

-
const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
-
-

그리고 앞서 만든 Geometry(물체의 형태)와 Material(물체의 색, 밝기, 질감 등)을 -이용해 Mesh를 만듭니다. MeshGeometry, Material 외에도 물체의 위치, 방향, -크기 등을 담은 객체입니다.

-
const cube = new THREE.Mesh(geometry, material);
-
-

마지막으로 완성된 정육면체 MeshScene에 넣어줍니다.

-
scene.add(cube);
-
-

rendererrender 메서드에 SceneCamera를 넘겨주면 화면을 렌더링할 -수 있습니다.

-
renderer.render(scene, camera);
-
-

아래는 전체 코드입니다.

-

- -

-

물론 위 예제는 3D 정육면체라고 하긴 어렵습니다. 코드 상으로 Three.js는 -분명 3D 정육면체를 그렸지만, 카메라가 -Z 방향을 바라보고, 정육면체도 -Z 축에 맞추어 정렬되어 있기 때문에 한 면만 보입니다.

-

한 번 이 물체에 애니메이션을 주고 3D처럼 보이는지 확인해보죠. -애니메이션을 구현하기 위해 requestAnimationFrame 루프 안에서 렌더링 함수를 호출합니다.

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cube.rotation.x = time;
-  cube.rotation.y = time;
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

requestAnimationFrame은 브라우저에 애니메이션 프레임을 요청하는 함수입니다. -인자로 실행할 함수를 전달하면 되죠(이 경우는 render 함수). 브라우저는 넘겨받은 -함수를 실행하고, 페이지에 변화가 있다면 페이지를 다시 렌더링합니다. 위 예제에서는 -Three.js의 renderer.render 메서드를 호출해 씬을 렌더링하도록 했죠.

-

requestAnimationFrame은 매개변수로 넘겨받은 함수에 페이지가 로드된 이후의 시간값을 -밀리초 단위로 넘겨줍니다. 전 초 단위가 더 익숙하기 때문에, 밀리초 단위를 초 단위로 -변경하였습니다.

-

그리고 정육면체의 X, Y축 회전값을 현재 시간값으로 설정합니다(이 회전값은 라디안(radians) -단위를 사용합니다). 360˚도는 2π 라디안이니 큐브는 각 축마다 -약 6.28초에 한 바퀴를 돌게 됩니다.

-

그리고 씬을 렌더링 한 후, 브라우저에 재귀적으로 애니메이션 프레임을 요청해 이 -애니메이션이 반복되도록 합니다.

-

마지막으로 루프 바깥에서 requestAnimationFrame을 한 번 호출해 루프를 -시작합니다.

-

- -

-

아까보단 낫지만 아직 3D 물체라고 부르기엔 뭔가 부족합니다. 광원을 추가해 그림자가 -지도록 하면 어떨까요? 나중에 이 글에서 자세히 다루겠지만, -Three.js에는 다양한 종류의 광원이 있습니다. 다 살펴보기 힘드니 지금은 예시로 -DirectionalLight를 사용해보도록 하죠.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 3;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(-1, 2, 4);
-  scene.add(light);
-}
-
-

DirectionalLight에는 위치(position)목표(target) 속성이 있습니다. -기본값은 0, 0, 0 이죠. 먼저 position-1, 2, 4로 설정해 카메라보다 -약간 동서쪽, Z축으로는 약간 위로 보냅니다. target은 기본값 0, 0, 0 그대로 -두어 공간의 중앙을 비추도록 합니다.

-

그리고 material도 바꿔야 합니다. MeshBasicMaterial은 광원에 반응하지 않으니, -광원에 반응하는 MeshPhongMaterial로 바꿉니다(phong은 광원 반사 모델을 처음 개발한 사람 이름. 역주).

-
-const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
-+const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
-
-

다음은 현재까지의 프로그램 구조를 도식화 한 것이고,

-
- -

아래는 결과물입니다.

-

- -

-

이제 3D라고 불러도 어색하지 않네요.

-

재미를 위해서 한 번 정육면체를 2개만 더 만들어 봅시다.

-

미리 만들어 놨던 Geometry를 사용하고, Material만 바꿔 다른 색을 -가진 큐브 2개를 만들겠습니다.

-

먼저 함수를 하나 만들어보겠습니다. 이 함수는 넘겨받은 색상값으로 -새로운 Material을 만들고, 넘겨받은 Geometry와 조합해 새로운 -Mesh를 만듭니다. 그리고 씬에 추가한 후 넘겨받은 X축 값을 통해 물체를 이동시키죠.

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-

다음으로 3가지 다른 색상과 X축 값으로 이 함수를 호출해 결과물을 배열로 -저장합니다.

-
const cubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

마지막으로 render 함수에서 3개의 정육면체를 회전시킵니다. 동적인 -효과를 위해 각 큐브마다 약간 다른 값을 주도록 해보죠.

-
function render(time) {
-  time *= 0.001;  // convert time to seconds
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  ...
-
-

결과물은 다음과 같습니다.

-

- -

-

아까 위에서 좌표로 도식한 그림과 위 결과물을 비교해보면, 예상대로 -X축으로 -2, +2만큼 이동한 정육면체들의 일부가 절두체에서 약간 벗어났습니다. -또한 가운데 정육면체에 비해 굉장히 굴절되어 보이는데, 이는 우리가 설정한 시야각이 -너무 좁은 탓입니다.

-

위 프로그램은 구조는 다음과 같습니다.

-
- -

그림을 보면 각 Mesh 객체는 같은 BoxGeometry를 참조합니다. 그러나 -각 Mesh는 다른 MeshPhongMaterial을 참조하므로 다른 색을 띄죠.

-

이 인트로가 Three.js를 시작하는 데 도움이 되었으면 합니다. -다음 장에서는 코드를 반응형으로 만들어 다양한 상황에 적용할 수 있도록 해 볼 것입니다.

-
-

es6 모듈, Three.js, 프로젝트 구조

-

Three.js r106 릴리즈 이후에서는 three.js를 es6 모듈로 사용하길 권장합니다.

-

-es6 모듈은 js 파일이나 인라인 <script type="module"> 태그 안에서 -import 키워드를 사용해 로드할 수 있습니다. -

-
<script type="module">
-import * as THREE from 'three';
-
-...
-
-</script>
-
-

-경로는 절대경로나 상대경로를 사용해야 하며, 상대경로는 <img>, <a> 태그와 -달리 ./ 또는 ../로 시작해야 합니다. -

-

-만약 절대경로가 같다면 같은 script는 한 번만 로드됩니다. Three.js 기반 프로젝트의 폴더 구조를 -잘 구성해야 하는 가장 큰 이유이죠. -

-
someFolder
- |
- ├-build
- | |
- | +-three.module.js
- |
- +-examples
-   |
-   +-jsm
-     |
-     +-controls
-     | |
-     | +-OrbitControls.js
-     | +-TrackballControls.js
-     | +-...
-     |
-     +-loaders
-     | |
-     | +-GLTFLoader.js
-     | +-...
-     |
-     ...
-
-

-이유인 즉 OrbitControls.js -같은 코드는 다음처럼 상대경로로 모듈을 로드하기 때문에 -

-
import * as THREE from '../../../build/three.module.js';
-
-

-같은 폴더 구조를 사용함으로써 모든 예제 스크립트가 같은 three.module.js 파일을 -참조하도록 할 수 있죠. -

-
import * as THREE from './someFolder/build/three.module.js';
-import {OrbitControls} from './someFolder/addons/controls/OrbitControls.js';
-
-

아래는 CDN을 사용하는 예시입니다. three.modules.js의 경로가 /build/three.modules.js -로 끝나야 한다는 것을 명심하세요.

-
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@<version>/build/three.module.js';
-import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/three@<version>/addons/controls/OrbitControls.js';
-
-
-
-
-
- - - - - - - - diff --git a/manual/ko/game.html b/manual/ko/game.html deleted file mode 100644 index 7df5ab41148927..00000000000000 --- a/manual/ko/game.html +++ /dev/null @@ -1,1654 +0,0 @@ - - - 로 게임 만들기 - - - - - - - - - - - - - - -
-
-

로 게임 만들기

-
-
-
-

제가 꽤 많이 받았던 질문 중 하나가 Three.js로 게임을 만드는 방법에 관한 것이었습니다. 기초적인 것이긴 해도 부디 이 글에 여러분이 원했던 내용이 있다면 좋겠네요.

-

글을 쓰는 현재를 기준으로, 아마 이 글이 이 시리즈에서 가장 긴 글이 될 것 같습니다. 예제로 쓴 코드가 지나치게 전문적으로 보일 수도 있지만 그건 예제를 만들며 문제가 생길 때마다 이전에 제가 실제로 만들었던 게임의 코드를 가져와서 그렇습니다. 또한 왜 이런 해결책을 썼는지 최대한 적으려고 했으니 길 수밖에 없죠. 물론 만들려는 게임의 규모가 작다면 이런 해결책이 전부 필요 없을 수 있습니다. 하지만 예제로 구현한 것도 굉장히 간단한 게임에 속합니다. 통상적으로 3D 캐릭터가 2D 캐릭터보다 더 복잡하니 처리해줘야 할 것이 많을 수밖에 없죠.

-

팩맨(PacMan)을 2D로 구현한다면 팩맨이 코너를 돌 때 바로 90도 꺾기만 하면 됩니다. 프레임 사이에 따로 처리해줘야 할 것이 없죠. 하지만 3D의 세계에서는 바로 방향을 틀기보다 몇 프레임에 걸쳐 서서히 방향을 트는 게 일반적입니다. 아주 간단한 차이점이지만, 이것 때문에 작업이 훨씬 복잡해집니다.

-

이 글에서 다룰 내용은 Three.js에 관한 것이라고 보기 어렵습니다. 왜냐하면 Three.js는 게임 엔진이 아니기 때문이죠. Three.js는 3D 라이브러리입니다. 3D 요소를 계열화하는 씬 그래프와 3D 요소를 렌더링하도록 도와주는 기능 등을 제공하죠. 하지만 게임과 관련한 기능은 지원하지 않습니다. 충돌(collision), 물리(physics), 입력 시스템, 패스 파인딩(path finding) 등등.. 이런 기능은 직접 만들어야 합니다.

-

결국 이 글의 미완성 게임을 만드는 데 꽤 많은 코드를 썼습니다. 아까 말했듯 제가 코드를 너무 지나치게 짰을 수도 있고, 더 간단한 해결책이 있을 수도 있으나, 저는 글을 마무리한 지금도 충분히 많은 코드를 썼는지, 설명을 빠뜨린 것이 없는지 걱정됩니다.

-

이 글에서 쓴 방법은 대부분 유니티(Unity) 엔진의 영향을 크게 받았습니다. 하지만 유니티를 잘 모른다고 해서 이 글을 읽는 게 어렵진 않을 겁니다. 1000개의 기능이 있다면 그 중 10개 정도 밖에 쓰지 않았거든요.

-

먼저 Three.js 부분부터 시작해봅시다. 게임에 쓸 모델들부터 찾아보죠.

-

opengameart.org 사이트에서 quaternius 작가의 움직이는 기사 모델을 찾았습니다.

-
- -

같은 작가가 만든 작품 중에 움직이는 동물들도 있더군요.

-
- -

이 모델들로 꽤 괜찮은 게임을 만들 수 있을 것 같습니다. 모델들을 불러와보죠.

-

glTF 파일 불러오기에 대해서는 이전에 다뤘었습니다. 동일한 방법을 사용하지만 이번에는 모델이 여러 개이기도 하고, 모델을 전부 불러오기 전에 게임을 시작해선 안 됩니다.

-

이런 경우를 대비해 Three.js는 LoadingManager를 제공합니다. LoadingManager의 인스턴스를 생성해 다른 로더(loader)에 넘겨주기면 되죠. LoadingManageronProgressonLoad 속성에 콜백 함수를 지정하면 되는데, onLoad는 모든 파일을 불러온 뒤 호출하고, onProgress는 각 파일을 불러왔을 때 호출합니다. onProgress를 이용하면 프로그래스 바를 보여줄 수 있죠.

-

glTF 파일 불러오기 예제를 가져와 카메라 절두체(frustum)를 조정하는 코드를 지우고 아래 코드를 추가합니다.

-
const manager = new THREE.LoadingManager();
-manager.onLoad = init;
-const models = {
-  pig:    { url: 'resources/models/animals/Pig.gltf' },
-  cow:    { url: 'resources/models/animals/Cow.gltf' },
-  llama:  { url: 'resources/models/animals/Llama.gltf' },
-  pug:    { url: 'resources/models/animals/Pug.gltf' },
-  sheep:  { url: 'resources/models/animals/Sheep.gltf' },
-  zebra:  { url: 'resources/models/animals/Zebra.gltf' },
-  horse:  { url: 'resources/models/animals/Horse.gltf' },
-  knight: { url: 'resources/models/knight/KnightCharacter.gltf' },
-};
-{
-  const gltfLoader = new GLTFLoader(manager);
-  for (const model of Object.values(models)) {
-    gltfLoader.load(model.url, (gltf) => {
-      model.gltf = gltf;
-    });
-  }
-}
-
-function init() {
-  // 나중에 작성할 예정
-}
-
-

위 코드는 models 객체에 있는 파일을 불러오고, LoadingManager가 파일을 전부 불러왔을 때 init 함수를 호출합니다. models 객체를 전역으로 선언한 건 나중에 GLTFLoader의 콜백을 이용해 각 모델의 정보를 사용할 때 불러온 각 모델에 접근할 수 있도록 하기 위함입니다.

-

모든 모델과 모델의 애니메이션 데이터는 현재 약 6.6MB입니다. 꽤 용량이 크네요. 여러분의 서버가 압축을 지원(이 사이트의 웹 서버가 이 기능을 지원합니다)한다면 용량은 약 1.4MB까지 줄어들 겁니다. 6.6MB와 비교하면 확실히 적은 데이터지만 절대 작은 데이터는 아닙니다. 프로그래스 바를 만들어 사용자에게 얼마나 기다려야 하는지를 표시해준다면 좋겠네요.

-

onProgress에 콜백 함수를 지정해줍시다. 이 콜백 함수는 호출할 때 3개의 매개변수를 받습니다. 각각 마지막에 불러온 파일의 url, 그리고 불러온 파일의 개수, 전체 파일의 개수입니다.

-

프로그래스 바는 HTML로 간단히 구현하도록 하죠.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="loading">
-+    <div>
-+      <div>...loading...</div>
-+      <div class="progress"><div id="progressbar"></div></div>
-+    </div>
-+  </div>
-</body>
-
-

#progressbar를 참조한 뒤 width를 퍼센트(%) 단위로 표시해 현재 진행율을 보여줄 겁니다. 콜백에서 이 스타일만 처리해주면 되겠네요.

-
const manager = new THREE.LoadingManager();
-manager.onLoad = init;
-
-+const progressbarElem = document.querySelector('#progressbar');
-+manager.onProgress = (url, itemsLoaded, itemsTotal) => {
-+  progressbarElem.style.width = `${ itemsLoaded / itemsTotal * 100 | 0 }%`;
-+};
-
-

이미 모든 모델을 불러왔을 때 init 함수를 호출하게 해놓았으니, 여기서 #loading 요소를 숨겨 프로그래스 바를 없앱니다.

-
function init() {
-+  // 프로그래스 바를 숨깁니다.
-+  const loadingElem = document.querySelector('#loading');
-+  loadingElem.style.display = 'none';
-}
-
-

아래는 프로그래스 바를 꾸미기 위한 CSS입니다. #loading은 페이지 전체를 꽉 채우고 자식 요소를 가운데 정렬시킵니다. 그리고 .progress는 프로그래스 바가 들어갈 영역을 정의하죠. 프로그래스 바에 간단한 애니메이션도 넣어줬습니다.

-
#loading {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  text-align: center;
-  font-size: xx-large;
-  font-family: sans-serif;
-}
-#loading>div>div {
-  padding: 2px;
-}
-.progress {
-  width: 50vw;
-  border: 1px solid black;
-}
-#progressbar {
-  width: 0;
-  transition: width ease-out .5s;
-  height: 1em;
-  background-color: #888;
-  background-image: linear-gradient(
-    -45deg,
-    rgba(255, 255, 255, .5) 25%,
-    transparent 25%,
-    transparent 50%,
-    rgba(255, 255, 255, .5) 50%,
-    rgba(255, 255, 255, .5) 75%,
-    transparent 75%,
-    transparent
-  );
-  background-size: 50px 50px;
-  animation: progressanim 2s linear infinite;
-}
-
-@keyframes progressanim {
-  0% {
-    background-position: 50px 50px;
-  }
-  100% {
-    background-position: 0 0;
-  }
-}
-
-

이제 프로그래스 바가 생겼으니 모델을 처리할 차례입니다. 이 모델들에는 애니메이션이 있는데, 이 애니메이션을 제어할 수 없다면 애니메이션이 있는 의미가 없겠죠. Three.js는 기본적으로 애니메이션들을 배열 형태로 저장합니다. 하지만 배열이 아닌 이름 형태로 저장하는 게 나중에 쓰기에 편하니 각 모델에 animation 속성을 만들겠습니다. 물론 각 애니메이션의 이름은 고유한 값이어야 하겠죠.

-
+function prepModelsAndAnimations() {
-+  Object.values(models).forEach(model => {
-+    const animsByName = {};
-+    model.gltf.animations.forEach((clip) => {
-+      animsByName[clip.name] = clip;
-+    });
-+    model.animations = animsByName;
-+  });
-+}
-
-function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-+  prepModelsAndAnimations();
-}
-
-

이제 애니메이션이 들어간 모델을 화면에 띄워봅시다.

-

이전 glTF 파일 예제와 달리 이번에는 각 모델을 하나 이상 배치할 계획입니다. 그러니 파일을 불러온 뒤 바로 장면에 넣는 대신 각 glTF의 씬 그래프(scene), 이 경우에는 움직이는 캐릭터를 복사해야 합니다. 다행히 Three.js에는 SkeletonUtil.clone이라는 함수가 있어 이를 쉽게 구현할 수 있죠. 먼저 해당 모듈을 불러오겠습니다.

-
import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
-+import { SkeletonUtils } from 'three/addons/utils/SkeletonUtils.js';
-
-

그리고 아까 불러왔던 모델을 복사합니다.

-
function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-+  Object.values(models).forEach((model, ndx) => {
-+    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-+    const root = new THREE.Object3D();
-+    root.add(clonedScene);
-+    scene.add(root);
-+    root.position.x = (ndx - 3) * 3;
-+  });
-}
-
-

위 코드에서는 불러온 각 모델의 gltf.scene을 복사해 새로운 Object3D의 자식으로 추가했습니다. 부모를 따로 만든 건 모델의 애니메이션이 모델의 각 요소의 위치값에 영향을 미치기에 코드로 직접 위치값을 수정하기도 어렵고, 제대로 반영도 안 될 것이기 때문입니다.

-

각 모델의 애니메이션을 재생하려면 AnimationMixer를 써야 합니다. AnimationMixer는 하나 이상의 AnimationAction으로 이루어지고, 각 AnimationAction에는 하나의 AnimationClip이 있습니다. AnimationAction에는 여러 액션(action)을 이어서 재생하거나, 다른 애니메이션으로 부드럽게 전환하기 등 다양한 설정이 있죠. 당장은 첫 번째 AnimationClip으로 액션을 만들어봅시다. 설정을 바꾸지 않는다면 해당 애니메이션 클립(clip)을 반복해 재생할 겁니다.

-
+const mixers = [];
-
-function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-  Object.values(models).forEach((model, ndx) => {
-    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-    const root = new THREE.Object3D();
-    root.add(clonedScene);
-    scene.add(root);
-    root.position.x = (ndx - 3) * 3;
-
-+    const mixer = new THREE.AnimationMixer(clonedScene);
-+    const firstClip = Object.values(model.animations)[0];
-+    const action = mixer.clipAction(firstClip);
-+    action.play();
-+    mixers.push(mixer);
-  });
-}
-
-

애니메이션을 시작하기 위해 play 메서드를 호출했습니다. 그리고 생성한 AnimationMixer들을 전부 mixers 배열에 넣었죠. 마지막으로 렌더링 루프에서 각 AnimationMixerAnimationMixer.update 메서드에 바로 직전 프레임과 현재 프레임의 시간값을 넘겨주어야 합니다.

-
+let then = 0;
-function render(now) {
-+  now *= 0.001;  // 초 단위로 변환
-+  const deltaTime = now - then;
-+  then = now;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  for (const mixer of mixers) {
-+    mixer.update(deltaTime);
-+  }
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

이제 각 모델과 모델의 첫 번째 애니메이션이 보일 겁니다.

-

- -

-

모든 애니메이션을 확인할 수 있도록 예제를 수정해봅시다. 애니메이션 클립을 전부 액션으로 만들어 재생할 수 있도록 만들겠습니다.

-
-const mixers = [];
-+const mixerInfos = [];
-
-function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-  Object.values(models).forEach((model, ndx) => {
-    const clonedScene = SkeletonUtils.clone(model.gltf.scene);
-    const root = new THREE.Object3D();
-    root.add(clonedScene);
-    scene.add(root);
-    root.position.x = (ndx - 3) * 3;
-
-    const mixer = new THREE.AnimationMixer(clonedScene);
--    const firstClip = Object.values(model.animations)[0];
--    const action = mixer.clipAction(firstClip);
--    action.play();
--    mixers.push(mixer);
-+    const actions = Object.values(model.animations).map((clip) => {
-+      return mixer.clipAction(clip);
-+    });
-+    const mixerInfo = {
-+      mixer,
-+      actions,
-+      actionNdx: -1,
-+    };
-+    mixerInfos.push(mixerInfo);
-+    playNextAction(mixerInfo);
-  });
-}
-
-+function playNextAction(mixerInfo) {
-+  const { actions, actionNdx } = mixerInfo;
-+  const nextActionNdx = (actionNdx + 1) % actions.length;
-+  mixerInfo.actionNdx = nextActionNdx;
-+  actions.forEach((action, ndx) => {
-+    const enabled = ndx === nextActionNdx;
-+    action.enabled = enabled;
-+    if (enabled) {
-+      action.play();
-+    }
-+  });
-+}
-
-

위 코드에서는 각 모델마다 액션 배열과 AnimationMixer를 객체로 만들어 저장했습니다. 액션 배열은 모델의 각 AnimationClip마다 AnimationAction을 하나씩 생성해 배열로 만든 것이죠. 그리고 하나의 액션을 제외한 나머지 액션의 enabled 속성을 끄는 playNextAction을 호출했습니다.

-

데이터 형식이 바뀌었으니 렌더링 루프의 업데이트 쪽 코드도 수정해야 합니다.

-
-for (const mixer of mixers) {
-+for (const { mixer } of mixerInfos) {
-  mixer.update(deltaTime);
-}
-
-

숫자키 1-8번을 눌러 각 모델의 애니메이션을 선택할 수 있도록 리스너를 지정합니다.

-
window.addEventListener('keydown', (e) => {
-  const mixerInfo = mixerInfos[e.keyCode - 49];
-  if (!mixerInfo) {
-    return;
-  }
-  playNextAction(mixerInfo);
-});
-
-

이제 예제를 클릭한 뒤 숫자키 1-8번을 누르면 각 번호에 해당하는 모델의 애니메이션이 바뀔 겁니다.

-

- -

-

Three.js 관련 내용은 여기까지입니다. 여태까지 다수의 파일을 불러오는 법, 텍스처가 씌워진 모델을 복사하는 법, 해당 모델의 애니메이션을 재생하는 법을 알아봤죠. 실제 게임에서는 AnimationAction 객체로 다양한 동작을 직접 처리해줘야 합니다.

-

자, 이제 게임의 기본 틀을 만들어봅시다.

-

최신 게임을 만들 때는 보통 Entity Component System(ECS)을 많이 사용합니다. Entity Component System에서는 게임의 요소를 여러 개의 컴포넌트(component)로 이루어진 엔티티(entity)라 부르죠. 새로운 엔티티를 생성할 때는 모든 코드를 새로 쓰는 것이 아닌, 미리 만들어 놓은 컴포넌트들을 엮어 생성합니다.

-

예제에서는 엔티티를 GameObject라 부르겠습니다. 이는 단순히 컴포넌트 배열과 THREE.Object3D를 합친 것입니다.

-
function removeArrayElement(array, element) {
-  const ndx = array.indexOf(element);
-  if (ndx >= 0) {
-    array.splice(ndx, 1);
-  }
-}
-
-class GameObject {
-  constructor(parent, name) {
-    this.name = name;
-    this.components = [];
-    this.transform = new THREE.Object3D();
-    parent.add(this.transform);
-  }
-  addComponent(ComponentType, ...args) {
-    const component = new ComponentType(this, ...args);
-    this.components.push(component);
-    return component;
-  }
-  removeComponent(component) {
-    removeArrayElement(this.components, component);
-  }
-  getComponent(ComponentType) {
-    return this.components.find(c => c instanceof ComponentType);
-  }
-  update() {
-    for (const component of this.components) {
-      component.update();
-    }
-  }
-}
-
-

GameObject.update 메서드를 호출하면 각 컴포넌트의 update 메서드를 호출합니다.

-

name 속성은 단순히 디버깅을 위한 것입니다. 콘솔에서 GameObject를 봤을 때 어떤 요소인지 쉽게 확인할 수 있겠죠.

-

생소해 보일 수 있는 것들 몇 가지만 집고 넘어가겠습니다.

-

GameObject.addComponent는 컴포넌트를 생성할 때 사용합니다. GameObject 안에서 컴포넌트를 생성하는 게 최선인지는 모르겠으나, 개인적으로 컴포넌트가 GameObject 밖에 존재하는 건 의미가 없어 보였습니다. 그래서 생성한 컴포넌트를 자동으로 GameObject의 배열에 추가하고, GameObject 자체도 컴포넌트의 constructor에 넘겨줄 수 있으면 편하겠다고 생각했죠. 쉽게 말해 지금은 다음처럼 컴포넌트를 추가하지만,

-
const gameObject = new GameObject(scene, 'foo');
-gameObject.addComponent(TypeOfComponent);
-
-

위와 같은 방식을 선호하지 않는다면 다음처럼 추가할 수도 있습니다.

-
const gameObject = new GameObject(scene, 'foo');
-const component = new TypeOfComponent(gameObject);
-gameObject.addComponent(component);
-
-

첫 번째 코드가 짧고 자동화됐다는 면에서 더 좋을까요, 아니면 기존 형식을 해쳐서 더 별로일까요? 저는 어떻다고 판단하기가 어렵네요.

-

GameObject.getComponent는 컴포넌트의 타입을 이용해 컴포넌트를 찾습니다. 이는 하나의 GameObject가 같은 타입의 컴포넌트를 두 개 이상 사용할 수 없다는 이야기죠. 물론 두 개 이상 사용한다고 에러가 나거나 하진 않겠지만, 별도의 API를 추가하지 않는 한 저 메서드는 항상 같은 타입 중 첫 번째 컴포넌트만을 반환할 겁니다.

-

컴포넌트가 다른 컴포넌트를 찾는 건 흔한 일입니다. 그리고 컴포넌트를 찾을 때는 잘못 참조하는 일이 없도록 타입을 체크해야 하죠. 그냥 각 컴포넌트에 고유한 이름 속성을 주고 그 이름으로 해당 컴포넌트를 찾을 수도 있습니다. 이렇게 하면 같은 타입의 컴포넌트를 여러 개 쓸 수 있으니 확장성 면에서 유리할 겁니다. 하지만 이 방법은 그다지 일관성이 없습니다. 이번에도 어떤 쪽이 더 좋다고 판단하기가 어렵네요.

-

아래는 컴포넌트의 기초 클래스입니다.

-
// 모든 컴포넌트의 기초
-class Component {
-  constructor(gameObject) {
-    this.gameObject = gameObject;
-  }
-  update() {
-  }
-}
-
-

컴포넌트에 기초 클래스가 필요할까요? 자바스크립트는 타입이 느슨한 언어이기에 굳이 기초 클래스를 쓸 필요는 없습니다. 각 컴포넌트의 constructor에서 첫 번째 인자가 GameObject이기만 하면 되죠. 만약 GameObject를 나중에 참조할 필요가 없다면 굳이 저장하지 않아도 될 겁니다. 하지만 저는 왠지 이 형식이 더 좋아 보이네요. 기초 클래스를 두면 부모의 GameObject에 쉽게 접근할 수 있을 뿐만 아니라 다른 컴포넌트를 쉽게 찾을 수 있고, 어떤 차이점이 있는지도 쉽게 알 수 있을 테니까요.

-

GameObject를 다루려면 GameObject를 관리하는 클래스를 만드는 게 좋을 듯합니다. 얼핏 GameObject를 배열 형식으로 갖고 있어도 괜찮지 않나 싶을 수 있으나, 실제로 게임을 플레이할 때는 요소가 추가되기도 하고, 없어지기도 합니다. 예를 들어 총 GameObject는 총을 발사할 때마다 총알 GameObject를 추가할 겁니다. 몬스터 GameObject가 누군가에 의해 죽는다면 해당 GameObject는 사라지겠죠. GameObject를 배열로 저장한다면 십중팔구 다음과 같은 식의 코드를 쓸 겁니다.

-
for (const gameObject of globalArrayOfGameObjects) {
-  gameObject.update();
-}
-
-

위 반복문은 globalArrayOfGameObjects에 GameObject가 추가되거나 제거됐을 경우, 특정 컴포넌트의 update 메서드에서 에러를 던지거나 예상 밖의 동작을 할 수 있습니다.

-

이런 일을 방지하기 위해 안전 장치를 추가해보도록 하죠.

-
class SafeArray {
-  constructor() {
-    this.array = [];
-    this.addQueue = [];
-    this.removeQueue = new Set();
-  }
-  get isEmpty() {
-    return this.addQueue.length + this.array.length > 0;
-  }
-  add(element) {
-    this.addQueue.push(element);
-  }
-  remove(element) {
-    this.removeQueue.add(element);
-  }
-  forEach(fn) {
-    this._addQueued();
-    this._removeQueued();
-    for (const element of this.array) {
-      if (this.removeQueue.has(element)) {
-        continue;
-      }
-      fn(element);
-    }
-    this._removeQueued();
-  }
-  _addQueued() {
-    if (this.addQueue.length) {
-      this.array.splice(this.array.length, 0, ...this.addQueue);
-      this.addQueue = [];
-    }
-  }
-  _removeQueued() {
-    if (this.removeQueue.size) {
-      this.array = this.array.filter(element => !this.removeQueue.has(element));
-      this.removeQueue.clear();
-    }
-  }
-}
-
-

위 클래스는 SafeArray의 요소를 더하거나 제거할 수 있도록 해줍니다. 원본 배열의 반복되는 동안 원본 배열을 변경하지 않는다는 게 차이점이죠. 대신 반복 중간에 추가된 요소는 addQueue에, 제거된 요소는 removeQueue에 들어간 뒤, 반복문이 돌아가지 않을 때 원본 배열에 제거/추가됩니다.

-

아래는 위 클래스를 이용한 GameObject의 관리 클래스입니다.

-
class GameObjectManager {
-  constructor() {
-    this.gameObjects = new SafeArray();
-  }
-  createGameObject(parent, name) {
-    const gameObject = new GameObject(parent, name);
-    this.gameObjects.add(gameObject);
-    return gameObject;
-  }
-  removeGameObject(gameObject) {
-    this.gameObjects.remove(gameObject);
-  }
-  update() {
-    this.gameObjects.forEach(gameObject => gameObject.update());
-  }
-}
-
-

여태까지 만든 요소로 첫 컴포넌트를 만들어봅시다. 이 컴포넌트는 아까 만들었던 것과 같은 Three.js glTF 객체를 관리할 겁니다. 간단히 애니메이션의 이름을 받아 해당 애니메이션을 재생하는 setAnimation 메서드만 새로 만들도록 하겠습니다.

-
class SkinInstance extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-    this.model = model;
-    this.animRoot = SkeletonUtils.clone(this.model.gltf.scene);
-    this.mixer = new THREE.AnimationMixer(this.animRoot);
-    gameObject.transform.add(this.animRoot);
-    this.actions = {};
-  }
-  setAnimation(animName) {
-    const clip = this.model.animations[animName];
-    // 모든 액션을 끕니다.
-    for (const action of Object.values(this.actions)) {
-      action.enabled = false;
-    }
-    // 해당 클립에 해당하는 액션을 생성 또는 가져옵니다.
-    const action = this.mixer.clipAction(clip);
-    action.enabled = true;
-    action.reset();
-    action.play();
-    this.actions[animName] = action;
-  }
-  update() {
-    this.mixer.update(globals.deltaTime);
-  }
-}
-
-

이 클래스는 아까 했던 것처럼 불러온 씬 그래프를 복사하고, AnimationMixer를 만듭니다. 클래스의 setAnimation 메서드는 해당 클립에 대한 액션이 존재하지 않는다면 새로 생성하고, 다른 액션을 전부 끄는 역할을 합니다.

-

이 코드는 globals.deltaTime을 사용합니다. 이 전역 객체도 만들어야겠죠.

-
const globals = {
-  time: 0,
-  deltaTime: 0,
-};
-
-

그리고 렌더링 루프에서 전역 객체를 업데이트하도록 합니다.

-
let then = 0;
-function render(now) {
-  // 초 단위로 변환
-  globals.time = now * 0.001;
-  // 시간값이 너무 크지 않도록 제한합니다.
-  globals.deltaTime = Math.min(globals.time - then, 1 / 20);
-  then = globals.time;
-
-

위 코드에서는 시간값의 범위가 1/20초를 넘지 않도록 했습니다. 이는 사용자가 탭을 숨기거나 했을 경우 시간값이 너무 커지지 않게 하기 위한 것이죠. 만약 이렇게 제한을 두지 않는다면 사용자가 탭을 몇 초, 또는 몇 분 숨겼다가 다시 탭을 열었을 때 프레임 간 시간값이 너무 커질 테고, 아래와 같이 시간으로 속력을 계산하는 경우 캐릭터가 순간이동하는 것처럼 보일 수 있습니다.

-
position += velocity * deltaTime;
-
-

deltaTime의 최댓값을 설정하면 이런 문제를 막을 수 있죠.

-

이제 플레이어 컴포넌트를 만들어봅시다.

-
class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-    this.skinInstance = gameObject.addComponent(SkinInstance, model);
-    this.skinInstance.setAnimation('Run');
-  }
-}
-
-

플레이어 컴포넌트는 초기화 시에 'Run'을 인자로 setAnimation을 호출합니다. 개인적으로 미리 어떤 애니메이션이 있는지 보려고 이전 예제를 수정해 애니메이션의 이름을 출력하도록 했죠.

-
function prepModelsAndAnimations() {
-  Object.values(models).forEach(model => {
-+    console.log('------->:', model.url);
-    const animsByName = {};
-    model.gltf.animations.forEach((clip) => {
-      animsByName[clip.name] = clip;
-+      console.log('  ', clip.name);
-    });
-    model.animations = animsByName;
-  });
-}
-
-

아래는 실제로 자바스크립트 개발자 콘솔에 출력된 결과입니다.

-
 ------->:  resources/models/animals/Pig.gltf
-    Idle
-    Death
-    WalkSlow
-    Jump
-    Walk
- ------->:  resources/models/animals/Cow.gltf
-    Walk
-    Jump
-    WalkSlow
-    Death
-    Idle
- ------->:  resources/models/animals/Llama.gltf
-    Jump
-    Idle
-    Walk
-    Death
-    WalkSlow
- ------->:  resources/models/animals/Pug.gltf
-    Jump
-    Walk
-    Idle
-    WalkSlow
-    Death
- ------->:  resources/models/animals/Sheep.gltf
-    WalkSlow
-    Death
-    Jump
-    Walk
-    Idle
- ------->:  resources/models/animals/Zebra.gltf
-    Jump
-    Walk
-    Death
-    WalkSlow
-    Idle
- ------->:  resources/models/animals/Horse.gltf
-    Jump
-    WalkSlow
-    Death
-    Walk
-    Idle
- ------->:  resources/models/knight/KnightCharacter.gltf
-    Run_swordRight
-    Run
-    Idle_swordLeft
-    Roll_sword
-    Idle
-    Run_swordAttack
-

운 좋게도 동물들의 애니메이션 이름이 전부 똑같네요. 나중에 편할 듯합니다. 뭐, 그건 나중 얘기고, 지금은 플레이어의 애니메이션 중 Run만 신경씁시다.

-

이제 만든 컴포넌트를 써 보겠습니다. 먼저 init 함수를 약간 수정합니다. init 함수는 GameObject를 만들고 거기에 Player 컴포넌트를 추가하는 역할을 할 겁니다.

-
const globals = {
-  time: 0,
-  deltaTime: 0,
-};
-+const gameObjectManager = new GameObjectManager();
-
-function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-+  {
-+    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-+    gameObject.addComponent(Player);
-+  }
-}
-
-

렌더링 루프에서 gameObjectManager.update를 호출하도록 합니다.

-
let then = 0;
-function render(now) {
-  // 초 단위로 변환
-  globals.time = now * 0.001;
-  // 시간값이 너무 크지 않도록 제한합니다.
-  globals.deltaTime = Math.min(globals.time - then, 1 / 20);
-  then = globals.time;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
--  for (const { mixer } of mixerInfos) {
--    mixer.update(deltaTime);
--  }
-+  gameObjectManager.update();
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

예제를 실행하면 플레이어 하나만 보일 겁니다.

-

- -

-

단순히 Entity Component System을 구현하는 데만 너무 많은 코드를 쓴 게 아닌가 싶지만, 이 정도가 대부분의 게임이 갖춰야할 기본입니다.

-

이제 사용자 입력 시스템을 추가해봅시다. 단순히 키보드 이벤트에 직접 코드를 작성하기보다 클래스를 만들어 코드의 다른 부분에서도 왼쪽, 오른쪽을 확인할 수 있도록 하겠습니다. 이러면 왼쪽, 오른쪽 등 다양한 키를 다양한 방법으로 지정할 수 있겠죠. 먼저 키보드 이벤트부터 지정합시다.

-
/**
- * 키 또는 버튼의 상태를 추적합니다.
- *
- * 왼쪽 방향키가 눌렸는지 확인하려면
- *
- *     inputManager.keys.left.down
- *
- * 을 확인하고, 현재 프레임에서 왼쪽 키를 눌렀는지 확인하려면
- *
- *     inputManager.keys.left.justPressed
- *
- * 를 확인하면 됩니다.
- *
- * 현재 등록된 키는 'left', 'right', 'a', 'b', 'up', 'down' 입니다.
- **/
-class InputManager {
-  constructor() {
-    this.keys = {};
-    const keyMap = new Map();
-
-    const setKey = (keyName, pressed) => {
-      const keyState = this.keys[keyName];
-      keyState.justPressed = pressed && !keyState.down;
-      keyState.down = pressed;
-    };
-
-    const addKey = (keyCode, name) => {
-      this.keys[name] = { down: false, justPressed: false };
-      keyMap.set(keyCode, name);
-    };
-
-    const setKeyFromKeyCode = (keyCode, pressed) => {
-      const keyName = keyMap.get(keyCode);
-      if (!keyName) {
-        return;
-      }
-      setKey(keyName, pressed);
-    };
-
-    addKey(37, 'left');
-    addKey(39, 'right');
-    addKey(38, 'up');
-    addKey(40, 'down');
-    addKey(90, 'a');
-    addKey(88, 'b');
-
-    window.addEventListener('keydown', (e) => {
-      setKeyFromKeyCode(e.keyCode, true);
-    });
-    window.addEventListener('keyup', (e) => {
-      setKeyFromKeyCode(e.keyCode, false);
-    });
-  }
-  update() {
-    for (const keyState of Object.values(this.keys)) {
-      if (keyState.justPressed) {
-        keyState.justPressed = false;
-      }
-    }
-  }
-}
-
-

위 코드는 키가 눌렸는지, 뗐는지를 추적합니다. 특정 키를 눌렀는지 확인하려면 예를 들어 inputManager.keys.left.down을 체크하면 되고, 해당 객체에 justPressed를 체크하면 사용자가 해당 프레임에서 키를 눌렀는지 확인할 수 있습니다. 예를 들어 점프를 구현할 경우 유저가 키를 누르고 있는지를 추적할 이유는 없겠죠. 단순히 해당 프레임에서 키를 눌렀는지만 확인하면 될 겁니다.

-

이제 InputManager의 인스턴스를 생성합니다.

-
const globals = {
-  time: 0,
-  deltaTime: 0,
-};
-const gameObjectManager = new GameObjectManager();
-+const inputManager = new InputManager();
-
-

그리고 렌더링 루프에서 update 메서드를 호출하도록 합니다.

-
function render(now) {
-
-  ...
-
-  gameObjectManager.update();
-+  inputManager.update();
-
-  ...
-}
-
-

gameObjectManager.update 전에 이 메서드를 호출하면 justPressed가 항상 false일 테니 gameObjectManager.update 뒤에 메서드를 호출하도록 했습니다.

-

이제 Player 컴포넌트에 사용자 입력을 추가해봅시다.

-
+const kForward = new THREE.Vector3(0, 0, 1);
-const globals = {
-  time: 0,
-  deltaTime: 0,
-+  moveSpeed: 16,
-};
-
-class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-    this.skinInstance = gameObject.addComponent(SkinInstance, model);
-    this.skinInstance.setAnimation('Run');
-+    this.turnSpeed = globals.moveSpeed / 4;
-  }
-+  update() {
-+    const { deltaTime, moveSpeed } = globals;
-+    const { transform } = this.gameObject;
-+    const delta = (inputManager.keys.left.down  ?  1 : 0) +
-+                  (inputManager.keys.right.down ? -1 : 0);
-+    transform.rotation.y += this.turnSpeed * delta * deltaTime;
-+    transform.translateOnAxis(kForward, moveSpeed * deltaTime);
-+  }
-}
-
-

위 코드에서는 플레이어를 앞으로 움직이기 위해 Object3D.transformOnAxis를 사용했습니다. Object3D.transformOnAxis는 지역 공간을 기준으로 하기에 해당 객체가 장면의 루트(root) 요소에 속할 때만 정상적으로 작동합니다. 1

-

또한 전역 객체에 moveSpeed를 추가했고 이를 turnSpeed의 기준으로 삼았습니다. 이는 캐릭터가 목표를 향해 상대적으로 빠르게 돌도록 만든 것으로, 이 turnSpeed의 값이 너무 작다면 캐릭터는 목표 주위를 빙빙 돌기만 하고 절대 목표에 닿지는 못할 겁니다. 물론 위 값은 어떤 수학적 공식을 사용한 것이 아닙니다. 그냥 대충 때려 넣은 것이죠.

-

이대로도 예제는 잘 작동할 테지만 플레이어가 화면을 벗어나면 캐릭터가 어디 있는지 찾기가 어려울 겁니다. 일단 화면에서 벗어난 뒤 일정 시간이 지나면 플레이어를 다시 중점으로 순간이동시키기로 합시다. Three.js의 Frustum 클래스를 이용하면 특정 점이 카메라의 절두체(frustum) 안에 있는지 알 수 있습니다.

-

먼저 카메라로 절두체를 만들어야 합니다. 플레이어 컴포넌트에서 이걸 처리할 수도 있지만, 다른 요소도 이 방법을 써야 할 수 있으니 카메라의 절두체를 관리하는 새로운 컴포넌트를 만들겠습니다.

-
class CameraInfo extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    this.projScreenMatrix = new THREE.Matrix4();
-    this.frustum = new THREE.Frustum();
-  }
-  update() {
-    const { camera } = globals;
-    this.projScreenMatrix.multiplyMatrices(
-        camera.projectionMatrix,
-        camera.matrixWorldInverse);
-    this.frustum.setFromProjectionMatrix(this.projScreenMatrix);
-  }
-}
-
-

다음으로 init 함수에서 방금 만든 컴포넌트로 새로운 GameObject를 추가합니다.

-
function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-
-+  {
-+    const gameObject = gameObjectManager.createGameObject(camera, 'camera');
-+    globals.cameraInfo = gameObject.addComponent(CameraInfo);
-+  }
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-    gameObject.addComponent(Player);
-  }
-}
-
-

Player 컴포넌트에 방금 만든 GameObject를 사용하는 코드를 추가합니다.

-
class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-    this.skinInstance = gameObject.addComponent(SkinInstance, model);
-    this.skinInstance.setAnimation('Run');
-    this.turnSpeed = globals.moveSpeed / 4;
-+    this.offscreenTimer = 0;
-+    this.maxTimeOffScreen = 3;
-  }
-  update() {
--    const { deltaTime, moveSpeed } = globals;
-+    const { deltaTime, moveSpeed, cameraInfo } = globals;
-    const { transform } = this.gameObject;
-    const delta = (inputManager.keys.left.down  ?  1 : 0) +
-                  (inputManager.keys.right.down ? -1 : 0);
-    transform.rotation.y += this.turnSpeed * delta * deltaTime;
-    transform.translateOnAxis(kForward, moveSpeed * deltaTime);
-
-+    const { frustum } = cameraInfo;
-+    if (frustum.containsPoint(transform.position)) {
-+      this.offscreenTimer = 0;
-+    } else {
-+      this.offscreenTimer += deltaTime;
-+      if (this.offscreenTimer >= this.maxTimeOffScreen) {
-+        transform.position.set(0, 0, 0);
-+      }
-+    }
-  }
-}
-
-

예제를 실행하기 전에 모바일 환경을 위한 터치 인터페이스를 추가하겠습니다. 먼저 터치 이벤트를 받을 HTML 요소를 만듭니다.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui">
-+    <div id="left"><img src="../resources/images/left.svg"></div>
-+    <div style="flex: 0 0 40px;"></div>
-+    <div id="right"><img src="../resources/images/right.svg"></div>
-+  </div>
-  <div id="loading">
-    <div>
-      <div>...loading...</div>
-      <div class="progress"><div id="progressbar"></div></div>
-    </div>
-  </div>
-</body>
-
-

버튼의 스타일도 작성합니다.

-
#ui {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: flex;
-  justify-items: center;
-  align-content: stretch;
-}
-#ui>div {
-  display: flex;
-  align-items: flex-end;
-  flex: 1 1 auto;
-}
-.bright {
-  filter: brightness(2);
-}
-#left {
-  justify-content: flex-end;
-}
-#right {
-  justify-content: flex-start;
-}
-#ui img {
-  padding: 10px;
-  width: 80px;
-  height: 80px;
-  display: block;
-}
-
-

제가 사용한 방법은 하나의 div 요소, #ui로 화면 전체를 채우고, 해당 요소의 자식으로 화면의 대략 반을 차지하는 #left#right를 각각 양쪽에, 가운데에는 40px짜리 구분선을 넣어 화면 전체가 이벤트를 감지하도록 한 것입니다. 이러면 사용자가 왼쪽 화살표를 누른 뒤 왼쪽에서 오른쪽으로 손가락을 움직였을 때 InputManagerkeys.leftkeys.right를 업데이트할 수 있겠죠. 굳이 작은 화살표를 누르느라 고생하지 않아도 되니 이 편이 훨씬 나을 겁니다.

-
class InputManager {
-  constructor() {
-    this.keys = {};
-    const keyMap = new Map();
-
-    const setKey = (keyName, pressed) => {
-      const keyState = this.keys[keyName];
-      keyState.justPressed = pressed && !keyState.down;
-      keyState.down = pressed;
-    };
-
-    const addKey = (keyCode, name) => {
-      this.keys[name] = { down: false, justPressed: false };
-      keyMap.set(keyCode, name);
-    };
-
-    const setKeyFromKeyCode = (keyCode, pressed) => {
-      const keyName = keyMap.get(keyCode);
-      if (!keyName) {
-        return;
-      }
-      setKey(keyName, pressed);
-    };
-
-    addKey(37, 'left');
-    addKey(39, 'right');
-    addKey(38, 'up');
-    addKey(40, 'down');
-    addKey(90, 'a');
-    addKey(88, 'b');
-
-    window.addEventListener('keydown', (e) => {
-      setKeyFromKeyCode(e.keyCode, true);
-    });
-    window.addEventListener('keyup', (e) => {
-      setKeyFromKeyCode(e.keyCode, false);
-    });
-
-+    const sides = [
-+      { elem: document.querySelector('#left'),  key: 'left'  },
-+      { elem: document.querySelector('#right'), key: 'right' },
-+    ];
-+
-+    const clearKeys = () => {
-+      for (const {key} of sides) {
-+          setKey(key, false);
-+      }
-+    };
-+
-+    const handleMouseMove = (e) => {
-+      e.preventDefault();
-+      // this is needed because we call preventDefault();
-+      // we also gave the canvas a tabindex so it can
-+      // become the focus
-+      canvas.focus();
-+      window.addEventListener('pointermove', handleMouseMove);
-+      window.addEventListener('pointerup', handleMouseUp);
-+
-+      for (const {elem, key} of sides) {
-+        let pressed = false;
-+        const rect = elem.getBoundingClientRect();
-+        const x = e.clientX;
-+        const y = e.clientY;
-+        const inRect = x >= rect.left && x < rect.right &&
-+                       y >= rect.top && y < rect.bottom;
-+        if (inRect) {
-+          pressed = true;
-+        }
-+        setKey(key, pressed);
-+      }
-+    };
-+
-+    function handleMouseUp() {
-+      clearKeys();
-+      window.removeEventListener('pointermove', handleMouseMove, {passive: false});
-+      window.removeEventListener('pointerup', handleMouseUp);
-+    }
-+
-+    const uiElem = document.querySelector('#ui');
-+    uiElem.addEventListener('pointerdown', handleMouseMove, {passive: false});
-+
-+    uiElem.addEventListener('touchstart', (e) => {
-+      // prevent scrolling
-+      e.preventDefault();
-+    }, {passive: false});
-  }
-  update() {
-    for (const keyState of Object.values(this.keys)) {
-      if (keyState.justPressed) {
-        keyState.justPressed = false;
-      }
-    }
-  }
-}
-
-

이제 화살표 키나 화면을 터치해 캐릭터를 움직일 수 있을 겁니다.

-

- -

-

물론 플레이어가 화면 밖으로 나갔을 때 카메라를 움직이거나, "화면 밖 = 죽음"이라는 설정을 넣을 수도 있습니다. 하지만 이것까지 다룬다면 안 그래도 긴 글이 더 길어질 테니 이 방법으로 만족하겠습니다.

-

이제 동물을 추가해봅시다. Player와 비슷한 방법으로 Animal 컴포넌트를 만듭니다.

-
class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-    const skinInstance = gameObject.addComponent(SkinInstance, model);
-    skinInstance.mixer.timeScale = globals.moveSpeed / 4;
-    skinInstance.setAnimation('Idle');
-  }
-}
-
-

위 코드에서는 AnimationMixer.timeScale을 설정해 애니메이션 속도가 이동 속도에 비례하도록 만들었습니다. 이러면 이동 속도와 같이 애니메이션 속도가 빨라지고 느려지겠죠.

-

다음으로 init 함수에서 각 동물을 배치합니다.

-
function init() {
-  // 프로그래스 바를 숨깁니다.
-  const loadingElem = document.querySelector('#loading');
-  loadingElem.style.display = 'none';
-
-  prepModelsAndAnimations();
-  {
-    const gameObject = gameObjectManager.createGameObject(camera, 'camera');
-    globals.cameraInfo = gameObject.addComponent(CameraInfo);
-  }
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-    globals.player = gameObject.addComponent(Player);
-    globals.congaLine = [gameObject];
-  }
-
-+  const animalModelNames = [
-+    'pig',
-+    'cow',
-+    'llama',
-+    'pug',
-+    'sheep',
-+    'zebra',
-+    'horse',
-+  ];
-+  animalModelNames.forEach((name, ndx) => {
-+    const gameObject = gameObjectManager.createGameObject(scene, name);
-+    gameObject.addComponent(Animal, models[name]);
-+    gameObject.transform.position.x = (ndx + 1) * 5;
-+  });
-}
-
-

동물들을 배치하고 끝내면 심심하니 뭔가를 추가해야겠네요.

-

동물이 플레이어를 따라 기차놀이*를 하게 해봅시다. 플레이어가 동물에 가까이 갔을 때만 기차에 합류하도록 하겠습니다. 이를 구현하려면 아래와 같은 모션(상태, state)이 필요할 겁니다.

-

※ 원문은 "conga line"입니다. 기차놀이와 유사한 꼬리잇기 놀이로, 우리에게 더 익숙한 "기차놀이"로 의역했습니다. 역주.

-
    -
  • 가만히 서 있는 모션(Idle):

    -

    플레이어가 가까워지기 전까지의 모션입니다.

    -
  • -
  • 기차의 끝에 갈 때까지 기다리는 모션(Wait for End of Line):

    -

    플레이어가 동물과 닿더라도 기차의 끝에 합류해야 하므로 그 전까지 기다리는 모션입니다.

    -
  • -
  • 따라붙기(Go to Last):

    -

    자신이 따라갈 대상이 있던 위치로 이동함과 동시에 따라갈 대상이 어디 있는지 기록합니다.

    -
  • -
  • 따라가기(Follow):

    -

    자신이 따라가는 대상의 현재 위치를 기록함과 동시에 대상이 있었던 위치로 이동합니다.

    -
  • -
-

이런 상태를 다룰 방법은 아주 다양합니다. 보통은 유한 상태 기계(Finite State Machine)와 이런 상태를 다룰 헬퍼 클래스를 사용하죠.

-
class FiniteStateMachine {
-  constructor(states, initialState) {
-    this.states = states;
-    this.transition(initialState);
-  }
-  get state() {
-    return this.currentState;
-  }
-  transition(state) {
-    const oldState = this.states[this.currentState];
-    if (oldState && oldState.exit) {
-      oldState.exit.call(this);
-    }
-    this.currentState = state;
-    const newState = this.states[state];
-    if (newState.enter) {
-      newState.enter.call(this);
-    }
-  }
-  update() {
-    const state = this.states[this.currentState];
-    if (state.update) {
-      state.update.call(this);
-    }
-  }
-}
-
-

위 클래스는 앞서 말한 헬퍼 클래스를 간단히 구현한 것입니다. 클래스는 생성 시 상태들의 객체를 받고, 각 상태에는 enter, update, exit이라는 메서드가 있습니다. 상태를 바꾸려면 FiniteStateMachine.transition을 호출할 때 새로운 이름을 넘겨주면 되죠. 만약 현재 상태에 exit 메서드가 있다면 해당 메서드를 호출합니다. 그리고 새로운 상태에 enter 메서드가 있을 경우 enter 메서드를 호출합니다. 마지막으로 매 프레임마다 FiniteStateMachine.update를 호출하면 각 상태의 update 메서드를 호출합니다.

-

이제 이 클래스를 활용해 동물들의 상태를 바꿔봅시다.

-
// 매개변수 obj1과 obj2이 가깝다면 true를 반환합니다.
-function isClose(obj1, obj1Radius, obj2, obj2Radius) {
-  const minDist = obj1Radius + obj2Radius;
-  const dist = obj1.position.distanceTo(obj2.position);
-  return dist < minDist;
-}
-
-// v 의 값이 -min과 +min 사이가 되도록 합니다.
-function minMagnitude(v, min) {
-  return Math.abs(v) > min
-      ? min * Math.sign(v)
-      : v;
-}
-
-const aimTowardAndGetDistance = function() {
-  const delta = new THREE.Vector3();
-
-  return function aimTowardAndGetDistance(source, targetPos, maxTurn) {
-    delta.subVectors(targetPos, source.position);
-    // 바라볼 방향을 계산합니다.
-    const targetRot = Math.atan2(delta.x, delta.z) + Math.PI * 1.5;
-    // 더 가까운 방향으로 회전합니다.
-    const deltaRot = (targetRot - source.rotation.y + Math.PI * 1.5) % (Math.PI * 2) - Math.PI;
-    // maxTurn보다 빠른 속도로 돌지 않도록 합니다.
-    const deltaRotation = minMagnitude(deltaRot, maxTurn);
-    // rotation 값을 0에서 Math.PI * 2 사이로 유지합니다.
-    source.rotation.y = THREE.MathUtils.euclideanModulo(
-        source.rotation.y + deltaRotation, Math.PI * 2);
-    // 목표까지의 거리를 반환합니다.
-    return delta.length();
-  };
-}();
-
-class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-+    const hitRadius = model.size / 2;
-    const skinInstance = gameObject.addComponent(SkinInstance, model);
-    skinInstance.mixer.timeScale = globals.moveSpeed / 4;
-+    const transform = gameObject.transform;
-+    const playerTransform = globals.player.gameObject.transform;
-+    const maxTurnSpeed = Math.PI * (globals.moveSpeed / 4);
-+    const targetHistory = [];
-+    let targetNdx = 0;
-+
-+    function addHistory() {
-+      const targetGO = globals.congaLine[targetNdx];
-+      const newTargetPos = new THREE.Vector3();
-+      newTargetPos.copy(targetGO.transform.position);
-+      targetHistory.push(newTargetPos);
-+    }
-+
-+    this.fsm = new FiniteStateMachine({
-+      idle: {
-+        enter: () => {
-+          skinInstance.setAnimation('Idle');
-+        },
-+        update: () => {
-+          // 플레이어가 근처에 있는지 확인합니다.
-+          if (isClose(transform, hitRadius, playerTransform, globals.playerRadius)) {
-+            this.fsm.transition('waitForEnd');
-+          }
-+        },
-+      },
-+      waitForEnd: {
-+        enter: () => {
-+          skinInstance.setAnimation('Jump');
-+        },
-+        update: () => {
-+          // 기차의 가장 마지막에 있는 gameObject를 가져옵니다.
-+          const lastGO = globals.congaLine[globals.congaLine.length - 1];
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          const targetPos = lastGO.transform.position;
-+          aimTowardAndGetDistance(transform, targetPos, deltaTurnSpeed);
-+          // 기차의 마지막에 있는 요소가 근처에 있는지 확인합니다.
-+          if (isClose(transform, hitRadius, lastGO.transform, globals.playerRadius)) {
-+            this.fsm.transition('goToLast');
-+          }
-+        },
-+      },
-+      goToLast: {
-+        enter: () => {
-+          // 따라갈 대상을 기록합니다. remember who we're following
-+          targetNdx = globals.congaLine.length - 1;
-+          // 기차의 마지막에 스스로를 추가합니다.
-+          globals.congaLine.push(gameObject);
-+          skinInstance.setAnimation('Walk');
-+        },
-+        update: () => {
-+          addHistory();
-+          // 기록된 위치 중 가장 나중 위치로 이동합니다.
-+          const targetPos = targetHistory[0];
-+          const maxVelocity = globals.moveSpeed * globals.deltaTime;
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          const distance = aimTowardAndGetDistance(transform, targetPos, deltaTurnSpeed);
-+          const velocity = distance;
-+          transform.translateOnAxis(kForward, Math.min(velocity, maxVelocity));
-+          if (distance <= maxVelocity) {
-+            this.fsm.transition('follow');
-+          }
-+        },
-+      },
-+      follow: {
-+        update: () => {
-+          addHistory();
-+          // 가장 오래된 위치값을 지우고 자기 자신의 위치값을 추가합니다.
-+          const targetPos = targetHistory.shift();
-+          transform.position.copy(targetPos);
-+          const deltaTurnSpeed = maxTurnSpeed * globals.deltaTime;
-+          aimTowardAndGetDistance(transform, targetHistory[0], deltaTurnSpeed);
-+        },
-+      },
-+    }, 'idle');
-+  }
-+  update() {
-+    this.fsm.update();
-+  }
-}
-
-

한 번에 너무 많은 코드를 보여준 듯하지만 위 코드는 방금 언급한 역할을 합니다. 각 상태에 대한 코드를 보고 어떤 식으로 작동하는지 분석해보기 바랍니다.

-

여기에 몇 가지 요소를 추가해야 합니다. 플레이어가 자기 자신을 전역 객체(globals)에 추가해 다른 동물이 자신의 위치를 추적하도록 해야 하고, 또 기차의 머리를 플레이어의 GameObject로 지정해야 합니다.

-
function init() {
-
-  ...
-
-  {
-    const gameObject = gameObjectManager.createGameObject(scene, 'player');
-+    globals.player = gameObject.addComponent(Player);
-+    globals.congaLine = [gameObject];
-  }
-
-}
-
-

각 모델의 크기도 계산해야 합니다.

-
function prepModelsAndAnimations() {
-+  const box = new THREE.Box3();
-+  const size = new THREE.Vector3();
-  Object.values(models).forEach(model => {
-+    box.setFromObject(model.gltf.scene);
-+    box.getSize(size);
-+    model.size = size.length();
-    const animsByName = {};
-    model.gltf.animations.forEach((clip) => {
-      animsByName[clip.name] = clip;
-      // 이런 부분은 .blend 파일에서 수정하는 게 좋습니다.
-      if (clip.name === 'Walk') {
-        clip.duration /= 2;
-      }
-    });
-    model.animations = animsByName;
-  });
-}
-
-

그리고 플레이어가 자기 자신의 크기를 기록하도록 합니다.

-
class Player extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const model = models.knight;
-+    globals.playerRadius = model.size / 2;
-
-

이제 와 생각해보니 플레이어가 아니라 기차의 머리를 바라보게 하는 편이 더 나았겠네요. 이건 나중에 돌아와 고치도록 하겠습니다.

-

예제를 처음 만들었을 때는 동물들이 모두 같은 크기의 경계 원(radius)을 썼지만, 이렇게 하고 보니 말과 퍼그(강아지)의 크기가 같은 게 말이 안 된다는 생각이 들었습니다. 그래서 각 모델의 크기에 따라 경계 원을 따로 지정했죠. 그리고 상태를 보여주면 좋겠다는 생각이 들어 상태를 보여 줄 StateDisplayHelper 컴포넌트를 추가했습니다.

-

또한 PolarGridHelper를 써 각 캐릭터의 경계 원이 보이도록 했고, HTML 요소를 3D로 정렬하기에서 썼던 방법으로 각 캐릭터의 상태를 HTML로 보여주도록 했습니다.

-

먼저 각 요소를 담을 HTML을 추가합니다.

-
<body>
-  <canvas id="c"></canvas>
-  <div id="ui">
-    <div id="left"><img src="../resources/images/left.svg"></div>
-    <div style="flex: 0 0 40px;"></div>
-    <div id="right"><img src="../resources/images/right.svg"></div>
-  </div>
-  <div id="loading">
-    <div>
-      <div>...loading...</div>
-      <div class="progress"><div id="progressbar"></div></div>
-    </div>
-  </div>
-+  <div id="labels"></div>
-</body>
-
-

CSS도 작성합니다.

-
#labels {
-  position: absolute;  /* 기준 요소 위로 올라가도록 합니다. */
-  left: 0;             /* 기준 요소 왼쪽 위로 정렬합니다. */
-  top: 0;
-  color: white;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  pointer-events: none;
-}
-#labels>div {
-  position: absolute;  /* 기준 요소를 기준으로 합니다. */
-  left: 0;             /* 기준 요소의 왼쪽 위로 정렬합니다. */
-  top: 0;
-  font-size: large;
-  font-family: monospace;
-  user-select: none;   /* 텍스트를 선택할 수 없도록 합니다. */
-  text-shadow:         /* 글자에 검은 윤곽선을 넣습니다. */
-    -1px -1px 0 #000,
-     0   -1px 0 #000,
-     1px -1px 0 #000,
-     1px  0   0 #000,
-     1px  1px 0 #000,
-     0    1px 0 #000,
-    -1px  1px 0 #000,
-    -1px  0   0 #000;
-}
-
-

아래는 StateDisplayHelper 컴포넌트입니다.

-
const labelContainerElem = document.querySelector('#labels');
-
-class StateDisplayHelper extends Component {
-  constructor(gameObject, size) {
-    super(gameObject);
-    this.elem = document.createElement('div');
-    labelContainerElem.appendChild(this.elem);
-    this.pos = new THREE.Vector3();
-
-    this.helper = new THREE.PolarGridHelper(size / 2, 1, 1, 16);
-    gameObject.transform.add(this.helper);
-  }
-  setState(s) {
-    this.elem.textContent = s;
-  }
-  setColor(cssColor) {
-    this.elem.style.color = cssColor;
-    this.helper.material.color.set(cssColor);
-  }
-  update() {
-    const { pos } = this;
-    const { transform } = this.gameObject;
-    const { canvas } = globals;
-    pos.copy(transform.position);
-
-    /**
-     * 해당 위치값을 정규화하면 x와 y 값은 -1에서 +1 사이의 값이 됩니다.
-     * x = -1 이면 왼쪽, y = -1 이면 오른쪽이죠.
-     **/
-    pos.project(globals.camera);
-
-    // 정규화한 위치값을 CSS 위치값으로 변환합니다.
-    const x = (pos.x *  .5 + .5) * canvas.clientWidth;
-    const y = (pos.y * -.5 + .5) * canvas.clientHeight;
-
-    // HTML 요소를 해당 위치로 옮깁니다.
-    this.elem.style.transform = `translate(-50%, -50%) translate(${ x }px, ${ y }px)`;
-  }
-}
-
-

동물 컴포넌트를 생성할 때 위 컴포넌트를 추가하도록 합니다.

-
class Animal extends Component {
-  constructor(gameObject, model) {
-    super(gameObject);
-+    this.helper = gameObject.addComponent(StateDisplayHelper, model.size);
-
-     ...
-
-  }
-  update() {
-    this.fsm.update();
-+    const dir = THREE.MathUtils.radToDeg(this.gameObject.transform.rotation.y);
-+    this.helper.setState(`${ this.fsm.state }:${ dir.toFixed(0) }`);
-  }
-}
-
-

추가로 lil-gui를 이용해 위 디버깅 요소들를 켜고 끌 수 있도록 합니다.

-
import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
-import { SkeletonUtils } from 'three/addons/utils/SkeletonUtils.js';
-+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-
+const gui = new GUI();
-+gui.add(globals, 'debug').onChange(showHideDebugInfo);
-+showHideDebugInfo();
-
-const labelContainerElem = document.querySelector('#labels');
-+function showHideDebugInfo() {
-+  labelContainerElem.style.display = globals.debug ? '' : 'none';
-+}
-+showHideDebugInfo();
-
-class StateDisplayHelper extends Component {
-
-  ...
-
-  update() {
-+    this.helper.visible = globals.debug;
-+    if (!globals.debug) {
-+      return;
-+    }
-
-    ...
-  }
-}
-
-

게임의 가장 기본적인 틀을 완성했네요.

-

- -

-

원래 처음에는 지렁이 게임을 만들려고 했습니다. 동물이 기차에 붙어 기차가 길어질수록 장애물을 피하기 어려워지는 게임이죠. 예제에 몇 가지 장애물 놓거나 화면 둘레에 벽을 세우기도 했습니다.

-

하지만 예제에서 사용한 동물은 이에 적합하지 않습니다. 예제의 동물들은 대부분 위에서 봤을 때 길고 폭이 얇거든요. 아래는 얼룩말을 위에서 본 것입니다.

-
- -

예제는 원 모양의 경계로 요소끼리의 충돌을 감지하기에 아래와 같이 울타리에 닿는 경우도 충돌로 감지할 겁니다.

-
- -

동물과 동물이 부딪히는 경우에도 마찬가지입니다. 특히 게임에서는 이래서 좋을 게 없죠.

-

2D 사각형을 만들어 충돌을 감지하는 것도 생각했으나, 바로 너무 많은 코드를 써야 한다는 걸 깨달았습니다. 예제의 각 모델에 다른 크기의 사각형을 추가하는 데는 그다지 많은 코드가 들어가지 않습니다. 하지만 이렇게 몇 가지 모델에 사각형을 추가해보면 곧 충돌을 감지하는 코드를 손봐야 할 필요가 생길 겁니다. 먼저 각 모델이 서로 충돌하는지 확인해야 하니 각 모델의 경계 정육면체나 경계 구체, 또는 모델과 같은 방향으로 정렬된 경계 육면체를 검사해야 합니다. 각 모델의 경계가 충돌했다는 건 두 모델이 어쩌면 서로 충돌했을 수도 있다는 이야기이기에, 각 모델이 실제로 충돌했는지 검사하기 위해 해당 모델들을 다시 검사해야 합니다. 대체로 경계 구체를 검사하는 것만 해도 꽤 많은 작업이 필요합니다. 가능하다면 각 요소가 근접했는지의 여부만 검사하는 등 더 특수한 방법을 사용하는 게 더 경제적이죠.

-

또한 충돌 여부를 검사하기만 하는 것으로 끝나는 것이 아니라 충돌 시스템도 구축해야 합니다. 그때 그때 각 모델에게 "너 다른 애랑 충돌했니?" 이렇게 물어보는 것보다 시스템이 직접 충돌 여부를 이벤트 등으로 알려주는 게 더 편할 테니까요. 충돌 시스템은 충돌과 관련한 이벤트나 콜백을 사용합니다. 이 방법의 장점은 모든 충돌을 한 번만 검사하기에 각 모델이 "내가 다른 애랑 충돌했나?" 이렇게 검사를 따로 할 필요가 없다는 거죠. 연산량을 훨씬 줄일 수 있습니다.

-

사각형을 확인하는 정도의 간단한 충돌 시스템을 만드는 코드는 100-300 줄 정도를 넘지 않을 겁니다. 하지만 예제와 비교하면 여전히 많은 코드이니 지금은 이대로 남겨 두겠습니다.

-

시도해봄직한 다른 방법은 다른 캐릭터 중 위에서 바라봤을 때 가장 원형에 가까운 캐릭터를 찾는 겁니다*. 인간형 캐릭터의 경우는 대부분 잘 작동할 테고, 동물과 동물의 경우도 일부 경우는 잘 작동할 겁니다. 하지만 동물과 울타리의 경우는 감지하지 못하겠죠. 원래 화면 주위에 울타리나 덤불, 둥근 막대를 둘러보려고 했으나 이러려면 120에서 200개 정도의 요소를 더 만들어야 하고, 위에서 언급한 최적화 문제에 부딪쳤을 겁니다.

-

※ 시야각 때문에 카메라의 중심에서 벗어날수록 머리 위가 아닌 옆이 보이는 걸 이용한 방법. 역주.

-

이런 여러 문제 때문에 대부분의 게임들이 기존에 쓰던 방법을 사용합니다. 그리고 이 방법들 중에는 물리 라이브러리에서 쓰는 것들도 있죠. 물리 라이브러리는 요소가 서로 충돌하는지 확인하는 기능이 필수기에, 제가 위에서 사용했던 방법을 사용하기도 합니다.

-

Three.js의 예제 중 ammo.js를 사용한 것을 보면 이런 해결 방법을 찾는 데 도움이 될지도 모르겠네요.

-

또 다른 방법은 장애물을 일정한 격자(grid)에 놓고 플레이어와 동물이 해당 격자만 참조하게 하는 겁니다. 성능 면에서 굉장히 좋은 방법인데, 이 또한 여러분이 직접 연습할 수 있는 😜 요소로 남겨 두면 좋겠다는 생각이 들더군요.

-

덧붙여 대부분의 게임 시스템에는 코루틴(coroutine)이라는 것이 있습니다. 코루틴은 특정 작업을 하는 동안 멈췄다가 나중에 다시 시작하는 루틴(routine)을 말하죠.

-

플레이어 위에 음표를 띄워 노래로 동물들을 꼬시는 것처럼 해보겠습니다. 구현할 수 있는 방법은 아주 많지만, 예제에서는 코루틴을 사용해 이를 구현하겠습니다.

-

먼저 코루틴을 관리하는 클래스를 만듭니다.

-
function* waitSeconds(duration) {
-  while (duration > 0) {
-    duration -= globals.deltaTime;
-    yield;
-  }
-}
-
-class CoroutineRunner {
-  constructor() {
-    this.generatorStacks = [];
-    this.addQueue = [];
-    this.removeQueue = new Set();
-  }
-  isBusy() {
-    return this.addQueue.length + this.generatorStacks.length > 0;
-  }
-  add(generator, delay = 0) {
-    const genStack = [generator];
-    if (delay) {
-      genStack.push(waitSeconds(delay));
-    }
-    this.addQueue.push(genStack);
-  }
-  remove(generator) {
-    this.removeQueue.add(generator);
-  }
-  update() {
-    this._addQueued();
-    this._removeQueued();
-    for (const genStack of this.generatorStacks) {
-      const main = genStack[0];
-      // 다른 코루틴이 해당 요소를 제거했을 경우
-      if (this.removeQueue.has(main)) {
-        continue;
-      }
-      while (genStack.length) {
-        const topGen = genStack[genStack.length - 1];
-        const { value, done } = topGen.next();
-        if (done) {
-          if (genStack.length === 1) {
-            this.removeQueue.add(topGen);
-            break;
-          }
-          genStack.pop();
-        } else if (value) {
-          genStack.push(value);
-        } else {
-          break;
-        }
-      }
-    }
-    this._removeQueued();
-  }
-  _addQueued() {
-    if (this.addQueue.length) {
-      this.generatorStacks.splice(this.generatorStacks.length, 0, ...this.addQueue);
-      this.addQueue = [];
-    }
-  }
-  _removeQueued() {
-    if (this.removeQueue.size) {
-      this.generatorStacks = this.generatorStacks.filter(genStack => !this.removeQueue.has(genStack[0]));
-      this.removeQueue.clear();
-    }
-  }
-}
-
-

위 클래스는 다른 코루틴이 실행되는 동안 요소를 안전하게 제거/추가하도록 SafeArray와 비슷한 구조로 만들었습니다. 또한 이 클래스는 중첩된 코루틴도 처리합니다.

-

코루틴을 만들려면 자바스크립트의 제너레이터 함수를 만들어야 합니다. 제너레이터 함수는 function*이라는 키워드로 생성하죠(별표를 붙여야 합니다!).

-

제너레이터 함수는 yield 키워드로 실행 순서를 양보(yield)할 수 있습니다.

-
function* count0To9() {
-  for (let i = 0; i < 10; ++i) {
-    console.log(i);
-    yield;
-  }
-}
-
-

이 함수를 아까 만든 CoroutineRunner에 추가하면 한 프레임, 또는 runner.update를 호출할 때마다 0부터 9까지의 숫자를 차례대로 출력할 겁니다.

-
const runner = new CoroutineRunner();
-runner.add(count0To9);
-while(runner.isBusy()) {
-  runner.update();
-}
-
-

코루틴은 동작이 끝났을 때 자동으로 제거됩니다. 코루틴이 끝나기 전에 제거하려면 제너레이터를 미리 참조한 뒤 remove 메서드를 호출해야 합니다.

-
const gen = count0To9();
-runner.add(gen);
-
-// 얼마 후
-
-runner.remove(gen);
-
-

이제 플레이어가 0.5에서 1초 사이마다 한 번씩 음표를 뱉도록 해봅시다.

-
class Player extends Component {
-  constructor(gameObject) {
-
-    ...
-
-+    this.runner = new CoroutineRunner();
-+
-+    function* emitNotes() {
-+      for (;;) {
-+        yield waitSeconds(rand(0.5, 1));
-+        const noteGO = gameObjectManager.createGameObject(scene, 'note');
-+        noteGO.transform.position.copy(gameObject.transform.position);
-+        noteGO.transform.position.y += 5;
-+        noteGO.addComponent(Note);
-+      }
-+    }
-+
-+    this.runner.add(emitNotes());
-  }
-  update() {
-+    this.runner.update();
-
-  ...
-
-  }
-}
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return Math.random() * (max - min) + min;
-}
-
-

위 코드에서는 CoroutineRunner를 만들고 emitNotes 코루틴을 추가했습니다. 이 함수는 0.5초에서 1초 사이마다 계속해서 Note 컴포넌트를 생성합니다.

-

Note 컴포넌트를 만들려면 먼저 텍스처가 필요합니다. 음표 이미지를 불러올 수도 있지만, 캔버스로 텍스처 만들기에서 다뤘던 것처럼 캔버스를 이용해 직접 음표를 만들겠습니다.

-
function makeTextTexture(str) {
-  const ctx = document.createElement('canvas').getContext('2d');
-  ctx.canvas.width = 64;
-  ctx.canvas.height = 64;
-  ctx.font = '60px sans-serif';
-  ctx.textAlign = 'center';
-  ctx.textBaseline = 'middle';
-  ctx.fillStyle = '#FFF';
-  ctx.fillText(str, ctx.canvas.width / 2, ctx.canvas.height / 2);
-  return new THREE.CanvasTexture(ctx.canvas);
-}
-const noteTexture = makeTextTexture('♪');
-
-

위에서 만든 텍스처는 하얀색으로, 나중에 텍스처를 사용할 때 색을 따로 지정해 원하는 색의 음표를 그릴 수 있습니다.

-

이제 음표 텍스처를 만들었으니 Note 컴포넌트를 만들 차례입니다. 음표 컴포넌트는 빌보드에 관한 글에서 다뤘던 SpriteMaterialSprite를 사용합니다.

-
class Note extends Component {
-  constructor(gameObject) {
-    super(gameObject);
-    const { transform } = gameObject;
-    const noteMaterial = new THREE.SpriteMaterial({
-      color: new THREE.Color().setHSL(rand(1), 1, 0.5),
-      map: noteTexture,
-      side: THREE.DoubleSide,
-      transparent: true,
-    });
-    const note = new THREE.Sprite(noteMaterial);
-    note.scale.setScalar(3);
-    transform.add(note);
-    this.runner = new CoroutineRunner();
-    const direction = new THREE.Vector3(rand(-0.2, 0.2), 1, rand(-0.2, 0.2));
-
-    function* moveAndRemove() {
-      for (let i = 0; i < 60; ++i) {
-        transform.translateOnAxis(direction, globals.deltaTime * 10);
-        noteMaterial.opacity = 1 - (i / 60);
-        yield;
-      }
-      transform.parent.remove(transform);
-      gameObjectManager.removeGameObject(gameObject);
-    }
-
-    this.runner.add(moveAndRemove());
-  }
-  update() {
-    this.runner.update();
-  }
-}
-
-

이 컴포넌트는 Sprite를 만들고 무작위로 속도를 정해 60프레임 동안 그 속도로 이동하게 합니다. 동시에 재질의 opacity 속성을 바꿔 페이드-아웃 효과도 주죠. 반복문이 끝나면 이 컴포넌트는 위치값과 음표를 해당 GameObject에서 제거합니다.

-

정말 마지막으로, 동물의 수를 좀 늘려보겠습니다.

-
function init() {
-
-   ...
-
-  const animalModelNames = [
-    'pig',
-    'cow',
-    'llama',
-    'pug',
-    'sheep',
-    'zebra',
-    'horse',
-  ];
-+  const base = new THREE.Object3D();
-+  const offset = new THREE.Object3D();
-+  base.add(offset);
-+
-+  // 소용돌이 형태로 동물들을 배치합니다.
-+  const numAnimals = 28;
-+  const arc = 10;
-+  const b = 10 / (2 * Math.PI);
-+  let r = 10;
-+  let phi = r / b;
-+  for (let i = 0; i < numAnimals; ++i) {
-+    const name = animalModelNames[rand(animalModelNames.length) | 0];
-    const gameObject = gameObjectManager.createGameObject(scene, name);
-    gameObject.addComponent(Animal, models[name]);
-+    base.rotation.y = phi;
-+    offset.position.x = r;
-+    offset.updateWorldMatrix(true, false);
-+    offset.getWorldPosition(gameObject.transform.position);
-+    phi += arc / r;
-+    r = b * phi;
-  }
-
-

- -

-

누군가 setTimeout을 쓰면 안 되냐고 물을지도 모르겠습니다. setTimeout을 쓰지 않은 건 setTimeout은 게임의 프레임 주기와 무관하기 때문입니다. 예를 들어 예제에서는 프레임 간 시간값을 최대 1/20초로 제한했죠. 방금 구축한 코루틴 시스템도 이 제한을 따를 테지만, setTimeout을 쓰면 그렇지 않을 겁니다.

-

물론 좀 더 간단한 타이머를 만들 수도 있습니다.

-
class Player ... {
-  update() {
-    this.noteTimer -= globals.deltaTime;
-    if (this.noteTimer <= 0) {
-      // 타이머를 초기화합니다.
-      this.noteTimer = rand(0.5, 1);
-      // GameObject로 음표 컴포넌트를 만듭니다.
-    }
-  }
-
-

특정 경우에야 이 방법이 더 좋을 수도 있지만, 더 많은 요소를 추가하면 그만큼 더 많은 변수와 코루틴을 추가해야 할테고, 그럴수록 setTimeout설정하고 까먹을 확률이 높아질 겁니다.

-

동물들의 상태를 설정할 때도 아래와 같이 코루틴을 사용할 수 있습니다.

-
// 실제로 사용하지 않는 함수
-function* animalCoroutine() {
-   setAnimation('Idle');
-   while(playerIsTooFar()) {
-     yield;
-   }
-   const target = endOfLine;
-   setAnimation('Jump');
-   while(targetIsTooFar()) {
-     aimAt(target);
-     yield;
-   }
-   setAnimation('Walk')
-   while(notAtOldestPositionOfTarget()) {
-     addHistory();
-     aimAt(target);
-     yield;
-   }
-   for(;;) {
-     addHistory();
-     const pos = history.unshift();
-     transform.position.copy(pos);
-     aimAt(history[0]);
-     yield;
-   }
-}
-
-

이 방법을 써도 딱히 문제는 없었겠지만, 상태가 일정하지 않아 다시 FiniteStateMachine을 찾게 될 겁니다.

-

또 저는 코루틴을 해당 컴포넌트와 독립적으로 실행하는 게 좋은지 잘 모르겠습니다. 물론 그냥 전역에 CoroutineRunner를 만들어 모든 코루틴을 여기에 집어 넣을 수는 있죠. 하지만 이러면 코루틴을 없애기가 힘들어질 겁니다. 지금 예제는 GameObject를 제거하면 해당 컴포넌트도 제거되고, 그러면 생성한 CoroutineRunner의 메서드를 호출할 일도 없으니 코루틴도 전부 가비지 컬렉션에 들어갈 겁니다. 전역에 CoroutineRunner를 두면 컴포넌트에서 직접 이 전역 객체의 코루틴을 제거하거나 자동으로 코루틴을 제거할 다른 방법이 필요할 겁니다.

-

실제 게임 엔진이라면 더 고려해야 할 문제가 많습니다. 지금은 GameObject나 컴포넌트에 따로 순서를 지정할 수 없죠. 그냥 추가한 순서가 해당 요소의 순서가 됩니다. 대부분의 게임 엔진은 우선 순위를 정해 순서를 바꿀 수 있습니다.

-

다른 문제는 Note 컴포넌트가 장면 위 GameObject의 transform 속성을 변경한다는 겁니다. 애초에 GameObject가 transform 속성을 변경했으니 좀 더 제대로 구현하려면 GameObject가 계속 transform 속성을 관리하는 게 맞겠죠. GameObjectdispose 같은 메서드를 두고 GameObjectManager.removeGameObject에서 이 메서드를 호출했다면 어떨까요?

-

gameObjectManager.updateinputManager.update를 직접 호출하는 대신 SystemManager를 만들어 update메서드를 가진 요소를 전부 추가해 이 클래스가 메서드를 호출하도록 하는 게 더 나을 수도 있습니다. 이렇게 하면 CollisionManager 등 새로운 시스템을 만들었을 때 render 함수를 수정하는 게 아니라 SystemManager에 이 시스템을 추가하기만 하면 될 겁니다.

-

저는 이런 문제들을 전부 다루기보다 여러분의 몫으로 남겨 두고자 합니다. 부디 이 글이 여러분만의 게임 엔진을 만드는 데 도움이 되었다면 좋겠네요.

-

어쩌면 제가 게임 잼(game jam)*을 열 수도 있겠네요. 위 예제의 jsfiddle이나 codepen을 클릭해보면 코드를 바로 편집해 볼 수 있는 사이트가 열릴 겁니다. 특정 기능을 추가하거나 해서 예제를 퍼그가 기사(knight)을 끌고 다니는 게임을 만들거나, 기사의 구르기 애니메이션을 볼링공으로써 동물 볼링 게임을 만들 수도 있겠죠. 또는 동물 이어 달리기 게임이라든가요. 괜찮은 게임을 만들었다면 아래에 댓글로 링크를 남겨주시면 감사하겠습니다.

-

※ 게임 잼: 보통 24시간에서 72시간 정도의 짧은 기간 내에 팀, 또는 개인이 게임을 만드는 대회. 역주.

-
-[1]: 물론 부모의 어떤 요소도 translation, rotation, scale 속성을 바꾸지 않았다면 정상적으로 작동합니다.[돌아가기] -
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/indexed-textures.html b/manual/ko/indexed-textures.html deleted file mode 100644 index cccc23666ad5ee..00000000000000 --- a/manual/ko/indexed-textures.html +++ /dev/null @@ -1,541 +0,0 @@ - - - 피킹과 색상에 인덱스 텍스처 사용하기 - - - - - - - - - - - - - - -
-
-

피킹과 색상에 인덱스 텍스처 사용하기

-
-
-
-

※ 이 글은 HTML 요소를 3D로 정렬하기에서 이어집니다. 이전 글을 읽지 않았다면 먼저 읽고 오기 바랍니다.

-

Three.js를 쓰다보면 창의적인 해결법이 필요할 때가 있습니다. 저도 나름 시리즈를 진행하며 나름 많은 해결법을 찾고, 적어 놓았죠. 혹 필요한 게 있다면 확인해보기 바랍니다. 물론 그게 최적의 해결법이라고 단언할 수는 없지만요.

-

이전 글에서는 3D 지구본 주위에 나라 이름을 표기했습니다. 여기서 더 나아가 사용자가 나라를 선택하고 자기가 선택한 나라를 보게 한다면 어떨까요? 또 어떻게 구현할 수 있을까요?

-

가장 쉽게 떠오르는 방법은 각 나라마다 geometry를 만드는 겁니다. 이전에 했던 것처럼 피킹(picking)을 써서 구현할 수 있겠죠. 이미 각 나라의 3D geometry는 만들었으니 사용자가 mesh를 클릭했을 때 어떤 나라를 클릭했는지 알 수 있을 겁니다.

-

시험삼아 이전 글에서 윤곽선을 만들기 위해 사용했던 데이터로 각 나라마다 3D mesh를 만들어봤습니다. 결과로 15.5MB짜리 GLTF(.glb) 파일이 나왔죠. 사용자가 간단한 지구본을 보려고 15.5MB나 다운 받아야 한다니, 개인적인 의견이지만 너무 과한 듯합니다.

-

데이터를 압축할 수 있는 방법이야 많습니다. 예를 들어 특정 알고리즘을 도입해 윤곽선의 해상도를 낮출 수 있죠. 이 글에서는 시도하지 않을 텐데, 이유는 미국의 경우 데이터를 많이 줄일 수 있겠지만 캐나다나 섬이 많은 나라는 그렇지 않을 것이기 때문입니다.

-

다른 방법은 실제 데이터를 전부 압축하는 겁니다. 압축 프로그램을 돌려 압축하니 용량이 11MB까지 줄더군요. 30% 정도 줄긴 했지만 여전히 큰 파일입니다.

-

32비트 부동 소수 대신 16비트 방식으로 데이터를 저장할 수도 있습니다. 또는 드레이코 압축기 같은 프로그램을 사용하는 것만으로 충분히 데이터를 줄일 수 있을지도 모르죠. 전 따로 드레이코 압축기를 사용해보진 않았으니 여러분이 한 번 써보시고 알려주신다면 감사하겠습니다 😅.

-

이 글에서는 피킹에 관한 글 마지막에서 다뤘던 GPU 피킹을 사용해보겠습니다. 각 mesh에 id 역할을 할 고유한 색을 부여하고 해당 mesh를 클릭했을 때 해당 픽셀의 색상값으로 사용자가 어떤 mesh를 클릭했는지 알아내는 방법이죠.

-

일단 각 나라에 고유한 색상을 부여한 뒤, 이 색상값을 인덱스로 나라 배열을 만듭니다. 그리고 피킹용 텍스처를 만든 뒤 이걸로 지구본을 렌더링합니다. 이러면 사용자가 클릭한 픽셀을 확인해 어떤 나라를 클릭했는지 알 수 있겠죠.

-

먼저 약간의 코드를 작성해 아래의 텍스처를 만들었습니다.

-
- -
-

참고: 이 텍스트를 만드는 데 사용한 데이터는 이 웹사이트이며, 라이선스는 CC-BY-SA입니다.

-
-

이 이미지는 271KB 정도밖에 되지 않습니다. 나라들의 mesh가 14MB가 넘었던 것에 비하면 훨씬 낫네요. 물론 해상도를 더 낮출 수도 있지만 이 정도면 충분한 것 같네요.

-

이제 나라에 피킹을 적용해 봅시다.

-

GPU 피킹 예제의 코드를 가져와 피킹용 장면(scene)을 따로 만듭니다.

-
const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

피킹용 장면에 피킹용 텍스처를 입힌 지구본을 추가합니다.

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-+  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-+  indexTexture.minFilter = THREE.NearestFilter;
-+  indexTexture.magFilter = THREE.NearestFilter;
-+
-+  const pickingMaterial = new THREE.MeshBasicMaterial({ map: indexTexture });
-+  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({ map: texture });
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

다음으로 GPUPickHelper를 통째로 가져와 몇 가지 수정합니다.

-
class GPUPickHelper {
-  constructor() {
-    // 1x1 픽셀 크기의 렌더 타겟을 생성합니다
-    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-    this.pixelBuffer = new Uint8Array(4);
--    this.pickedObject = null;
--    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera) {
-    const { pickingTexture, pixelBuffer } = this;
-
-    // view offset을 마우스 포인터 아래 1픽셀로 설정합니다
-    const pixelRatio = renderer.getPixelRatio();
-    camera.setViewOffset(
-      renderer.getContext().drawingBufferWidth,   // 전체 너비
-      renderer.getContext().drawingBufferHeight,  // 전체 높이
-      cssPosition.x * pixelRatio | 0,             // 사각 x 좌표
-      cssPosition.y * pixelRatio | 0,             // 사각 y 좌표
-      1,                                          // 사각 좌표 width
-      1,                                          // 사각 좌표 height
-    );
-    // 장면을 렌더링합니다
-    renderer.setRenderTarget(pickingTexture);
-    renderer.render(scene, camera);
-    renderer.setRenderTarget(null);
-    // view offset을 정상으로 돌려 원래의 화면을 렌더링하도록 합니다
-    camera.clearViewOffset();
-    // 픽셀을 감지합니다
-    renderer.readRenderTargetPixels(
-        pickingTexture,
-        0,   // x
-        0,   // y
-        1,   // width
-        1,   // height
-        pixelBuffer);
-
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2] <<  0);
-+
-+    return id;
--    const id =
--        (pixelBuffer[0] << 16) |
--        (pixelBuffer[1] <<  8) |
--        (pixelBuffer[2]      );
--    const intersectedObject = idToObject[id];
--    if (intersectedObject) {
--      // 첫 번째 물체가 제일 가까우므로 해당 물체를 고릅니다
--      this.pickedObject = intersectedObject;
--      // 기존 색을 저장해둡니다
--      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
--      // emissive 색을 빨강/노랑으로 빛나게 만듭니다
--      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
--    }
-  }
-}
-
-

GPUPickHelper를 이용해 나라를 선택하도록 합니다.

-
const pickHelper = new GPUPickHelper();
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // 아직 데이터를 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    // 나라를 선택했을 때 해당 나라의 'selected' 속성을 바꿉니다.
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    // 나라를 클릭했을 때 특수키를 누르지 않았다면 다른 나라의 'selected'
-    // 속성을 전부 끕니다.
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-  } else if (numCountriesSelected) {
-    // 바다나 하늘을 클릭했을 경우
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-}
-
-canvas.addEventListener('pointerup', pickCountry);
-
-

위 코드는 나라 배열에 속한 나라의 selected 속성을 켜고 끕니다. shift, ctrl, cmd 중 하나를 누르면 하나 이상의 나라를 선택할 수 있죠.

-

이제 선택한 나라를 보여줄 일만 남았습니다. 지금은 일단 해당 나라의 이름표를 보여주기로 하죠.

-
function updateLabels() {
-  // 아직 데이터를 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-  const large = settings.minArea * settings.minArea;
-  // 카메라의 상대 방향을 나타내는 행렬 좌표를 가져옵니다.
-  normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-  // 카메라의 위치를 가져옵니다.
-  camera.getWorldPosition(cameraPosition);
-  for (const countryInfo of countryInfos) {
--    const { position, elem, area } = countryInfo;
--    // 영역이 특정 값보다 작다면 이름표를 표시하지 않습니다.
--    if (area < large) {
-+    const { position, elem, area, selected } = countryInfo;
-+    const largeEnough = area >= large;
-+    const show = selected || (numCountriesSelected === 0 && largeEnough);
-+    if (!show) {
-      elem.style.display = 'none';
-      continue;
-    }
-
-    ...
-
-

이제 나라를 선택해 볼 수 있습니다.

-

- -

-

위 예제는 여전히 영역 크기에 따라 나라 이름을 보여주긴 하나, 특정 나라를 클릭하면 해당 나라의 이름만 보여줄 겁니다.

-

이만하면 각 나라를 피킹하는 예제로 충분해 보이지만... 선택한 나라의 색을 바꾸려면 어떻게 해야 할까요?

-

컬러 팔레트(color palette)를 사용하면 이 문제를 해결할 수 있습니다.

-

컬러 팔레트) 혹은 인덱스 팔레트는 아타리 800, Amiga, NES, 슈퍼 닌텐도, 구형 IBM PC 등 구형 시스템에서 사용하던 기법입니다. 비트맵을 색상당 8비트 혹은 32바이트 이상의 RGBA 색상으로 적용하는 대신 비트맵을 8비트 이하의 값으로 저장하는 기법이죠. 각 픽셀의 색상값은 팔레트의 인덱스 값으로, 픽셀의 색상값이 3이라면 특정 "팔레트"의 3번 색상을 사용한다는 의미입니다.

-

자바스크립트로 설명하자면 아래와 같은 형식을 생각할 수 있습니다.

-
const face7x7PixelImageData = [
-  0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 2, 0, 2, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  1, 0, 3, 3, 3, 0, 1,
-  1, 0, 0, 0, 0, 0, 1,
-  0, 1, 1, 1, 1, 1, 1,
-];
-
-const palette = [
-  [255, 255, 255],  // white
-  [  0,   0,   0],  // black
-  [  0, 255, 255],  // cyan
-  [255,   0,   0],  // red
-];
-
-

이미지 데이터의 각 픽셀은 팔레트의 인덱스를 가리킵니다. 위 데이터를 위 팔레트로 해석하면 다음과 같은 이미지가 나오겠죠.

-
- -

예제의 경우 이미 각 나라별로 고유 색을 부여한 텍스처가 있습니다. 이 텍스처에 팔레트를 적용하면 각 나라에 다른 색을 부여할 수 있겠죠. 또 이 팔레트의 색을 바꾸면 각 나라의 색도 바뀔 겁니다. 그러니 팔레트의 색을 전부 검정으로 바꾼 뒤, 선택한 나라만 다른 색으로 바꾸면 해당 나라를 선택했다는 것을 시각적으로 나타낼 수 있을 겁니다.

-

컬러 팔레트 기법을 사용하려면 쉐이더를 직접 만들어야 합니다. Three.js의 내장 쉐이더를 수정해서 사용하면 조명이나 다른 기능도 나중에 사용할 수 있으니 이 방법을 사용하도록 하죠.

-

다중 애니메이션 요소 최적화하기에서 다뤘듯 재질의 onBeforeCompile 속성에 함수를 지정하면 내장 쉐이더를 수정할 수 있습니다.

-

아래는 내장 fragment 쉐이더를 수정하기 전입니다.

-
#include <common>
-#include <color_pars_fragment>
-#include <uv_pars_fragment>
-#include <map_pars_fragment>
-#include <alphamap_pars_fragment>
-#include <aomap_pars_fragment>
-#include <lightmap_pars_fragment>
-#include <envmap_pars_fragment>
-#include <fog_pars_fragment>
-#include <specularmap_pars_fragment>
-#include <logdepthbuf_pars_fragment>
-#include <clipping_planes_pars_fragment>
-void main() {
-    #include <clipping_planes_fragment>
-    vec4 diffuseColor = vec4( diffuse, opacity );
-    #include <logdepthbuf_fragment>
-    #include <map_fragment>
-    #include <color_fragment>
-    #include <alphamap_fragment>
-    #include <alphatest_fragment>
-    #include <specularmap_fragment>
-    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
-    #ifdef USE_LIGHTMAP
-        reflectedLight.indirectDiffuse += texture2D( lightMap, vLightMapUv ).xyz * lightMapIntensity;
-    #else
-        reflectedLight.indirectDiffuse += vec3( 1.0 );
-    #endif
-    #include <aomap_fragment>
-    reflectedLight.indirectDiffuse *= diffuseColor.rgb;
-    vec3 outgoingLight = reflectedLight.indirectDiffuse;
-    #include <envmap_fragment>
-    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
-    #include <premultiplied_alpha_fragment>
-    #include <tonemapping_fragment>
-    #include <colorspace_fragment>
-    #include <fog_fragment>
-}
-
-

위 코드의 쉐이더 조각을 일일이 뒤져 보니 Three.js는 diffuseColor라는 변수로 재질(material)의 색상값을 제어합니다. 이 변수는 <color_fragment>라는 쉐이더 조각에서 선언하니 변수 선언 후에 색상값을 수정하면 되겠네요.

-

저 때 diffuseColor는 아까 만들었던 윤곽선 텍스처에서 색상을 가져온 상태일 테니, 이 색상값으로 팔레트 텍스처에서 새로운 색상값을 가져 올 수 있을 겁니다.

-

이전에 했던 것처럼 바꿀 문자열 정보를 배열로 만들어 Material.onBeforeCompile에서 쉐이더를 수정하겠습니다.

-
{
-  const loader = new THREE.TextureLoader();
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-
-  const indexTexture = loader.load('resources/data/world/country-index-texture.png', render);
-  indexTexture.minFilter = THREE.NearestFilter;
-  indexTexture.magFilter = THREE.NearestFilter;
-
-  const pickingMaterial = new THREE.MeshBasicMaterial({ map: indexTexture });
-  pickingScene.add(new THREE.Mesh(geometry, pickingMaterial));
-
-+  const fragmentShaderReplacements = [
-+    {
-+      from: '#include <common>',
-+      to: `
-+        #include <common>
-+        uniform sampler2D indexTexture;
-+        uniform sampler2D paletteTexture;
-+        uniform float paletteTextureWidth;
-+      `,
-+    },
-+    {
-+      from: '#include <color_fragment>',
-+      to: `
-+        #include <color_fragment>
-+        {
-+          vec4 indexColor = texture2D(indexTexture, vUv);
-+          float index = indexColor.r * 255.0 + indexColor.g * 255.0 * 256.0;
-+          vec2 paletteUV = vec2((index + 0.5) / paletteTextureWidth, 0.5);
-+          vec4 paletteColor = texture2D(paletteTexture, paletteUV);
-+          // diffuseColor.rgb += paletteColor.rgb;   // 하얀 윤곽선
-+          diffuseColor.rgb = paletteColor.rgb - diffuseColor.rgb;  // 검은 윤곽선
-+        }
-+      `,
-+    },
-+  ];
-
-  const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-  const material = new THREE.MeshBasicMaterial({ map: texture });
-+  material.onBeforeCompile = function(shader) {
-+    fragmentShaderReplacements.forEach((rep) => {
-+      shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-+    });
-+  };
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

위 코드에서는 indexTexture, paletteTexture, paletteTextureWidth, 총 3개의 균등 변수(uniform)를 사용했습니다. indexTexture는 색상값을 불러와 인덱스로 변환하기 위한 것으로, 이때 사용한 vUv는 Three.js가 넘겨주는 텍스처 좌표이죠. 그리고 이 인덱스 값으로 컬러 팔레트에서 새로운 색상값을 가져 와 diffuseColor와 섞었습니다. 이때 diffuseColor는 검은바탕에 하얀색 윤곽선 텍스처이니 두 색을 더해도 하얀 윤곽선이 나올 겁니다. 대신 새로운 색에서 diffuseColor를 뺀다면 검은 윤곽선이 나오겠죠.

-

다음으로 렌더링 전에 팔레트 텍스처와 3개의 균등 변수를 지정해야 합니다.

-

팔레트 텍스처에는 나라당 하나의 색상과 바다의 색상(id = 0) 하나만 필요합니다. 전 세계적으로 약 240여 개의 나라가 있죠. 나라 배열을 불러올 때까지 기다렸다가 정확한 개수를 받아올 수도 있을 겁니다. 하지만 당장 숫자가 크다고 문제가 될 것 같지는 않으니 512 정도의 큰 숫자를 고르기로 합시다.

-

아래는 팔레트 텍스처를 만드는 코드입니다.

-
const maxNumCountries = 512;
-const paletteTextureWidth = maxNumCountries;
-const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 4);
-const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight);
-paletteTexture.minFilter = THREE.NearestFilter;
-paletteTexture.magFilter = THREE.NearestFilter;
-
-

DataTexture를 쓰면 텍스처를 로우-데이터(raw data) 형식으로 넘길 수 있습니다. 예제의 경우에는 512 RGBA 색상을 넘겨주면 되겠죠. 각 값은 3바이트로, 이 바이트는 각각 red, green, blue을 0부터 255까지의 숫자로 나타냅니다.

-

일단은 무작위로 색을 지정해 잘 작동하는지 테스트해봅시다.

-
for (let i = 1; i < palette.length; ++i) {
-  palette[i] = Math.random() * 256;
-}
-// 바다의 색을 지정합니다. (index #0)
-palette.set([100, 200, 255, 255], 0);
-paletteTexture.needsUpdate = true;
-
-

palette 배열로 팔레트 텍스처를 업데이트할 때마다 장면을 업데이트해야 하니 paletteTexture.needsUpdatetrue로 설정합니다.

-

다음으로 재질에 균등 변수를 설정해줍니다.

-
const geometry = new THREE.SphereGeometry(1, 64, 32);
-const material = new THREE.MeshBasicMaterial({ map: texture });
-material.onBeforeCompile = function(shader) {
-  fragmentShaderReplacements.forEach((rep) => {
-    shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
-  });
-+  shader.uniforms.paletteTexture = { value: paletteTexture };
-+  shader.uniforms.indexTexture = { value: indexTexture };
-+  shader.uniforms.paletteTextureWidth = { value: paletteTextureWidth };
-};
-scene.add(new THREE.Mesh(geometry, material));
-
-

이제 예제를 실행하면 각 나라의 색상이 무작위로 지정된 것이 보일 겁니다.

-

- -

-

인덱싱과 팔레트 텍스처가 잘 작동하는 것을 확인했으니, 이제 팔레트를 조작해 선택한 나라의 색상만 바꾸도록 해봅시다.

-

먼저 함수를 하나 만듭니다. 이 함수는 Three.js의 Color를 매개변수로 받아 팔레트 텍스처에 지정할 수 있는 값을 반환할 겁니다.

-
const tempColor = new THREE.Color();
-function get255BasedColor(color) {
-  tempColor.set(color);
-  const base = tempColor.toArray().map(v => v * 255);
-  base.push(255); // alpha
-  return base;
-}
-
-

위 함수를 color = get255BasedColor('red')와 같은 식으로 호출하면 [255, 0, 0] 이런 식의 배열을 반환합니다.

-

다음으로 위 함수를 이용해 몇 가지 색을 만들어 팔레트를 채웁니다.

-
const selectedColor = get255BasedColor('red');
-const unselectedColor = get255BasedColor('#444');
-const oceanColor = get255BasedColor('rgb(100,200,255)');
-resetPalette();
-
-function setPaletteColor(index, color) {
-  palette.set(color, index * 4);
-}
-
-function resetPalette() {
-  // 모든 팔레트의 색상을 unselectedColor로 바꿉니다.
-  for (let i = 1; i < maxNumCountries; ++i) {
-    setPaletteColor(i, unselectedColor);
-  }
-
-  // 바다의 색을 지정합니다. (index #0)
-  setPaletteColor(0, oceanColor);
-  paletteTexture.needsUpdate = true;
-}
-
-

이제 resetPalette 함수를 이용해 나라를 선택했을 때 팔레트를 업데이트합니다.

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // 아직 데이터를 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-  const position = getCanvasRelativePosition(event);
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-+    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-+    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-+  resetPalette();
-}
-
-

이제 선택한 나라가 강조되어 보일 겁니다.

-

- -

-

잘 작동하는 것 같네요!

-

다만 지구본을 돌릴 때도 나라가 선택된다는 게 거슬립니다. 또 나라를 선택하고 지구본을 돌리면 해당 선택이 풀려버리네요.

-

마지막으로 이것까지 고쳐봅시다. 2가지 정도를 확인하면 충분할 것 같네요. 하나는 포인터를 누른 후 떼기까지 얼마나 시간이 흘렀는지를 확이하는 것이고, 다른 하나는 포인터가 움직였는지 확인하는 겁니다. 마우스를 떼는 데 시간이 얼마 안 걸렸고 포인터가 움직이지 않았다면 클릭으로 간주하는 것이죠.

-
+const maxClickTimeMs = 200;
-+const maxMoveDeltaSq = 5 * 5;
-+const startPosition = {};
-+let startTimeMs;
-+
-+function recordStartTimeAndPosition(event) {
-+  startTimeMs = performance.now();
-+  const pos = getCanvasRelativePosition(event);
-+  startPosition.x = pos.x;
-+  startPosition.y = pos.y;
-+}
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function pickCountry(event) {
-  // 아직 데이터를 불러오지 않았을 경우
-  if (!countryInfos) {
-    return;
-  }
-
-+  // 포인터를 누른 후 떼기까지 일정 시간 이상 걸렸다면
-+  // 선택 액션이 아닌 드래그 액션으로 간주합니다.
-+  const clickTimeMs = performance.now() - startTimeMs;
-+  if (clickTimeMs > maxClickTimeMs) {
-+    return;
-+  }
-+
-+  // 포인터가 움직였다면 드래그로 간주합니다.
-+  const position = getCanvasRelativePosition(event);
-+  const moveDeltaSq = (startPosition.x - position.x) ** 2 +
-+                      (startPosition.y - position.y) ** 2;
-+  if (moveDeltaSq > maxMoveDeltaSq) {
-+    return;
-+  }
-
--  const position = { x: event.clientX, y: event.clientY };
-  const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
-    const countryInfo = countryInfos[id - 1];
-    const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
-      unselectAllCountries();
-    }
-    numCountriesSelected += selected ? 1 : -1;
-    countryInfo.selected = selected;
-    setPaletteColor(id, selected ? selectedColor : unselectedColor);
-    paletteTexture.needsUpdate = true;
-  } else if (numCountriesSelected) {
-    unselectAllCountries();
-  }
-  requestRenderIfNotRequested();
-}
-
-function unselectAllCountries() {
-  numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
-    countryInfo.selected = false;
-  });
-  resetPalette();
-}
-
-+canvas.addEventListener('pointerdown', recordStartTimeAndPosition);
-canvas.addEventListener('pointerup', pickCountry);
-
-

제 기준에서는 이 정도면 충분한 듯하네요.

-

- -

-

저는 UX 전문가가 아니니 더 나은 방법이 있을 경우 알려주시면 감사하겠습니다.

-

이 글이 인덱스(indexed) 그래픽을 활용하고, Three.js의 쉐이더를 수정해 간단한 효과를 구현하는 데 도움이 되었다면 좋겠네요. 쉐이더를 작성할 때 쓴 GLSL에 대해 다루기에는 너무 내용이 방대하니 후처리에 관한 글에 있는 링크를 참고하기 바랍니다.

- -
-
-
- - - - - - - - diff --git a/manual/ko/lang.css b/manual/ko/lang.css deleted file mode 100644 index 89472eebf2ff4a..00000000000000 --- a/manual/ko/lang.css +++ /dev/null @@ -1,19 +0,0 @@ -@font-face { - font-family: 'PureunJeonnam'; - font-style: normal; - font-weight: 700; - src: url(resources/fonts/PureunJeonnam-Bold.woff) format('woff'), - url(resources/fonts/PureunJeonnam-Bold.ttf) format('truetype'); -} -@font-face { - font-family: 'PureunJeonnam'; - font-style: normal; - font-weight: 400; - src: url(resources/fonts/PureunJeonnam.woff) format('woff'), - url(resources/fonts/PureunJeonnam.ttf) format('truetype'); -} - -:root { - --article-font-family: 'PureunJeonnam', sans-serif; - --headline-font-family: 'PureunJeonnam', sans-serif; -} \ No newline at end of file diff --git a/manual/ko/lights.html b/manual/ko/lights.html deleted file mode 100644 index bb905e6033759a..00000000000000 --- a/manual/ko/lights.html +++ /dev/null @@ -1,461 +0,0 @@ - - - 조명(Lights) - - - - - - - - - - - - - - -
-
-

조명(Lights)

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글과 -개발 환경 설정하는 법을 읽고 오길 권장합니다.

-

이전 글은 텍스처에 관한 글이었죠. 이번에는 -Three.js의 다양한 조명을 어떻게 쓰는지 알아보겠습니다.

-

먼저 이전 예제에서 카메라를 수정하겠습니다. 시야각(fov, field of view)은 -45도, far면은 100칸, 카메라의 위치는 중점에서 위로 10칸, 뒤로 20칸 옮깁니다.

-
*const fov = 45;
-const aspect = 2;  // canvas 요소의 기본 비율
-const near = 0.1;
-*const far = 100;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-+camera.position.set(0, 10, 20);
-
-

다음으로 OrbitControls를 추가합니다. OrbitControls는 특정 좌표를 -중심으로 카메라를 자전 또는 공전(orbit)하도록 해줍니다. OrbitControls는 -별도 모듈이므로, 먼저 페이지에 로드해야 합니다.

-
import * as THREE from 'three';
-+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-

이제 OrbitControls에 카메라와, DOM 이벤트를 감지할 수 있도록 -canvas 요소를 넘겨줍니다.

-
const controls = new OrbitControls(camera, canvas);
-controls.target.set(0, 5, 0);
-controls.update();
-
-

또한 시점을 중점에서 위로 5칸 올린 후 controls.update 메서드를 -호출해 OrbitControls가 새로운 시점을 바라보게 합니다.

-

다음으로 빛을 받을 무언가를 만들어보겠습니다. 먼저 땅의 역할을 할 -평면을 만들고, 평면에 2x2 픽셀의 체크판 텍스처를 씌우겠습니다.

-
- -
- -

일단 텍스처를 불러온 뒤, 반복하도록 래핑(wrapping)을 설정해줍니다. 필터는 -NearestFilter, 텍스처가 2x2 픽셀의 체크판이니 repeat 속성을 평면의 -반으로 설정하면 체크판의 각 칸은 정확히 (장면의) 1칸이 될 겁니다.

-
const planeSize = 40;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
-texture.colorSpace = THREE.SRGBColorSpace;
-const repeats = planeSize / 2;
-texture.repeat.set(repeats, repeats);
-
-

그리고 평면 geometry, 평면에 쓸 재질(material), 장면(scene)에 추가할 -mesh를 만듭니다. 평면은 기본적으로 XY축을 기준으로 하니, XZ축을 기준으로 -하려면 평면을 회전시켜야 합니다.

-
const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planeMat = new THREE.MeshPhongMaterial({
-  map: texture,
-  side: THREE.DoubleSide,
-});
-const mesh = new THREE.Mesh(planeGeo, planeMat);
-mesh.rotation.x = Math.PI * -.5;
-scene.add(mesh);
-
-

정육면체와 구체도 추가해서 평면까지 총 3개의 물체를 추가하도록 하죠.

-
{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-  const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

빛을 받을 물체를 만들었으니 이제 조명을 가지고 놀아봅시다!

-

AmbientLight

-

먼저 AmbientLight(자연광)를 써보겠습니다.

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.AmbientLight(color, intensity);
-scene.add(light);
-
-

이 조명도 lil-gui를 사용해 -속성을 조정할 수 있도록 만들겠습니다. lil-gui로 색상을 조정하려면 간단한 -헬퍼 클래스가 필요합니다. 이 클래스는 색상을 CSS hex(예: #FF8844) 값으로 -변경해 lil-gui에 넘겨주는 역할을 할 거예요. 그리고 lil-gui가 클래스의 -속성을 지정할 때, 이를 조명에 직접 지정하도록 합니다.

-
class ColorGUIHelper {
-  constructor(object, prop) {
-    this.object = object;
-    this.prop = prop;
-  }
-  get value() {
-    return '#' + this.object[this.prop].getHexString();
-  }
-  set value(hexString) {
-    this.object[this.prop].set(hexString);
-  }
-}
-
-

아래는 lil-gui를 만드는 코드입니다.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

결과물은 다음과 같죠.

-

- -

-

카메라를 공전시키기(orbit) 위해 화면을 드래그해보세요.

-

물체들이 평평하고, 윤곽이 뚜렷하지 않습니다. AmbientLight는 물체와 -조명의 색, 그리고 조명의 밝기를 곱한 것과 같죠.

-
color = materialColor * light.color * light.intensity;
-

이게 전부입니다. AmbientLight에는 방향이라는 개념이 없죠. 주변광은 -완전히 고르게 적용되고 공간 안 물체의 색을 바꾸는 역할만 하기 때문에 -실용적이지 않은데다 그다지 조명처럼 느껴지지도 않습니다. 어두운 장면을 -덜 어둡게 만드는 정도에만 도움이 되죠.

-

HemisphereLight

-

조명을 HemisphereLight(반구광)으로 바꾸겠습니다. HemisphereLight는 -천장과 바닥의 색을 인자로 받아, 물체의 천장을 바라보는 면은 천장 색, 바닥을 -바라보는 면은 바닥 색으로 혼합합니다.

-
-const color = 0xFFFFFF;
-+const skyColor = 0xB1E1FF;  // 하늘색
-+const groundColor = 0xB97A20;  // 오렌지 브라운
-const intensity = 1;
--const light = new THREE.AmbientLight(color, intensity);
-+const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
-scene.add(light);
-
-

마찬가지로 lil-gui를 수정해 두 색상을 조정할 수 있도록 합니다.

-
const gui = new GUI();
--gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-+gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('skyColor');
-+gui.addColor(new ColorGUIHelper(light, 'groundColor'), 'value').name('groundColor');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-

- -

-

이 또한 그다지 입체적이지 않습니다. 아까보다는 낮지만 전체적으로 2D처럼 -보이네요. HemisphereLight는 주로 풍경을 표현하거나 할 때 다른 조명과 -함께 사용합니다. 다른 조명과 조합할 때 유용하고, 간단히는 AmbientLight -대신 사용할 수 있죠.

-

DirectionalLight

-

이번에는 조명을 DirectionalLight(직사광)로 바꿔보죠. DirectionalLight는 -주로 태양을 표현할 때 사용합니다.

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.DirectionalLight(color, intensity);
-light.position.set(0, 10, 0);
-light.target.position.set(-5, 0, 0);
-scene.add(light);
-scene.add(light.target);
-
-

먼저 lightlight.target(목표)을 모두 장면에 추가해야 합니다. -그래야 Three.js의 DirectionalLight가 목표가 있는 방향으로 빛을 -쬘 테니까요.

-

이 역시 GUI를 사용해 목표의 위치를 조정할 수 있도록 만들겠습니다.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-gui.add(light.target.position, 'x', -10, 10);
-gui.add(light.target.position, 'z', -10, 10);
-gui.add(light.target.position, 'y', 0, 10);
-
-

- -

-

조명의 위치가 보이지 않으니 정확한 동작을 확인하기가 좀 어렵네요. -다행히 Three.js에는 눈에 보이지 않는 요소의 시각화를 도와주는 -다양한 헬퍼 객체가 있습니다. 이 경우 DirectionalLightHelper를 -사용해 조명을 면으로, 조명의 방향을 선으로 나타낼 수 있습니다. -사용법도 간단해서 조명을 인자로 넘겨주고 생성한 인스턴스를 장면에 -추가하면 됩니다.

-
const helper = new THREE.DirectionalLightHelper(light);
-scene.add(helper);
-
-

하는 김에 조명과 목표 둘 다 위치를 조정할 수 있도록 하겠습니다. -Vector3 객체를 인자로 받아, lil-gui로 이 객체의 x, y, -z 속성을 조정하는 함수를 하나 만듭니다.

-
function makeXYZGUI(gui, vector3, name, onChangeFn) {
-  const folder = gui.addFolder(name);
-  folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
-  folder.add(vector3, 'y', 0, 10).onChange(onChangeFn);
-  folder.add(vector3, 'z', -10, 10).onChange(onChangeFn);
-  folder.open();
-}
-
-

헬퍼 객체를 사용할 때는 헬퍼 객체의 update 메서드를 수동으로 -호출해줘야 합니다. 한 예로 lil-gui가 객체 속성을 변경할 때마다 -인자로 넘겨준 onChangeFn에서 헬퍼 객체의 update 메서드를 -호출할 수 있죠.

-

그리고 조명의 위치, 목표의 위치 객체에 방금 만든 함수를 각각 적용합니다.

-
+function updateLight() {
-+  light.target.updateMatrixWorld();
-+  helper.update();
-+}
-+updateLight();
-
-const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 5, 0.01);
-
-+makeXYZGUI(gui, light.position, 'position', updateLight);
-+makeXYZGUI(gui, light.target.position, 'target', updateLight);
-
-

이제 조명, 목표의 위치를 각각 조정할 수 있습니다.

-

- -

-

카메라를 돌려보면 아까보다 훨씬 동작이 명확하게 보일 겁니다. -평면은 DirectionalLight를 나타내는데, 이는 직사광이 어느 -한 점에서 뻗어나오는 조명이 아니기 때문입니다. 무한한 광원이 -목표를 향해 평행하게 빛을 내리쬐는 것이죠.

-

PointLight

-

PointLight는 한 점에서 무한히 뻗어나가는 광원입니다. 코드를 -다시 한 번 수정해보죠.

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.PointLight(color, intensity);
-light.position.set(0, 10, 0);
--light.target.position.set(-5, 0, 0);
-scene.add(light);
--scene.add(light.target);
-
-

헬퍼 객체도 PointLightHelper로 바꾸겠습니다.

-
-const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.PointLightHelper(light);
-scene.add(helper);
-
-

PointLight에는 목표가 없으므로 onChange 함수도 훨씬 간단하게 -짤 수 있습니다.

-
function updateLight() {
--  light.target.updateMatrixWorld();
-  helper.update();
-}
--updateLight();
-
-

PointLightHelper는 점의 표상을 그립니다. 점의 표상이란 점으로는 확인이 어려우니, -기본값으로 다이아몬드 형태의 와이어프레임(wireframe)을 대신 그려놓은 것이죠. 점의 -형태는 조명에 mesh 객체를 하나 넘겨 얼마든지 바꿀 수 있습니다.

-

PointLight에는 추가로 distance 속성이 있습니다. -distance가이 0이면 PointLight의 밝기가 무한대임을 의미하고, 0보다 크면 -distance에 지정된 거리만큼만 영향을 미칩니다.

-

거리도 조정할 수 있도록 GUI에 추가하겠습니다.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 250, 1);
-+gui.add(light, 'distance', 0, 40).onChange(updateLight);
-
-makeXYZGUI(gui, light.position, 'position', updateLight);
--makeXYZGUI(gui, light.target.position, 'target', updateLight);
-
-

이제 한 번 테스트해보죠.

-

- -

-

distance가 0보다 클 때 조명의 밝기를 잘 관찰해보세요.

-

SpotLight

-

스포트라이트는 비유하자면 원뿔 안의 PointLight입니다. -차이점은 원뿔 안에서만 빛난다는 점이죠. SpotLight의 -원뿔은 종류는 외부 원뿔과 내부 원뿔 두 가지입니다. -빛의 밝기는 내부 원뿔에서 가장 세고, 외부 원뿔에 가까워질수록 -0까지 낮아집니다.

-

DirectionalLight와 마찬가지로 SpotLight도 목표의 위치를 -정해줘야 합니다. 원뿔의 밑면이 해당 목표물을 바라보게 되죠.

-

위 예제의 DirectionalLight와 헬퍼 객체를 수정하겠습니다.

-
const color = 0xFFFFFF;
--const intensity = 1;
-+const intensity = 150;
--const light = new THREE.DirectionalLight(color, intensity);
-+const light = new THREE.SpotLight(color, intensity);
-scene.add(light);
-scene.add(light.target);
-
--const helper = new THREE.DirectionalLightHelper(light);
-+const helper = new THREE.SpotLightHelper(light);
-scene.add(helper);
-
-

원뿔의 내각은 angle에 호도(radians)값을 지정해 -설정합니다. 텍스처 예제에서 사용했던 DegRadHelper -객체를 사용해 UI에는 도(degrees)로 표시하도록 하겠습니다.

-
gui.add(new DegRadHelper(light, 'angle'), 'value', 0, 90).name('angle').onChange(updateLight);
-
-

내부 원뿔의 크기는 penumbra(반음영) 속성을 외부 -원뿔에 대한 비율(퍼센트)로 지정해 사용합니다. 다시 말해 penumbra 속성이 -0이면 외부 원뿔과 크기가 동일하다는 것이고, 1이면 빛이 중앙에서부터 외부 -원뿔까지 점점 희미해짐을 의미하죠. penumbra 속성이 0.5이라면? 중앙과 외부 -원뿔의 사이 50% 지점부터 빛이 희미해짐을 의미합니다.

-
gui.add(light, 'penumbra', 0, 1, 0.01);
-
-

- -

-

penumbra 속성이 0일 때는 빛의 경계가 굉장히 분명한 것이 보일 겁니다. -penumbra 속성을 1에 가깝게 조정하면 경계가 점점 흐릿해지죠.

-

SpotLight원뿔 모양처럼 보이지 않을지도 모릅니다. 이는 바닥이 원뿔의 -거리보다 가까이 있기 때문으로, distance를 약 5 정도로 조정하면 원뿔의 밑면을 -확인할 수 있을 겁니다.

-

RectAreaLight

-

마지막으로 살펴볼 조명은 RectAreaLight입니다. 이름 그대로 사각 형태의 -조명으로, 형광등이나 천장의 유리를 통과하는 태양빛을 표현하기에 적합합니다.

-

RectAreaLightMeshStandardMaterialMeshPhysicalMaterial만 -지원합니다. 예전 코드에서 재질(material)을 MeshStandardMaterial로 바꾸겠습니다.

-
  ...
-
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
--  const planeMat = new THREE.MeshPhongMaterial({
-+  const planeMat = new THREE.MeshStandardMaterial({
-    map: texture,
-    side: THREE.DoubleSide,
-  });
-  const mesh = new THREE.Mesh(planeGeo, planeMat);
-  mesh.rotation.x = Math.PI * -.5;
-  scene.add(mesh);
-}
-{
-  const cubeSize = 4;
-  const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-- const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-+ const cubeMat = new THREE.MeshStandardMaterial({color: '#8AC'});
-  const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-  mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-  scene.add(mesh);
-}
-{
-  const sphereRadius = 3;
-  const sphereWidthDivisions = 32;
-  const sphereHeightDivisions = 16;
-  const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
--  const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-+ const sphereMat = new THREE.MeshStandardMaterial({color: '#CA8'});
-  const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-  mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-  scene.add(mesh);
-}
-
-

RectAreaLight를 사용하려면 별도의 데이터를 불러와야 합니다. 또한 -RectAreaLightHelper도 같이 불러와 조명을 시각화하겠습니다.

-
import * as THREE from 'three';
-+import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';
-+import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';
-
-

모듈을 불러온 후 RectAreaLightUniformsLib.init 메서드를 호출합니다.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  RectAreaLightUniformsLib.init();
-
-

데이터를 불러오지 않아도 에러는 발생하지 않지만, 이상하게 보일 것이므로 -데이터를 불러와야 한다는 것을 꼭 기억하기 바랍니다.

-

이제 조명을 추가합니다.

-
const color = 0xFFFFFF;
-*const intensity = 5;
-+const width = 12;
-+const height = 4;
-*const light = new THREE.RectAreaLight(color, intensity, width, height);
-light.position.set(0, 10, 0);
-+light.rotation.x = THREE.MathUtils.degToRad(-90);
-scene.add(light);
-
-*const helper = new RectAreaLightHelper(light);
-*light.add(helper);
-
-

RectAreaLightDirectionalLight, SpotLight와 달리 목표를 사용하지 않습니다. -빛의 방향은 rotation으로 설정할 수 있죠. 또 RectAreaLightHelper는 직접 조명을 -자식으로 두는 다른 헬퍼 객체와 달리, 해당 조명의 자식이어야 합니다.

-

조명의 rotation, width, height 속성을 조정할 수 있도록 GUI도 수정해줍니다.

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'intensity', 0, 10, 0.01);
-gui.add(light, 'width', 0, 20);
-gui.add(light, 'height', 0, 20);
-gui.add(new DegRadHelper(light.rotation, 'x'), 'value', -180, 180).name('x rotation');
-gui.add(new DegRadHelper(light.rotation, 'y'), 'value', -180, 180).name('y rotation');
-gui.add(new DegRadHelper(light.rotation, 'z'), 'value', -180, 180).name('z rotation');
-
-makeXYZGUI(gui, light.position, 'position');
-
-

- -

- -

조명은 renderer가 장면을 렌더링하는 속도에 영향을 미칩니다. 그러니 -가능한 적은 조명을 쓰는 게 좋죠.

-

다음 장에서는 카메라 조작법에 대해 알아보겠습니다.

-

- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/load-gltf.html b/manual/ko/load-gltf.html deleted file mode 100644 index 6516509639b0b1..00000000000000 --- a/manual/ko/load-gltf.html +++ /dev/null @@ -1,673 +0,0 @@ - - - 에서 .GLTF 파일 불러오기 - - - - - - - - - - - - - - -
-
-

에서 .GLTF 파일 불러오기

-
-
-
-

이전 글에서는 .OBJ 파일을 불러오는 법에 대해 -배웠습니다. 이전 글을 읽지 않았다면 먼저 읽고 오길 권장합니다.

-

이전 글에서 말했듯 .OBJ 파일은 굉장히 오래된 파일 형식이고 구성이 간단합니다. -애초에 3D 에디터끼리 간단히 데이터를 주고 받을 것을 목적으로 만들었기에 씬 -그래프라는 개념이 없죠. 하나의 거대한 mesh입니다.

-

gLTF 형식은 애초부터 그래픽 요소를 -표현하기 위해 설계된 파일 형식입니다. 3D 파일 형식은 크게 3, 4개 형식으로 나눌 -수 있죠.

-
    -
  • 3D 에디터 형식

    -

    특정 프로그램을 위한 파일 형식입니다. .blend(블렌더), .max(3D Studio Max), -.mb, .ma(마야) 등이 있죠.

    -
  • -
  • 교환 형식

    -

    여기에 .OBJ, .DAE(Collada), .FBX 등이 여기에 속합니다. 3D 에디터끼리 데이터를 -교환하기 위해 고안된 형식으로, 보통 3D 에디터 내부에서 사용하는 것보다 더 많은 -데이터를 포함합니다.

    -
  • -
  • 앱 형식

    -

    특정 앱이나 게임 등에서 사용하는 파일 형식입니다.

    -
  • -
  • 전달(transmission) 형식

    -

    glTF가 첫 전달 형식 파일입니다. 굳이 따지자면 VRML이 처음이라고 할 수도 있으나, -VRML은 부족한 점이 많습니다.

    -

    glTF는 기존 파일 형식에서 부진한 점을 보완한 형식으로, 크게 다음 면에서 기존 형식보다 -뛰어납니다.

    -
      -
    1. 전달 시 파일 용량 최적화

      -

      정점 등의 큰 데이터를 이진수(binary) 형태로 저장하는 것을 의미합니다. glTF 파일을 -사용하면 별도의 가공 과정 없이 데이터를 GPU에 바로 로드할 수 있죠. 반면 VRML, .OBJ, -.DAE 등의 형식은 이런 데이터를 텍스트로 저장하여 파싱 과정이 필요합니다. 텍스트 기반의 -정점 데이터는 이진수 데이터보다 3배에서 많게는 5배까지 큽니다.

      -
    2. -
    3. 렌더링 최적화

      -

      앱 형식을 제외한 다른 파일 형식과 다른 점입니다. glTF 형식의 데이터는 수정이 아니라, -렌더링에 최적화되어 있습니다. 일반적으로 렌더링에 필요없는 데이터를 제거하는데, 예를 -들어 다각형을 glTF 형식으로 저장하면 전부 삼각형으로 변환됩니다. 적용할 재질 데이터도 -전부 지정되어 있죠.

      -
    4. -
    -
  • -
-

glTF는 특정 목적으로 고안되었기에 대부분의 경우 glTF 파일을 다운받아 사용하는 것은 -큰 문제가 없습니다. 다른 형식을 사용할 때는 대부분 조금씩 문제가 있었는데, 이번에는 -아니길 빌어봐야겠네요.

-

사실 예제 하나로는 glTF를 전부 소개하기 어렵습니다. 단순한 glTF 파일은 .OBJ 파일보다 -사용하기가 쉬운 경우도 많고, .OBJ 파일과 달리 재질(materials)을 파일 안에 포함하거든요. -그러니 파일을 하나 골라 불러오고, 이 과정에서 발생하는 문제를 해결하는 것이 더 도움이 -될 듯합니다.

-

인터넷 검색으로 로우-폴리(low-poly) 마을을 -하나 찾았습니다(작가: antonmoek). 뭔가 괜찮은 -예제가 나올 것 같은 예감이 드네요.

-
- -

.OBJ에 관한 글에서 썼던 예제를 가져와 .OBJ 파일을 불러오는 -코드를 .GLTF를 불러오는 코드로 바꾸겠습니다.

-

아래의 기존 코드를

-
const mtlLoader = new MTLLoader();
-mtlLoader.loadMtl('resources/models/windmill/windmill-fixed.mtl', (mtl) => {
-  mtl.preload();
-  mtl.materials.Material.side = THREE.DoubleSide;
-  objLoader.setMaterials(mtl);
-  objLoader.load('resources/models/windmill/windmill.obj', (event) => {
-    const root = event.detail.loaderRootNode;
-    scene.add(root);
-    ...
-  });
-});
-
-

.GLTF를 불러오는 코드로 바꿉니다.

-
{
-  const gltfLoader = new GLTFLoader();
-  const url = 'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf';
-  gltfLoader.load(url, (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-    ...
-  });
-
-

자동으로 카메라의 시야를 조정하는 코드는 그대로 두었습니다.

-

모듈이 바뀌었으니 import 문도 변경해야 합니다. OBJLoader를 제거하고 GLTFLoader를 -추가합니다.

-
-import { LoaderSupport } from 'three/addons/loaders/LoaderSupport.js';
--import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
--import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
-+import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
-
-

이제 실행해보죠.

-

- -

-

이런 걸 마법이라고 하나봅니다. 텍스처를 비롯해 모든 게 한 번에 완성됐네요.

-

여기에 자동차가 도로를 따라 달리도록 할 수 있다면 더 멋있겠습니다. 먼저 장면(scene)에서 -차가 별도의 요소인지 확인하고, 별도의 요소라면 이 요소를 다룰 수 있는 방법을 찾아야 합니다.

-

먼저 간단하게 함수를 만들어 씬 그래프를 자바스크립트 콘솔에 -띄워보겠습니다.

-
function dumpObject(obj, lines = [], isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

씬을 전부 불러온 뒤, 만든 함수를 호출합니다.

-
const gltfLoader = new GLTFLoader();
-gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-  const root = gltf.scene;
-  scene.add(root);
-  console.log(dumpObject(root).join('\n'));
-
-

코드를 실행하니 아래와 같은 결과가 -나왔습니다.

-
OSG_Scene [Scene]
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    └─RootNode_(model_correction_matrix) [Object3D]
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        └─RootNode [Object3D]
-          │ ...
-          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-          │ ├─CAR_03_2 [Object3D]
-          │ │ └─CAR_03_2_World_ap_0 [Mesh]
-          │ ├─Car_04_1 [Object3D]
-          │ │ └─Car_04_1_World_ap_0 [Mesh]
-          │ ├─Car_04_2 [Object3D]
-          │ │ └─Car_04_2_World_ap_0 [Mesh]
-          │ ├─Car_04_3 [Object3D]
-          │ │ └─Car_04_3_World_ap_0 [Mesh]
-          │ ├─Car_04_4 [Object3D]
-          │ │ └─Car_04_4_World_ap_0 [Mesh]
-          │ ├─Car_08_4 [Object3D]
-          │ │ └─Car_08_4_World_ap8_0 [Mesh]
-          │ ├─Car_08_3 [Object3D]
-          │ │ └─Car_08_3_World_ap9_0 [Mesh]
-          │ ├─Car_04_1_2 [Object3D]
-          │ │ └─Car_04_1_2_World_ap_0 [Mesh]
-          │ ├─Car_08_2 [Object3D]
-          │ │ └─Car_08_2_World_ap11_0 [Mesh]
-          │ ├─CAR_03_1_2 [Object3D]
-          │ │ └─CAR_03_1_2_World_ap_0 [Mesh]
-          │ ├─CAR_03_2_2 [Object3D]
-          │ │ └─CAR_03_2_2_World_ap_0 [Mesh]
-          │ ├─Car_04_2_2 [Object3D]
-          │ │ └─Car_04_2_2_World_ap_0 [Mesh]
-          ...
-
-

살펴보니 모든 자동차는 "Cars"라는 부모의 자식이네요.

-
*          ├─Cars [Object3D]
-          │ ├─CAR_03_1 [Object3D]
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ ├─CAR_03 [Object3D]
-          │ │ └─CAR_03_World_ap_0 [Mesh]
-          │ ├─Car_04 [Object3D]
-          │ │ └─Car_04_World_ap_0 [Mesh]
-
-

간단히 테스트를 해봅시다. 먼저 "Cars"의 자식 요소 전부를 Y축을 기준으로 -회전시켜보겠습니다.

-

장면을 불러온 뒤, "Cars" 요소를 참조해 변수로 저장합니다.

-
+let cars;
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-+    cars = root.getObjectByName('Cars');
-
-

그리고 render 함수 안에서 cars의 자식 요소를 전부 회전시킵니다.

-
+function render(time) {
-+  time *= 0.001;  // convert to seconds
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (cars) {
-+    for (const car of cars.children) {
-+      car.rotation.y = time;
-+    }
-+  }
-
-  renderer.render(scene, camera);
-
-  requestAnimationFrame(render);
-}
-
-

잘 작동하는지 볼까요?

-

- -

-

음... 기준축이 제각각인 것을 보니 이 파일을 만든 디자이너가 애니메이션까지 -고려하지는 않은 듯합니다. 트럭들이 전부 이상한 방향으로 도네요.

-

이처럼 3D 프로젝트를 진행할 때는 목적에 따라 개체를 디자인해야 합니다. 그래야 -기준축이나, 크기 등이 제대로 적용될 테니까요.

-

저는 디자이너도 아니고 블렌더를 그다지 잘 하지도 못하기에, 편법을 사용하겠습니다. -각각의 자동차에 별도의 Object3D를 만들어 자동차를 이 Object3D의 자식으로 -지정할 겁니다. 이러면 자동차가 아닌 Object3D로 차를 움직일 수 있고, 자동차의 -기준축도 별도로 설정할 수 있죠.

-

아까 봤던 씬 그래프를 다시 보니 자동차의 종류는 총 3개인 듯합니다. "Car_08", -"CAR_03", "Car_04" 이렇게요. 종류별로 조정했을 때 제대로 적용되는지 봅시다.

-

아래의 코드는 각 자동차를 새로운 Object3D의 자식으로 지정하고, 이 Object3D를 -장면에 추가한 뒤, 자동차의 종류별로 기준축을 정렬합니다. 그리고 새로 만든 -Object3Dcars 배열에 추가하죠.

-
-let cars;
-+const cars = [];
-{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
--    cars = root.getObjectByName('Cars');
-+    const loadedCars = root.getObjectByName('Cars');
-+    const fixes = [
-+      { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
-+      { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
-+      { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+    ];
-+
-+    root.updateMatrixWorld();
-+    for (const car of loadedCars.children.slice()) {
-+      const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-+      const obj = new THREE.Object3D();
-+      car.getWorldPosition(obj.position);
-+      car.position.set(0, 0, 0);
-+      car.rotation.set(...fix.rot);
-+      obj.add(car);
-+      scene.add(obj);
-+      cars.push(obj);
-+    }
-     ...
-
-

이제 기준축이 제대로 정렬되었습니다.

-

- -

-

이제 자동차를 달리게 만들어봅시다.

-

간단한 이동 시스템이라고 해도 튜토리얼에서 다루기에는 다소 복잡합니다. 대신 -도로 전체를 달리는 뒤얽힌 경로를 만들어 자동차를 해당 경로에 놓을 수는 있죠. -아래 스크린샷은 경로를 반쯤 완성했을 때 블렌더의 화면을 캡쳐한 것입니다.

-
- -

이제 블렌더에서 데이터를 추출해야 합니다. 다행히 경로만을 골라 내보낼 수 있네요. -"write nurbs"를 체크해 경로를 .OBJ 파일로 내보냅니다.

-
- -

.OBJ 파일을 열어보니 각 정점 데이터가 있습니다. 이를 배열로 바꿔 사용하도록 -하죠.

-
const controlPoints = [
-  [1.118281, 5.115846, -3.681386],
-  [3.948875, 5.115846, -3.641834],
-  [3.960072, 5.115846, -0.240352],
-  [3.985447, 5.115846, 4.585005],
-  [-3.793631, 5.115846, 4.585006],
-  [-3.826839, 5.115846, -14.736200],
-  [-14.542292, 5.115846, -14.765865],
-  [-14.520929, 5.115846, -3.627002],
-  [-5.452815, 5.115846, -3.634418],
-  [-5.467251, 5.115846, 4.549161],
-  [-13.266233, 5.115846, 4.567083],
-  [-13.250067, 5.115846, -13.499271],
-  [4.081842, 5.115846, -13.435463],
-  [4.125436, 5.115846, -5.334928],
-  [-14.521364, 5.115846, -5.239871],
-  [-14.510466, 5.115846, 5.486727],
-  [5.745666, 5.115846, 5.510492],
-  [5.787942, 5.115846, -14.728308],
-  [-5.423720, 5.115846, -14.761919],
-  [-5.373599, 5.115846, -3.704133],
-  [1.004861, 5.115846, -3.641834],
-];
-
-

Three.js에는 몇 가지 곡선 클래스가 있습니다. 이 경우 CatmullRomCurve3가 -적당하겠네요. 이런 곡선은 각 정점을 지나는 부드러운 곡선을 만든다는 것이 -특징입니다.

-

만약 위 정점으로 곡선을 생성하면 다음 그림과 같은 곡선이 생길 겁니다.

-
- -

모서리가 각지면 좀 더 깔끔할 듯하네요. 정점을 몇 개 더 추가해 원하는 -결과를 만들어봅시다. 각 정점 짝마다 10% 아래에 하나, 두 정점 사이 90% -지점에 하나를 새로 만들어 CatmullRomCurve3에 넘겨주겠습니다.

-

우리가 원하는 곡선은 다음과 같죠.

-
- -

아래는 곡선을 생성하는 코드입니다.

-
let curve;
-let curveObject;
-{
-  const controlPoints = [
-    [1.118281, 5.115846, -3.681386],
-    [3.948875, 5.115846, -3.641834],
-    [3.960072, 5.115846, -0.240352],
-    [3.985447, 5.115846, 4.585005],
-    [-3.793631, 5.115846, 4.585006],
-    [-3.826839, 5.115846, -14.736200],
-    [-14.542292, 5.115846, -14.765865],
-    [-14.520929, 5.115846, -3.627002],
-    [-5.452815, 5.115846, -3.634418],
-    [-5.467251, 5.115846, 4.549161],
-    [-13.266233, 5.115846, 4.567083],
-    [-13.250067, 5.115846, -13.499271],
-    [4.081842, 5.115846, -13.435463],
-    [4.125436, 5.115846, -5.334928],
-    [-14.521364, 5.115846, -5.239871],
-    [-14.510466, 5.115846, 5.486727],
-    [5.745666, 5.115846, 5.510492],
-    [5.787942, 5.115846, -14.728308],
-    [-5.423720, 5.115846, -14.761919],
-    [-5.373599, 5.115846, -3.704133],
-    [1.004861, 5.115846, -3.641834],
-  ];
-  const p0 = new THREE.Vector3();
-  const p1 = new THREE.Vector3();
-  curve = new THREE.CatmullRomCurve3(
-    controlPoints.map((p, ndx) => {
-      p0.set(...p);
-      p1.set(...controlPoints[(ndx + 1) % controlPoints.length]);
-      return [
-        (new THREE.Vector3()).copy(p0),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.1),
-        (new THREE.Vector3()).lerpVectors(p0, p1, 0.9),
-      ];
-    }).flat(),
-    true,
-  );
-  {
-    const points = curve.getPoints(250);
-    const geometry = new THREE.BufferGeometry().setFromPoints(points);
-    const material = new THREE.LineBasicMaterial({color: 0xff0000});
-    curveObject = new THREE.Line(geometry, material);
-    scene.add(curveObject);
-  }
-}
-
-

코드의 첫 블럭에서 곡선을 만듭니다. 두 번째 블럭에서는 곡선에서 250개의 -정점을 받은 뒤, 이 정점들을 이어 곡선을 시각화합니다.

-

하지만 예제를 실행하니 곡선이 보이지 -않습니다. 일단 어디에 있는지 확인하기 위해 깊이 테스트(depth test) 옵션을 -끄고, 마지막에 렌더링하도록 설정하겠습니다.

-
    curveObject = new THREE.Line(geometry, material);
-+    material.depthTest = false;
-+    curveObject.renderOrder = 1;
-
-

다시 예제를 실행해보니 곡선이 너무 작은 게 문제였네요.

-
- -

블렌더로 계층 구조를 확인해보니 디자이너가 자동차 부모의 스케일(scale)을 -건드렸습니다.

-
- -

실제 3D 앱에서 스케일을 건드리는 것은 좋지 않습니다. 갖은 문제를 일으켜 -개발자를 좌절의 굴레에 빠지게 하거든요. 디자이너 입장에서야 각각의 크기를 -직접 수정하는 것보다 전체의 스케일을 조정하는 게 훨씬 편하겠지만, 실제 3D -앱 프로젝트에 참여한다면 디자이너에게 스케일을 건드리지 말라고 요청하기 -바랍니다. 만약 디자이너가 스케일을 수정해야만 하는 경우라면, 앱을 만들 때 -스케일을 무시할 수 있도록 정점에까지 스케일을 적용할 수 있는 방법을 찾아야 -합니다.

-

이 예제의 경우는 스케일뿐만 아니라 자동차들의 회전값과 위치값까지 Cars -요소의 영향을 받습니다. 이러면 자동차가 돌아다니게 만들기가 훨씬 어렵죠. -물론 예제의 경우 차를 전역 공간 안에서 움직여야 하기에 어려움이 있지만, -지역 공간에서만 무언가를 조작하는 경우, 예를 들어 지구를 도는 달을 구현하는 -경우는 이런 것이 큰 걸림돌이 되진 않습니다.

-

씬 그래프를 출력하기 위해 썼던 코드를 다시 가져와 이번에는 각 요소의 -위치값(position), 회전값(rotation), 크기값(scale)까지 출력해봅시다.

-
+function dumpVec3(v3, precision = 3) {
-+  return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
-+}
-
-function dumpObject(obj, lines, isLast = true, prefix = '') {
-  const localPrefix = isLast ? '└─' : '├─';
-  lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
-+  const dataPrefix = obj.children.length
-+     ? (isLast ? '  │ ' : '│ │ ')
-+     : (isLast ? '    ' : '│   ');
-+  lines.push(`${prefix}${dataPrefix}  pos: ${dumpVec3(obj.position)}`);
-+  lines.push(`${prefix}${dataPrefix}  rot: ${dumpVec3(obj.rotation)}`);
-+  lines.push(`${prefix}${dataPrefix}  scl: ${dumpVec3(obj.scale)}`);
-  const newPrefix = prefix + (isLast ? '  ' : '│ ');
-  const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
-    const isLast = ndx === lastNdx;
-    dumpObject(child, lines, isLast, newPrefix);
-  });
-  return lines;
-}
-
-

코드를 실행하니 -다음과 같은 결과가 나옵니다.

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-        └─RootNode [Object3D]
-          │   pos: 0.000, 0.000, 0.000
-          │   rot: 0.000, 0.000, 0.000
-          │   scl: 1.000, 1.000, 1.000
-          ├─Cars [Object3D]
-*          │ │   pos: -369.069, -90.704, -920.159
-*          │ │   rot: 0.000, 0.000, 0.000
-*          │ │   scl: 1.000, 1.000, 1.000
-          │ ├─CAR_03_1 [Object3D]
-          │ │ │   pos: 22.131, 14.663, -475.071
-          │ │ │   rot: -3.142, 0.732, 3.142
-          │ │ │   scl: 1.500, 1.500, 1.500
-          │ │ └─CAR_03_1_World_ap_0 [Mesh]
-          │ │       pos: 0.000, 0.000, 0.000
-          │ │       rot: 0.000, 0.000, 0.000
-          │ │       scl: 1.000, 1.000, 1.000
-
-

이제 보니 기존 장면의 Cars에 있던 회전값과 크기값이 자식에게 옮겨갔네요. -파일을 열었을 때와 렌더링했을 때의 데이터가 다른 이유는 아마 디자이너가 -.GLTF 파일을 만들 때 쓴 프로그램이 무언가를 건드렸거나, 디자이너가 .blend -파일에서 조금 수정한 버젼으로 .GLTF 파일을 만들었기 때문일 겁니다.

-

진작 .blend 파일을 받아 직접 .GLTF 파일을 만들었더라면 좋았을 거라는 생각이 -듭니다. 내보내기 전에 주요 요소를 점검해 불필요한 설정을 제거했으면 더 -좋았을 텐데 말이죠.

-

아래의 이 요소들도

-
OSG_Scene [Scene]
-  │   pos: 0.000, 0.000, 0.000
-  │   rot: 0.000, 0.000, 0.000
-  │   scl: 1.000, 1.000, 1.000
-  └─RootNode_(gltf_orientation_matrix) [Object3D]
-    │   pos: 0.000, 0.000, 0.000
-    │   rot: -1.571, 0.000, 0.000
-    │   scl: 1.000, 1.000, 1.000
-    └─RootNode_(model_correction_matrix) [Object3D]
-      │   pos: 0.000, 0.000, 0.000
-      │   rot: 0.000, 0.000, 0.000
-      │   scl: 1.000, 1.000, 1.000
-      └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
-        │   pos: 0.000, 0.000, 0.000
-        │   rot: 1.571, 0.000, 0.000
-        │   scl: 1.000, 1.000, 1.000
-
-

전부 불필요한 것들이고요.

-

위치값도, 회전값도, 크기값도 없는 하나의 "root" 요소가 있는 게 더 이상적입니다. -런타임에 루트 요소의 자식을 전부 꺼내 장면 자체의 자식으로 지정하는 것은 어떨까요? -"Cars"와 루트 요소가 자동차를 찾는 데 도움이 될 수는 있으나, 이 역시 별도의 위치값, -회전값, 크기값이 없는 게 나으니 간단히 장면을 자동차의 부모로 지정하는 것은요?

-

가장 최선의 해결책은 아니지만, 곡선 자체의 크기를 키우는 게 가장 빠른 해결책이긴 -합니다.

-

일단 저는 마지막 해결책을 선택하겠습니다.

-

먼저 곡선의 위치를 옮겨 적당한 위치에 둔 뒤 곡선을 숨깁니다.

-
{
-  const points = curve.getPoints(250);
-  const geometry = new THREE.BufferGeometry().setFromPoints(points);
-  const material = new THREE.LineBasicMaterial({color: 0xff0000});
-  curveObject = new THREE.Line(geometry, material);
-+  curveObject.scale.set(100, 100, 100);
-+  curveObject.position.y = -621;
-+  curveObject.visible = false;
-  material.depthTest = false;
-  curveObject.renderOrder = 1;
-  scene.add(curveObject);
-}
-
-

다음으로 자동차가 곡선을 따라 달리도록 코드를 작성합니다. 자동차마다 곡선에 비례해 -0에서 1사이의 위치를 정한 뒤, curveObject를 이용해 전역 공간에서의 위치값을 -구합니다. 그리고 곡선의에서 조금 더 낮은 값을 구한 뒤, looAt 메서드를 이용해 -자동차가 이 점을 바라보도록 설정하고, 자동차를 위치값과 방금 구한 점 중간에 둡니다.

-
// 경로를 계산할 때 쓸 Vector3 객체를 생성합니다
-const carPosition = new THREE.Vector3();
-const carTarget = new THREE.Vector3();
-
-function render(time) {
-  ...
-
--  for (const car of cars) {
--    car.rotation.y = time;
--  }
-
-+  {
-+    const pathTime = time * .01;
-+    const targetOffset = 0.01;
-+    cars.forEach((car, ndx) => {
-+      // 0에서 1사이의 값으로, 자동차의 간격을 균일하게 배치합니다
-+      const u = pathTime + ndx / cars.length;
-+
-+      // 첫 번째 점을 구합니다
-+      curve.getPointAt(u % 1, carPosition);
-+      carPosition.applyMatrix4(curveObject.matrixWorld);
-+
-+      // 곡선을 따라 첫 번째 점보다 조금 낮은 두 번째 점을 구합니다
-+      curve.getPointAt((u + targetOffset) % 1, carTarget);
-+      carTarget.applyMatrix4(curveObject.matrixWorld);
-+
-+      // (임시로) 자동차를 첫 번째 점에 둡니다
-+      car.position.copy(carPosition);
-+      // 자동차가 두 번째 점을 바라보게 합니다
-+      car.lookAt(carTarget);
-+
-+      // 차를 두 점 중간에 둡니다
-+      car.position.lerpVectors(carPosition, carTarget, 0.5);
-+    });
-+  }
-
-

실행시켜보니 자동차의 높이 기준도 제각기네요. 각 자동차의 위치값을 조금씩 수정하겠습니다.

-
const loadedCars = root.getObjectByName('Cars');
-const fixes = [
--  { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
--  { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
--  { prefix: 'Car_04', rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_08', y: 0,  rot: [Math.PI * .5, 0, Math.PI * .5], },
-+  { prefix: 'CAR_03', y: 33, rot: [0, Math.PI, 0], },
-+  { prefix: 'Car_04', y: 40, rot: [0, Math.PI, 0], },
-];
-
-root.updateMatrixWorld();
-for (const car of loadedCars.children.slice()) {
-  const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
-  const obj = new THREE.Object3D();
-  car.getWorldPosition(obj.position);
--  car.position.set(0, 0, 0);
-+  car.position.set(0, fix.y, 0);
-  car.rotation.set(...fix.rot);
-  obj.add(car);
-  scene.add(obj);
-  cars.push(obj);
-}
-
-

- -

-

몇 분 투자한 것 치고는 괜찮은 결과물이네요!

-

마지막으로 그림자까지 추가하면 완벽할 것 같습니다.

-

그림자에 관한 글DirectionalLight 그림자 예제를 가져와 -그대로 코드에 붙여 넣습니다.

-

그리고 파일을 불러온 뒤, 모든 요소의 그림자 설정을 켜줍니다.

-
{
-  const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
-    const root = gltf.scene;
-    scene.add(root);
-
-+    root.traverse((obj) => {
-+      if (obj.castShadow !== undefined) {
-+        obj.castShadow = true;
-+        obj.receiveShadow = true;
-+      }
-+    });
-
-

그런데 그림자 헬퍼가 하나도 나타나지 않습니다. renderer의 그림자 설정을 -켜주지 않았기 때문이죠.

-
renderer.shadowMap.enabled = true;
-
-

이 간단한 걸 해결하느라 무려 4시간이 걸렸다는 건 비밀입니다. 😭

-

그리고 DirectionLight의 그림자용 카메라가 장면 전체를 투사하도록 절두체를 -조정합니다. 다음과 같이요.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-+  light.castShadow = true;
-*  light.position.set(-250, 800, -850);
-*  light.target.position.set(-550, 40, -450);
-
-+  light.shadow.bias = -0.004;
-+  light.shadow.mapSize.width = 2048;
-+  light.shadow.mapSize.height = 2048;
-
-  scene.add(light);
-  scene.add(light.target);
-+  const cam = light.shadow.camera;
-+  cam.near = 1;
-+  cam.far = 2000;
-+  cam.left = -1500;
-+  cam.right = 1500;
-+  cam.top = 1500;
-+  cam.bottom = -1500;
-...
-
-

마지막으로 배경색을 옅은 하늘색으로 설정합니다.

-
const scene = new THREE.Scene();
--scene.background = new THREE.Color('black');
-+scene.background = new THREE.Color('#DEFEFF');
-
-

- -

-

이 글이 씬 그래프를 포함한 파일을 불러오고, 몇몇 문제를 해결하는 데 도움이 -되었으면 합니다.

-

.blend 파일과 .gltf 파일을 비교해보면 재미있는 점이 하나 있습니다. .blend -파일에는 몇 가지 조명 요소가 있지만 씬 그래프로 변환하면 더 이상 조명의 역할을 -하지 못한다는 거죠. .GLTF 파일은 단순한 JSON 형태의 파일이기에 쉽게 내용을 -열어 볼 수 있습니다. .GLTF에는 여러 배열이 있고 이 배열의 요소를 참조할 때는 -인덱스값을 사용하죠. 기능을 확장하기에 쉬운 형식이라고는 해도, 다른 3D 형식과 -마찬가지로 존재하는 모든 기능을 지원하지는 못합니다.

-

때문에 항상 추가 데이터가 필요합니다. 아까 자동차가 따라갈 경로를 따로 내보낸 -것도 한 예죠. 경로까지 .GLTF 파일에 포함하는 게 이상적이긴 하나, 그러려면 -내보내기 규칙도 작성해야 하고, 규칙을 적용하기 위해 각 요소에 이름을 따로 -부여하든지, 네이밍 스키마를 사용하든지, 하여간 데이터를 앱에서 사용하기 위해 -무언가 해야 합니다.

-

어떤 게 가장 좋은 방법일까요? 제 생각에 이건 전적으로 여러분이 풀어나가야 할 -숙제입니다. 상황에 따라서 많이 달라질 테니까 말이죠.

- -
-
-
- - - - - - - - diff --git a/manual/ko/load-obj.html b/manual/ko/load-obj.html deleted file mode 100644 index 030af4757784d2..00000000000000 --- a/manual/ko/load-obj.html +++ /dev/null @@ -1,598 +0,0 @@ - - - 에서 .OBJ 파일 불러오기 - - - - - - - - - - - - - - -
-
-

에서 .OBJ 파일 불러오기

-
-
-
-

Three.js로 프로젝트를 진행할 때, 3D 모델 파일을 불러와 사용하는 것은 -아주 흔한 일입니다. 오늘은 주로 사용하는 파일 형식인 .OBJ 파일을 -불러오는 법에 대해 알아보겠습니다.

-

인터넷을 검색해 CC-BY-NC 3.0 풍자 3D 모델을 -하나 가져왔습니다(작가: ahedov).

-
- -

다운받은 파일 형식이 .blend네요. 블렌더(Blender)로 -파일을 열어 .OBJ 형식으로 변환하겠습니다.

-
- -
-

블렌더는 다른 프로그램과 다른 점이 많아 낯설게 느껴질 수 있습니다. -블렌더를 처음 접한다면, 글 읽기를 잠시 멈추고 블렌더의 기본 UI 가이드를 -먼저 읽어보길 권장합니다.

-

추가로 보통 3D 프로그램은 수천 가지 기능을 지원하는 거대 함선과 같습니다. -프로그램들 중에서도 복잡하기로 유명하죠. 1996년, 제가 3D Studio Max를 처음 -배우기 시작했을 때 저는 하루에 몇 시간씩 3주를 들여 공식 매뉴얼의 70% 정도를 -정독했습니다. 그리고 그게 몇 년 뒤 마야(Maya)를 배울 때 도움이 많이 됐죠. 3D -모델을 만들든, 기존 모델을 수정하든, 3D 프로그램으로 무언가를 하고 싶다면 강의나 -튜토리얼에 따로 시간을 투자하기 바랍니다.

-
-

특별한 일이 없다면 저는 파일을 내보낼 때 아래의 옵션을 사용합니다.

-
- -

자 이제 한 번 화면에 띄워보죠!

-

조명에 관한 글에서 썼던 예제를 가져와 이 예제를 -반구광(hemisphere light) 예제와 합칩니다. 그러면 장면에는 HemisphereLight -하나, DirectionalLight 하나가 있는 셈입니다. 또 GUI 관련 코드와 정육면체, -구체 관련 코드도 지웁니다.

-

다음으로 먼저 OBJLoader 모듈을 스크립트에 로드합니다.

-
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
-
-

OBJLoader의 인스턴스를 생성한 뒤 .OBJ 파일의 경로와 콜백 함수를 넘겨 -load 메서드를 실행합니다. 그리고 콜백 함수에서 불러온 모델을 장면에 -추가합니다.

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-    scene.add(root);
-  });
-}
-
-

어떤 결과가 나올까요?

-

- -

-

뭔가 성공한 듯하지만 재질(materials)이 없어 오류가 납니다. .OBJ 파일에도 -재질이 없고 따로 재질을 지정하지도 않았기 때문이죠.

-

위에서 생성한 .OBJ 로더에는 이름 : 재질 쌍을 객체로 지정할 수 있습니다. -.OBJ 파일을 불러올 때, 이름이 지정되었다면 로더에 지정한 재질 중에 이름(키)과 -일치하는 재질을 찾아 사용하고, 재질을 찾지 못했다면 기본 재질을 사용하죠.

-

.OBJ 파일을 생성할 때 재질에 대한 데이터를 담은 .MTL 파일이 같이 생성되기도 -합니다. 방금의 경우에도 .MTL 파일이 같이 생성되었죠. MTL 파일은 ASCII 인코딩이므로 -일반 텍스트 파일처럼 열어볼 수 있습니다.

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
-map_Bump windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
-map_Bump windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

파일을 살펴보면 2개의 재질과 5개의 jpg 텍스처가 보이는데, 텍스처 파일은 -디렉토리 내에 보이지 않습니다. 대체 어디에 있는 걸까요?

-
- -

생성된 거라고는 .OBJ 파일 하나와 .MTL 파일 하나 뿐입니다.

-

사실 방금 사용한 모델의 텍스처는 .blend 파일에 포함되어 있습니다. -File->External Data->Unpack All Into Files를 선택하고

-
- -

Write Files to Current Directory를 선택해 텍스처를 별도 파일로 -내보낼 수 있습니다.

-
- -

이러면 .blend 파일과 같은 경로의 textures 폴더 안에 텍스처 파일이 -생성됩니다.

-
- -

내보낸 텍스처를 복사해 .OBJ 파일과 같은 경로에 두겠습니다.

-
- -

이제 .MTL 파일에서 사용할 텍스처를 생성했으니 .MTL 파일을 불러오도록 합시다.

-

MTLLoader 모듈을 불러옵니다.

-
import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
-+import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
-
-

-

우선 .MTL 파일을 불러와 MtlObjBridge로 재질을 만듭니다. 그리고 OBJLoader -인스턴스에 방금 만든 재질을 추가한 뒤 .OBJ 파일을 불러옵니다.

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
-+    mtl.preload();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      scene.add(root);
-    });
-+  });
-}
-
-

- -

-

얼핏 제대로 불러온 것 같지만 아직 부족한 점이 있습니다. 모델을 이리저리 -회전시켜 보면 풍차의 날개 뒷면이 사라지는 것을 볼 수 있을 겁니다.

-
- -

재질에 관한 글을 읽었다면 원인이 무엇인지 알 -겁니다. 일단 풍차의 날개 양면을 모두 렌더링하도록 설정해야 겠네요. .MTL -파일을 직접 수정하기는 어렵습니다. 그렇다면 쉽게 떠올릴 수 있는 방법은 -3가지 정도죠.

-
    -
  1. 모든 재질을 불러온 뒤 반복문으로 처리한다.

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.preload();
    -   for (const material of Object.values(mtl.materials)) {
    -     material.side = THREE.DoubleSide;
    -   }
    -   ...
    -

    문제가 해결되긴 하겠지만, 양면 렌더링은 단면 렌더링에 비해 성능이 느립니다. -양면일 필요가 있는 재질만 양면으로 렌더링하는 게 이상적이겠죠.

    -
  2. -
  3. 특정 재질을 골라 설정한다.

    -

    .MTL 파일에는 "windmill", "Material" 2개의 재질이 있습니다. 여러 번의 시도와 -에러 끝에 날개가 "Material"이라는 이름의 재질을 쓴다는 것을 알아낸 뒤, 이 재질에만 -양면 속성을 설정할 수도 있을 겁니다.

    -
     const mtlLoader = new MTLLoader();
    - mtlLoader.load('resources/models/windmill/windmill.mtl', (mtl) => {
    -   mtl.preload();
    -   mtl.materials.Material.side = THREE.DoubleSide;
    -   ...
    -
  4. -
  5. .MTL 파일의 한계에 굴복하고 직접 재질을 만든다.

    -
     objLoader.load('resources/models/windmill/windmill.obj', (root) => {
    -   const materials = {
    -     Material: new THREE.MeshPhongMaterial({...}),
    -     windmill: new THREE.MeshPhongMaterial({...}),
    -   };
    -   root.traverse(node => {
    -     const material = materials[node.material?.name];
    -     if (material) {
    -       node.material = material;
    -     }
    -   })
    -   scene.add(root);
    - });
    -
  6. -
-

뭘 선택하든 그건 여러분의 선택입니다. 1번이 가장 간단하고, 3번이 가장 -확장성이 좋죠. 2번은 그 중간입니다. 지금은 2번 해결책을 사용하도록 하죠.

-

해결책을 적용하면 날개가 제대로 보일 겁니다. 하지만 문제가 하나 더 남았습니다. -모델을 확대해보면 텍스처가 굉장히 각져 보일 거예요.

-
- -

뭐가 문제일까요?

-

텍스처 파일 중에는 NOR, 법선 맵(NORmal map)이라는 이름이 붙은 파일이 있습니다. -이 파일이 바로 법선 맵이죠. 범프 맵(bump map)이 흑백이라면 법선 맵은 보통 -자주색을 띱니다. 범프 맵이 표면의 높이를 나타낸다면 법선 맵은 표면의 방향을 -나타내죠.

-
- -

MTLLoader의 소스 코드를 -살펴보면 법선 맵의 키(key)가 norm이어야 한다고 합니다. 간단히 .MTL 파일을 -수정해보죠.

-
# Blender MTL File: 'windmill_001.blend'
-# Material Count: 2
-
-newmtl Material
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_lopatky_COL.jpg
--map_Bump windmill_001_lopatky_NOR.jpg
-+norm windmill_001_lopatky_NOR.jpg
-
-newmtl windmill
-Ns 0.000000
-Ka 1.000000 1.000000 1.000000
-Kd 0.800000 0.800000 0.800000
-Ks 0.000000 0.000000 0.000000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 1
-map_Kd windmill_001_base_COL.jpg
--map_Bump windmill_001_base_NOR.jpg
-+norm windmill_001_base_NOR.jpg
-map_Ns windmill_001_base_SPEC.jpg
-
-

이제 법선 맵이 정상적으로 적용되었고, 날개의 뒷면도 제대로 보입니다.

-

- -

-

다른 파일도 불러와봅시다.

-

인터넷을 뒤져 CC-BY-NC -풍차 3D 모델을 발견했습니다(작가: Roger Gerzner / GERIZ.3D Art).

-
- -

.OBJ 형식으로 다운 받을 수 있으므로, 해당 형식으로 받아 불러오겠습니다(잠깐 -.MTL 로더를 제거했습니다).

-
-  objLoader.load('resources/models/windmill/windmill.obj', ...
-+  objLoader.load('resources/models/windmill-2/windmill.obj', ...
-
-

- -

-

음, 아무것도 나타나지 않습니다. 뭐가 문제일까요? 모델의 원래 크기 때문일까요? -Three.js로부터 모델 사이즈를 구해 카메라를 한 번 업데이트해보겠습니다.

-

먼저 Three.js가 방금 불러온 모델을 감싸는 육면체를 계산해 모델의 크기와 중심점을 -구하는 코드를 작성합니다.

-
objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-  scene.add(root);
-
-+  const box = new THREE.Box3().setFromObject(root);
-+  const boxSize = box.getSize(new THREE.Vector3()).length();
-+  const boxCenter = box.getCenter(new THREE.Vector3());
-+  console.log(boxSize);
-+  console.log(boxCenter);
-
-

자바스크립트 콘솔을 확인해보면 아래와 -같은 결과가 보일 겁니다.

-
size 2123.6499788469982
-center p { x: -0.00006103515625, y: 770.0909731090069, z: -3.313507080078125 }
-
-

이 카메라는 현재 near 0.1, far가 100 이므로 약 100칸 정도를 투사합니다. -땅도 40x40칸인데 이 모델은 2000칸이죠. 카메라의 시야보다 훨씬 크니 절두체 영역 -밖에 있는 게 당연합니다.

-
- -

수작업으로 고칠 수도 있지만, 카메라가 장면의 크기를 자동으로 감지하도록 만들어보겠습니다. -방금 모델의 크기를 구할 때 썼던 육면체를 이용하면 되겠네요. 카메라의 위치를 정하는 데 -정해진 방법은 없습니다. 경우에 따라 카메라의 방향과 위치가 다르니 그때 그때 상황에 -맞춰 방법을 찾아야 하죠.

-

카메라에 관해 배운 내용을 떠올려봅시다. 카메라를 만들려면 -절두체를 정의해야 하죠. 절두체는 fov(시야각, field of view), near, far 속성을 -지정해 정의합니다. 시야각이 얼마이든, 절두체가 무한히 늘어난다고 가정할 때, 장면을 -둘러싼 육면체가 절두체 안에 들어오게 하려면 카메라를 얼마나 멀리 보내야 할까요? 그러니까 -near가 0.00000001이고 far가 무한대라 가정했을 때 말이죠.

-

다행히 시야각과 육면체의 크기를 아니 다음 그림과 같은 삼각형을 사용할 수 있습니다.

-
- -

그림에서 왼쪽은 카메라이고, 카메라에서 뻗어나온 파란 절두체가 풍차를 투사합니다. -방금 풍차를 둘러싼 육면체의 위치값을 계산했죠. 이제 얼마나 카메라를 멀리 보내야 -육면체가 절두체 안에 들어올지 계산해야 합니다.

-

절두체의 시야각과 육면체의 크기를 구했으니, 기본 삼각함수와 *SOHCAHTOA를 -이용해 카메라와 육면체의 거리(distance)를 구할 수 있습니다.

-

※ SOH-CAH-TOA: 한국에서 삼각함수를 배울 때 얼싸안코와 비슷한 식으로 외우듯, -영미권에도 삼각함수를 배울 때 Sin = Opposite(대변) 나누기 Hypotenuse(빗변), -Cos = Adjacent(밑변) 나누기 Hypotenuse, Tan = Oppsite 나누기 Adjacent와 같은 -식으로 외웁니다. 이를 줄여서 SOH-CAH-TOA(소-카-토아)라고 부릅니다. 역주.

-
- -

그림을 기반으로 계산식을 짜보겠습니다.

-
distance = halfSizeToFitOnScreen / tangent(halfFovY) // 거리 = 화면 크기의 반 / 탄젠트(시야각의 절반)
-
-

이제 위 계산식을 코드로 옮겨야 합니다. 먼저 distance(거리)를 구한 뒤 -카메라를 육면체의 중심에서 distance값만큼 옮깁니다. 그리고 카메라가 육면체의 -center(중심)을 바라보게 설정합니다.

-
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-
-  // 육면체의 중심에서 카메라가 있는 곳으로 향하는 방향 벡터를 계산합니다
-  const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-
-  // 방향 벡터에 따라 카메라를 육면체로부터 일정 거리에 위치시킵니다
-  camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
-
-  // 육면체를 투사할 절두체를 near와 far값으로 정의합니다
-  camera.near = boxSize / 100;
-  camera.far = boxSize * 100;
-
-  camera.updateProjectionMatrix();
-
-  // 카메라가 육면체의 중심을 바라보게 합니다
-  camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
-}
-
-

이 함수는 boxSizesizeToFitOnScreen, 두 개의 크기값을 매개변수로 받습니다. -boxSize 값으로 sizeToFitOnScreen 값을 대체할 수도 있지만, 이러면 육면체가 -화면에 꽉 차게 됩니다. 조금 여유가 있는 편이 보기 편하므로 조금 더 큰 값을 넘겨주도록 -하겠습니다.

-
{
-  const objLoader = new OBJLoader();
-  objLoader.load('resources/models/windmill_2/windmill.obj', (root) => {
-    scene.add(root);
-+    // 모든 요소를 포함하는 육면체를 계산합니다
-+    const box = new THREE.Box3().setFromObject(root);
-+
-+    const boxSize = box.getSize(new THREE.Vector3()).length();
-+    const boxCenter = box.getCenter(new THREE.Vector3());
-+
-+    // 카메라가 육면체를 완전히 감싸도록 설정합니다
-+    frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-+
-+    // 마우스 휠 이벤트가 큰 크기에 대응하도록 업데이트합니다
-+    controls.maxDistance = boxSize * 10;
-+    controls.target.copy(boxCenter);
-+    controls.update();
-  });
-}
-
-

위 예제에서는 boxSize * 1.2 값을 넘겨주어 20% 정도 빈 공간을 더 만들었습니다. -또 카메라가 장면의 중심을 기준으로 회전하도록 OrbitControls도 업데이트했죠.

-

이제 코드를 실행하면...

-

- -

-

성공했습니다. 마우스로 장면을 드래그하면 풍차가 보일 거예요. 하지만 카메라가 풍차의 -정면이 아닌 아래쪽을 먼저 보여줍니다. 이는 풍차가 너무 커서 육면체의 중심이 약 -(0, 770, 0)인데, 카메라를 육면체의 중심에서 기존 위치 (0, 10, 20) 방향으로 distance만큼 -옮겼기에 풍차의 아래쪽에 카메라가 위치하게 된 것입니다.

-
- -

카메라의 기존 위치에 상관없이 육면체의 중심을 기준으로 카메라를 배치해보겠습니다. -단순히 카메라와 육면체 간 벡터의 y 요소를 0으로 만들면 됩니다. y 요소를 0으로 -만든 뒤 벡터를 정규화(normalize)하면, XZ 면에 평행한 벡터, 그러니까 바닥에 평행한 -벡터가 되겠죠.

-
-// 육면체의 중심에서 카메라가 있는 곳으로 향하는 방향 벡터를 계산합니다
--const direction = (new THREE.Vector3()).subVectors(camera.position, boxCenter).normalize();
-+// 카메라와 육면체 사이의 방향 벡터를 항상 XZ 면에 평행하게 만듭니다
-+const direction = (new THREE.Vector3())
-+    .subVectors(camera.position, boxCenter)
-+    .multiply(new THREE.Vector3(1, 0, 1))
-+    .normalize();
-
-

풍차의 아랫면을 보면 작은 정사각형이 하나 보일 겁니다. 원래 땅으로 썼던 평면이죠.

-
- -

원래 땅은 40x40칸이었으니 풍차에 비해 훨씬 작은 것이 당연합니다. 풍차의 크기는 -2000칸이 넘습니다. 땅을 풍차에 맞게 키워야 겠네요. 또 크기만 키우면 체크무늬가 -너무 작아 확대하지 않는 한 보기가 어려울 테니 체스무늬 한 칸의 크기도 키우겠습니다.

-
-const planeSize = 40;
-+const planeSize = 4000;
-
-const loader = new THREE.TextureLoader();
-const texture = loader.load('resources/images/checker.png');
-texture.wrapS = THREE.RepeatWrapping;
-texture.wrapT = THREE.RepeatWrapping;
-texture.magFilter = THREE.NearestFilter;
--const repeats = planeSize / 2;
-+const repeats = planeSize / 200;
-texture.repeat.set(repeats, repeats);
-
-

- -

-

이제 재질을 다시 붙여봅시다. 이전 모델과 마찬가지로 텍스처에 대한 데이터를 담은 -.MTL 파일이 보입니다. 하지만 동시에 다른 문제도 보이네요.

-
 $ ls -l windmill
- -rw-r--r--@ 1 gregg  staff       299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff    142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_diffuse.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 20  2009 windmill_normal.tga
- -rw-r--r--@ 1 gregg  staff  12582956 Apr 19  2009 windmill_spec.tga
-
-

어마어마하게 큰 TARGA (.tga) 파일이 있습니다.

-

THREE.js에 TGA 로더가 있기는 하나 대부분의 경우 이를 사용하는 건 좋지 않습니다. -아주 소수의 경우, 예를 들어 사용자가 임의의 3D 모델 파일을 불러와 확인할 수 있는 -뷰어를 만든다거나 하는 경우라면 TGA 파일을 사용할 수도 있죠.(*)

-

TGA 파일의 문제점 중 하나는 압축을 거의 하지 않는다는 점입니다. TGA는 아주 간단한 -압축만 지원하죠. 파일의 크기가 모두 같을 확률은 매우 희박하니, 위 파일들은 아예 -압축이 되지 않았다고 볼 수 있습니다. 게다가 파일 하나당 무려 12 메가바이트!! 저 -파일을 그대로 사용한다면 사용자는 풍차 하나를 보기 위해 36MB의 데이터를 다운받아야 -하는 셈이 됩니다.

-

또한 브라우저가 TGA를 지원하지 않기에, .JPG나 .PNG 파일보다 로딩 시간이 훨씬 느릴 -겁니다.

-

확신하건데, 이 경우 .JPG 파일로 변환하는 게 가장 좋은 선택입니다. TGA 파일은 알파값이 -없는 RGB 3개의 채널로 구성되죠. JPG도 채널 3개만 사용하니 딱 적당합니다. 또 JPG는 손실 -압축을 사용하기에 파일 용량을 훨씬 많이 줄일 수 있습니다.

-

파일을 열어보니 각각 해상도가 2048x2048입니다. 쓰기에 따라 다르겠지만, 저는 이게 다소 -낭비라는 생각에 해상도를 1024x1024로 낯추고 포토샵의 퀄리티 설정을 50%로 지정했습니다. -다시 파일 구조를 살펴보죠.

-
 $ ls -l ../threejs.org/manual/examples/resources/models/windmill
- -rw-r--r--@ 1 gregg  staff     299 May 20  2009 windmill.mtl
- -rw-r--r--@ 1 gregg  staff  142989 May 20  2009 windmill.obj
- -rw-r--r--@ 1 gregg  staff  259927 Nov  7 18:37 windmill_diffuse.jpg
- -rw-r--r--@ 1 gregg  staff   98013 Nov  7 18:38 windmill_normal.jpg
- -rw-r--r--@ 1 gregg  staff  191864 Nov  7 18:39 windmill_spec.jpg
-
-

36MB에서 0.55MB가 되었네요! 물론 디자너이너의 생각은 다를 수 있으니 절충안을 -찾기 전에 상의를 하는 것이 좋습니다.

-

이제 .MTL 파일을 열어 .TGA 파일 경로를 .JPG 파일로 바꿉니다. 다행히 .MTL 파일은 -텍스트라 수정이 어렵지 않습니다.

-
newmtl blinn1SG
-Ka 0.10 0.10 0.10
-
-Kd 0.00 0.00 0.00
-Ks 0.00 0.00 0.00
-Ke 0.00 0.00 0.00
-Ns 0.060000
-Ni 1.500000
-d 1.000000
-Tr 0.000000
-Tf 1.000000 1.000000 1.000000
-illum 2
--map_Kd windmill_diffuse.tga
-+map_Kd windmill_diffuse.jpg
-
--map_Ks windmill_spec.tga
-+map_Ks windmill_spec.jpg
-
--map_bump windmill_normal.tga
--bump windmill_normal.tga
-+map_bump windmill_normal.jpg
-+bump windmill_normal.jpg
-
-

텍스처의 용량을 최적화했으니 이제 불러올 일만 남았습니다. 먼저 아까 했던 것처럼 -재질을 불러와 OBJLoader에 지정합니다.

-
{
-+  const mtlLoader = new MTLLoader();
-+  mtlLoader.load('resources/models/windmill_2/windmill-fixed.mtl', (mtl) => {
-+    mtl.preload();
-+    const objLoader = new OBJLoader();
-+    objLoader.setMaterials(mtl);
-    objLoader.load('resources/models/windmill/windmill.obj', (root) => {
-      root.updateMatrixWorld();
-      scene.add(root);
-      // 모든 요소를 포함하는 육면체를 계산합니다
-      const box = new THREE.Box3().setFromObject(root);
-
-      const boxSize = box.getSize(new THREE.Vector3()).length();
-      const boxCenter = box.getCenter(new THREE.Vector3());
-
-      // 카메라가 육면체를 완전히 감싸도록 설정합니다
-      frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
-
-      // 마우스 휠 이벤트가 큰 크기에 대응하도록 업데이트합니다
-      controls.maxDistance = boxSize * 10;
-      controls.target.copy(boxCenter);
-      controls.update();
-    });
-+  });
-}
-
-

결과를 확인했는데 문제가 발생했습니다. 여러분에게 직접 보여주기보다 하나하나 -짚어보도록 하죠.

-

문제 #1: 3개의 MTLLoader가 각각 디퓨즈(diffuse) 색과 디퓨즈 텍스처 맵으로 -혼합하는 재질을 만듬.

-

이는 유용한 기능이지만, .MTL 파일의 디퓨즈 색상은 0입니다.

-
Kd 0.00 0.00 0.00
-
-

(텍스처 맵 * 0 = 검정)이죠. 모델링 프로그램에서는 디퓨즈 텍스처 맵과 디퓨즈 색을 혼합하지 -않아도 모델이 제대로 보입니다. 이 풍차를 만든 디자이너 입장에서는 이 파일이 문제가 -없다고 생각하는 것이 당연하죠.

-

.MTL 파일을 다음과 같이 수정해 문제를 해결할 수 있습니다.

-
Kd 1.00 1.00 1.00
-
-

(텍스처 맵 * 1 = 텍스처 맵)이니까요.

-

문제 #2: 스페큘러(specular) 색이 검정임.

-

Ks로 시작하는 줄은 스페큘러 색을 나타냅니다. 이 역시 디자이너가 사용한 모델링 -프로그램이 디퓨즈 맵처럼 뭔가 다른 처리를 해주었을 겁니다. Three.js는 스페큘러 -색을 얼마나 많이 반사할지 결정할 때 스페큘러 맵의 빨강(red) 채널만 사용하기는 -하나, 3가지 색상 채널을 모두 지정하긴 해야 합니다.

-

디퓨즈 색과 마찬가지로 .MTL 파일을 다음과 같이 수정하겠습니다.

-
-Ks 0.00 0.00 0.00
-+Ks 1.00 1.00 1.00
-
-

문제 #3: windmill_normal.jpg가 법선 맵이 아닌 범프 맵임.

-

마찬가지로 .MTL 파일을 수정해줍니다.

-
-map_bump windmill_normal.jpg
--bump windmill_normal.jpg
-+norm windmill_normal.jpg
-
-

위 변경 사항을 모두 반영하면 재질이 정상적으로 적용될 겁니다.

-

- -

-

모델을 불러올 때 주의해야 하는 점을 몇 가지만 적어보겠습니다.

-
    -
  • 크기를 알아야 한다

    -

    예제에서는 카메라가 장면 전체를 감싸도록 했지만, 이게 항상 최적의 해결책이 될 수는 없습니다. -직접 모델을 만들거나, 모델을 다운받아 3D 프로그램으로 크기를 조절하는 것이 더 이상적인 방법입니다.

    -
  • -
  • 잘못된 방향축

    -

    Three.js에서는 보통 Y축이 위쪽입니다. 모델링 프로그램에서는 Z축이 위쪽인 경우, Y축이 위쪽인 경우, 직접 -설정할 수 있는 경우 등 경우가 다양하죠. 모델을 불러왔는데 방향이 잘못되었다면, 모델을 불러온 후 방향을 -바꾸거나(권장하지 않음), 3D 프로그램이나 커맨드 라인 프로그램으로 모델을 원하는 방향으로 맞출 수 있습니다. -브라우저에서 이미지를 쓸 때와 마찬가지로, 이미지를 수정하는 코드를 넣는 것보다는 이미지를 다운받아 이미지 -자체를 편집하는 게 더 나을 겁니다. 블렌더에서는 아예 파일을 내보낼 때 방향을 바꿀 수 있습니다.

    -
  • -
  • .MTL 파일이 없거나 재질 또는 지원하지 않는 값이 있는 경우

    -

    위 예제를 만들 때 .MTL 파일 덕에 재질을 만드는 수고는 덜었지만, 몇 가지 문제가 있었습니다. 문제를 해결하기 -위해 직접 .MTL 파일을 수정했고요. 파일을 열어 .OBJ 파일 안에 어떤 재질이 있는지 확인하거나, Three.js로 -.OBJ 파일을 불러와 재질을 전부 출력하도록 하는 것은 꽤 자주 있는 일입니다. 그런 후에 .MTL 파일 대신 직접 -재질을 만들어 적절한 이름/재질 쌍의 객체로 로더에 넘겨주거나, 장면을 렌더링한 뒤 테스트하면서 문제를 수정하는 -것이죠.

    -
  • -
  • 고용량 텍스처

    -

    3D 모델은 주로 건축, 영화나 광고, 게임 등에서 사용합니다. 건축이나 영화 같은 분야라면 텍스처의 용량을 -신경 쓸 필요는 없죠. 반면 게임의 경우는 메모리도 제한적이고 로컬 환경에서 구동되기에 신경을 꽤 써야 합니다. -웹 페이지의 경우는 빠르게 불러와야 하니 용량이 퀄리티가 너무 떨어지지 않는 선에서 최대한 작은 게 좋죠. -첫 번째로 쓴 풍차의 경우, 실제로 사용하려면 텍스처를 손볼 필요가 있습니다. 지금은 총 용량이 무려 10MB가 -넘거든요!!!

    -

    또한 텍스처에 관한 글에서 말했듯, 텍스처의 해상도도 고려해야 합니다. 50KB짜리 -4096x4096 JPG 이미지는 불러오는 속도는 빠를지 몰라도 굉장히 많은 메모리를 차지할 테니까요.

    -
  • -
-

마지막으로 풍차가 돌아가는 것을 보여주고 싶지만, .OBJ 파일에는 계층 구조가 없습니다. 다시 말해 풍차의 모든 -요소를 기본적으로 1개의 mesh로 취급한다는 것이죠. 풍차의 날개를 건물에서 분리할 수 없기에 날개를 회전시킬 -수가 없습니다.

-

이런 이유로 .OBJ는 그다지 좋은 파일 형식이라고 하기 어렵습니다. 추측하건데 .OBJ 형식을 자주 사용하는 이유는 -사용법이 간단하고, 복잡한 기능이 필요 없는 경우가 많기 때문일 겁니다. 예를 들어 건축 디자인을 하는 경우, -대부분 애니메이션이 필요 없기에 장면에 정적 요소를 추가하는 게 더 좋을 수 있죠.

-

.gLTF는 .OBJ보다 더 많은 기능을 지원합니다. 다음 글에서는 이 gLTF 장면을 불러오는 법에 대해 알아보겠습니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/material-table.html b/manual/ko/material-table.html deleted file mode 100644 index bf8f1b2a4440a0..00000000000000 --- a/manual/ko/material-table.html +++ /dev/null @@ -1,48 +0,0 @@ - - - 재질(Material) 속성표 - - - - - - - - - - - - - - -
-
-

재질(Material) 속성표

-
-
-
-

Three.js에서 주로 쓰는 재질(material)은 Mesh 재질입니다. 아래는 각 재질이 지원하는 속성을 표로 나타낸 것입니다.

-
-
- - -
- - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/materials.html b/manual/ko/materials.html deleted file mode 100644 index 1fe12cf2ad00ee..00000000000000 --- a/manual/ko/materials.html +++ /dev/null @@ -1,317 +0,0 @@ - - - 재질(Materials) - - - - - - - - - - - - - - -
-
-

재질(Materials)

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글을 -읽고 오길 권장합니다.

-

Three.js에는 기본으로 제공하는 재질(materials) 몇 개가 있습니다. -재질이란, 물체가 씬(scene)에 어떤 식으로 나타날지를 결정하는 요소로서, -어떤 재질을 사용할지는 전적으로 상황에 따라 판단해야 합니다.

-

재질의 속성(property)를 정하는 방법은 크게 두 가지로 나뉩니다. 하나는 -이전처럼 생성자를 호출할 때 값을 넘겨주는 것이고,

-
const material = new THREE.MeshPhongMaterial({
-  color: 0xFF0000,    // 빨강 (CSS처럼 문자열로 넘겨줄 수도 있음. "#ff0000")
-  flatShading: true,
-});
-
-

다른 하나는 생성한 뒤에 바꾸는 것이죠.

-
const material = new THREE.MeshPhongMaterial();
-material.color.setHSL(0, 1, .5);  // 빨강
-material.flatShading = true;
-
-

물론 HSL 색상 모델 외에 rgb, hex 등 다양한 방법으로 색을 지정할 -수 있습니다.

-
material.color.set(0x00FFFF);    // CSS의 #RRGGBB 형식
-material.color.set(cssString);   /* CSS 색상 문자열, 예를 들어 'purple', '#F32',
-                                  * 'rgb(255, 127, 64)',
-                                  * 'hsl(180, 50%, 25%)' 등
-                                  */
-material.color.set(someColor)    // THREE.Color에 정의된 static 색상
-material.color.setHSL(h, s, l)   // hsl 색상, 0부터 1까지
-material.color.setRGB(r, g, b)   // rgb 색상, 0부터 1까지
-
-

생성시에도 hex 값 또는 CSS 문자열을 전달해도 됩니다.

-
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000});         // 빨강
-const m2 = new THREE.MeshBasicMaterial({color: 'red'});            // 빨강
-const m3 = new THREE.MeshBasicMaterial({color: '#F00'});           // 빨강
-const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'});   // 빨강
-const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'}); // 빨강
-
-

이제 Three.js의 기본 재질을 살펴보겠습니다.

-

MeshBasicMaterial은 광원의 영향을 받지 않습니다. MeshLambertMaterial은 -정점에서만 광원을 계산하고, MeshPhongMaterial은 픽셀 하나하나 전부 광원을 -계산합니다. 뿐만 아니라 MeshPhongMaterial은 반사점(specular highlights, 물체가 조명을 받을 때 물체에 나타나는 밝은 점. 역주)도 -지원합니다.

-
-
-
-
Basic
-
-
-
-
Lambert
-
-
-
-
Phong
-
-
-
-
-
-
-
-
-
-
-
-
-
-
같은 모델을 로우-폴리(low poly) 모델로 바꾼 것
- -

MeshPhongMaterialshininess 속성으로 반사점의 밝기를 조절할 수 -있습니다(기본값 30).

-
-
-
-
shininess: 0
-
-
-
-
shininess: 30
-
-
-
-
shininess: 150
-
-
- -

만약 MeshLambertMaterial이나 MeshPhongMaterialemissive 속성에 -색상값을 지정하고, (MeshPhongMaterialshininess도 0으로 지정해야함) -color 속성을 검정으로 지정하면 MeshBasicMaterial과 마찬가지로 입체감이 -사라집니다.

-
-
-
-
-
Basic
-
color: 'purple'
-
-
-
-
-
-
Lambert
-
color: 'black'
-
emissive: 'purple'
-
-
-
-
-
-
Phong
-
color: 'black'
-
emissive: 'purple'
-
shininess: 0
-
-
-
- -

MeshPhongMaterialMeshBasicMaterialMeshLambertMaterial을 -구현할 수 있는데 3가지로 분리해 놓았을까요? 이미 감을 잡으셨겠지만, 재질이 -정교할수록 GPU의 부담이 커지기 때문입니다. GPU 성능이 낮은 저사양 기기에서는 -덜 정교한 재질을 씀으로써 GPU의 부담을 줄일 수 있죠. 또한 복잡한 표현이 필요 -없다면 더 간단한 재질을, 광원 효과가 아예 필요 없다면 MeshBasicMaterial을 -사용하는 것이 좋습니다.

-

MeshToonMaterialMeshPhongMaterial과 유사하나, 큰 차이점이 하나 있습니다. -부드럽게 쉐이딩(shading)하는 대신, MeshToonMaterial은 그라디언트 맵(gradient map)을 -사용합니다. 기본적으로 MeshToonMaterial은 처음 70%까지는 밝고 다음 100%까지는 -어두운 그라디언트 맵을 사용하나, 그라디언트 맵을 직접 지정해 줄 수도 있죠. MeshToonMaterial로 -만든 물체는 투톤을 띄어 카툰 느낌을 줍니다.

-
-
-
- -

다음으로 살펴 볼 두 재질은 물리 기반 렌더링을 위한 재질입니다. 물리 기반 렌더링(Physically Based Rendering)은 -줄여서 PBR이라고 하죠.

-

위에서 살펴본 재질들은 재질을 3D처럼 보이게 하기 위해 간단한 수학을 사용하나, -이는 실제 세계와는 다릅니다. 이 두 가지 PBR 재질은 실제 세계에서처럼 물체를 -구현하기 위해 훨씬 복잡한 수학을 사용하죠.

-

첫 번째는 MeshStandardMaterial입니다.MeshPhongMaterialMeshStandardMaterial의 -가장 큰 차이점은 사용하는 속성이 다르다는 점입니다. MeshPhongMaterial은 -shininess를 사용하지만, MeshStandardMaterialroughnessmetalness -두 가지 속성을 사용합니다.

-

roughnessroughness는 -0부터 1까지의 숫자값으로, shininess의 반대입니다. 높은 roughness를 -가진 물체, 예를 들어 야구공은 빛 반사가 거의 없지만, 반대로 낮은 -roughness를 가진 물체, 당구공은 매우 번들번들하죠.

-

metalness는 얼마나 금속성입니다. -얼마나 금속 재질에 가까울 것인가로써, 0은 아예 금속 같지 않은 것이고, -1은 완전히 금속처럼 보이는 것을 의미합니다.

-

아래의 예제는 MeshStandardMaterialroughness를 왼쪽에서 오른쪽으로 -커지게(0 -> 1), metalness를 위에서 아래로 커지게(0 -> 1) 한 것입니다.

-
- -

MeshPhysicalMaterialMeshStandardMaterial과 기본적으로 같지만, -0부터 1까지의 clearcoat 속성으로 표면에 코팅 세기를 설정하고, -clearcoatRoughness 속성으로 코팅의 거침 정도를 설정한다는 점이 다릅니다.

-

아래는 위의 예제와 마찬가지로 roughnessmetalness 속성을 주고 -clearcoat 속성과 clearcoatRoughness 속성을 조정할 수 있도록 한 예제입니다.

-
- -

여태까지 살펴본 Three.js의 기본 재질을 성능이 빠른 것부터 나열하면,

-

MeshBasicMaterialMeshLambertMaterialMeshPhongMaterial ➡ -MeshStandardMaterialMeshPhysicalMaterial

-

입니다. 성능 부담이 -클수록 더 현실적인 결과물을 얻을 수 있지만, 저사양 지원을 위해서는 코드 -최적화에 그만큼 신경을 써야 합니다.

-

또 특수한 경우에 사용하는 세 가지 재질이 있습니다. ShadowMaterial은 -그림자로부터 데이터를 가져오는 데 사용하죠. 아직 그림자에 대해서는 다루지 -않았지만, 그림자에 대해서 살펴볼 때 씬 뒤에서 무슨 일이 일어나는지 -자세히 살펴볼 것입니다.

-

MeshDepthMaterial은 각 픽셀의 깊이를 렌더링합니다. 카메라의 마이너스 -near에 위치한 픽셀은 0으로, 마이너스 -far에 위치한 픽셀은 1로 렌더링하죠. 이 재질을 -사용해 구현할 수 있는 것에 대해서는 다른 글에서 나중에 다뤄보겠습니다.

-
-
-
-
-
- -

MeshNormalMaterialgeometry법선(normals)을 보여줍니다. -법선이란 특정한 삼각형이나 픽셀이 가리키는 방향을 의미하죠. -MeshNormalMaterial은 카메라를 기반으로 법선을 렌더링합니다. -x축은 빨강, -y축은 초록, -z축은 파랑이죠. -다시 말해 오른쪽 면은 분홍, -왼쪽 면은 청녹, -위쪽 면은 청녹, -아래쪽 면은 자주, -정면은 연보라가 됩니다.

-
-
-
-
-
- -

ShaderMaterialRawShaderMaterial은 재질을 커스텀할 때 사용합니다. -둘의 차이점은 ShaderMaterial은 Three.js의 쉐이더 시스템을 이용하고, -RawShaderMaterial은 아예 Three.js의 도움을 받지 않는다는 점이죠. 둘 -다 짧게 다루기는 어려운 주제로, 나중에 상세하게 다루겠습니다.

-

재질 속성(properties)의 대부분은 Material 클래스에 의해 정의됩니다. -자세한 건 공식 문서를 참고하되, 여기서는 자주 사용하는 -두 가지 속성만 살펴보도록 하죠.

-

flatShading: -물체를 각지게(faceted) 표현할지의 여부입니다. 기본값은 false.

-
-
-
-
flatShading: false
-
-
-
-
flatShading: true
-
-
- -

side: -어떤 면을 렌더링할지의 여부입니다. 기본값은 THREE.FrontSide(앞면). -다른 값으로는 THREE.BackSide(뒷면)THREE.DoubleSide(양면)를 -지정할 수 있습니다. 3D로 렌더링한 물체는 대부분 불투명한 고체이기에, -뒷면(고체의 안쪽면)은 굳이 렌더링할 필요가 없습니다. side 속성을 -별도로 지정하는 경우는 면이나 비-고체 등 뒷면을 렌더링해야 할 경우 -뿐이죠.

-

아래는 각각 THREE.FrontSideTHREE.DoubleSide를 이용해 6개의 -면을 렌더링한 것입니다.

-
-
-
-
side: THREE.FrontSide
-
-
-
-
side: THREE.DoubleSide
-
-
- -

실제 프로젝트에서 재질을 다룰 때는 고려해야 할 것이 훨씬 많습니다. -이 장에서는 아주 기본적인 것만 살펴보았을 뿐이고, 제대로 사용하기 -위해서는 알아야 할 것들이 훨씬 더 많죠. 예를 들어 나중에 살펴볼 -텍스처(textures, 질감)만 추가해도 경우의 수가 엄청나게 늘어납니다. -말 나온 김에 바로 텍스처를 살펴보는 것도 좋지만, 다음 장에서는 잠시 -쉬어가는 의미로 Three.js 개발 환경 구성하기에 -대해 알아보겠습니다.

-
-

material.needsUpdate

-

-이 속성은 사용할 일이 그다지 많진 않으니 참고로 알아두시기 바랍니다. -Three.js는 재질을 사용할 때-해당 재질을 사용하는 물체를 렌더링할 때- -재질의 설정을 적용합니다. 재질을 바꿀 때는 많은 자원이 들어가기에, -Three.js는 기본적으로 처음 한 번만 재질의 설정을 적용합니다. 만약 -재질의 속성(properties)을 런타임에 바꿔야 할 경우, material.needsUpdate = true를 -설정해 Three.js가 변경사항을 반영하도록 해야 하죠. 대표적으로 -needsUpdate를 사용해야 하는 경우는 다음과 같습니다. - -

-
    -
  • flatShading 속성을 변경할 때
  • -
  • 텍스처를 추가/제거할 때 -

    - 단순히 텍스처를 변경할 때는 상관없으나, 아예 텍스처를 사용하지 않다가 - 텍스처를 추가하는 경우, 또는 텍스처를 사용하다가 텍스처를 제거하는 경우 - needsUpdate = true를 설정해주어야 합니다. -

    -

    - 하지만 텍스처를 제거하는 경우, 대게 1x1 하얀색 픽셀 텍스처로 변경하는 게 - 낫습니다. -

  • -
-

-위에서 언급했듯, 대부분의 앱은 이런 경우를 고려할 일이 거의 없습니다. -flatShade 속성을 변경하는 경우는 흔치 않고, 텍스처를 변경하는 -경우는 있어도 물체의 속성이나 색상을 지정하지 않았다가 추가하는 경우는 흔치 않기 -때문입니다. -

-
- -

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/multiple-scenes.html b/manual/ko/multiple-scenes.html deleted file mode 100644 index 3e8a3b4e2b2d7d..00000000000000 --- a/manual/ko/multiple-scenes.html +++ /dev/null @@ -1,649 +0,0 @@ - - - 로 캔버스, 장면 여러 개 만들기 - - - - - - - - - - - - - - -
-
-

로 캔버스, 장면 여러 개 만들기

-
-
-
-

사람들이 자주 하는 질문 중 하나는 Three.js로 여러 개의 캔버스(canvas)를 렌더링하려면 -어떻게 해야 하나요?"입니다. 쇼핑몰 사이트나 3D 도표가 여러 개 있는 웹 페이지를 -제작한다고 해봅시다. 얼핏 그리 어려울 건 없어 보입니다. 그냥 도표가 들어갈 곳마다 -각각 캔버스를 만들고, 각 캔버스마다 Renderer를 생성하면 되지 않을까요?

-

하지만 이 방법을 적용하자마자 문제가 생깁니다.

-
    -
  1. 브라우저의 WebGL 컨텍스트(context)는 제한적이다.

    -

    일반적으로 약 8개가 최대입니다. 9번째 컨텍스트를 만들면 제일 처음에 만들었던 - 컨텍스트가 사라지죠.

    -
  2. -
  3. WebGL 자원은 컨텍스트끼리 공유할 수 없다.

    -

    10MB짜리 모델을 캔버스 두 개에서 사용하려면 모델을 각각 총 두 번 로드해야 하고, - 원래의 두 배인 20MB의 자원을 사용한다는 의미입니다. 컨텍스트끼리는 어떤 것도 공유할 - 수 없죠. 또한 초기화도 두 번, 쉐이더 컴파일도 두 번, 같은 동작은 모두 두 번씩 - 실행해야 합니다. 캔버스의 개수가 많아질수록 성능에 문제가 생기겠죠.

    -
  4. -
-

그렇다면 어떻게 해야 할까요?

-

방법 중 하나는 캔버스 하나로 화면 전체를 채우고, 각 "가상" 캔버스를 대신할 HTML 요소(element)를 -두는 겁니다. Renderer는 하나만 만들되 가상 캔버스에 각각 Scene을 만드는 거죠. 그리고 -가상 HTML 요소의 좌표를 계산해 요소가 화면에 보인다면 Three.js가 해당 장면(scene)을 가상 -요소의 좌표에 맞춰 렌더링하도록 합니다.

-

이 방법은 캔버스를 하나만 사용하므로 위 1번과 2번 문제 모두 해결할 수 있습니다. 컨텍스트를 -하나만 사용하니 WebGL 컨텍스트 제한을 걱정할 일도 없고, 자원을 몇 배씩 더 사용할 일도 없죠.

-

2개의 장면만 만들어 간단히 테스트를 해보겠습니다. 먼저 HTML을 작성합니다.

-
<canvas id="c"></canvas>
-<p>
-  <span id="box" class="diagram left"></span>
-  I love boxes. Presents come in boxes.
-  When I find a new box I'm always excited to find out what's inside.
-</p>
-<p>
-  <span id="pyramid" class="diagram right"></span>
-  When I was a kid I dreamed of going on an expedition inside a pyramid
-  and finding a undiscovered tomb full of mummies and treasure.
-</p>
-
-

다음으로 CSS를 작성합니다.

-
#c {
-  position: fixed;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  display: block;
-  z-index: -1;
-}
-.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-  border: 1px solid black;
-}
-.left {
-  float: left;
-  margin-right: .25em;
-}
-.right {
-  float: right;
-  margin-left: .25em;
-}
-
-

캔버스가 화면 전체를 채우도록 하고 z-index를 -1로 설정해 다른 요소 뒤로 가도록 했습니다. -가상 요소에 컨텐츠가 없어 크기가 0이니 별도의 width와 height도 지정해줬습니다.

-

이제 각각의 카메라와 조명이 있는 장면 2개를 만듭니다. 하나에는 정육면체, 다른 하나에는 -다이아몬드 모양을 넣을 겁니다.

-
function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // 캔버스 기본값
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  return { scene, camera, elem };
-}
-
-function setupScene1() {
-  const sceneInfo = makeScene(document.querySelector('#box'));
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({color: 'red'});
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-function setupScene2() {
-  const sceneInfo = makeScene(document.querySelector('#pyramid'));
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  sceneInfo.scene.add(mesh);
-  sceneInfo.mesh = mesh;
-  return sceneInfo;
-}
-
-const sceneInfo1 = setupScene1();
-const sceneInfo2 = setupScene2();
-
-

이제 각 요소가 화면에 보일 때만 장면을 렌더링할 함수를 만듭니다. Renderer.setScissorTest를 -호출해 가위(scissor) 테스트를 활성화하면 Three.js가 캔버스의 특정 부분만 렌더링하도록 -할 수 있습니다. 그리고 Renderer.setScissor로 가위를 설정한 뒤 Renderer.setViewport로 -장면의 좌표를 설정합니다.

-
function renderSceneInfo(sceneInfo) {
-  const { scene, camera, elem } = sceneInfo;
-
-  // 해당 요소의 화면 대비 좌표를 가져옵니다
-  const { left, right, top, bottom, width, height } =
-      elem.getBoundingClientRect();
-
-  const isOffscreen =
-      bottom < 0 ||
-      top > renderer.domElement.clientHeight ||
-      right < 0 ||
-      left > renderer.domElement.clientWidth;
-
-  if (isOffscreen) {
-    return;
-  }
-
-  camera.aspect = width / height;
-  camera.updateProjectionMatrix();
-
-  const positiveYUpBottom = canvasRect.height - bottom;
-  renderer.setScissor(left, positiveYUpBottom, width, height);
-  renderer.setViewport(left, positiveYUpBottom, width, height);
-
-  renderer.render(scene, camera);
-}
-
-

다음으로 render 함수 안에서 먼저 캔버스 전체를 비운 뒤 각 장면을 렌더링합니다.

-
function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  sceneInfo1.mesh.rotation.y = time * .1;
-  sceneInfo2.mesh.rotation.y = time * .1;
-
-  renderSceneInfo(sceneInfo1);
-  renderSceneInfo(sceneInfo2);
-
-  requestAnimationFrame(render);
-}
-
-

결과를 확인해볼까요?

-

- -

-

첫 번째 <span> 요소가 있는 곳에는 빨간 정육면체가, 두 번째 <span> 요소가 있는 곳에는 -파란 다이아몬드가 보일 겁니다.

-

동기화하기

-

위 코드는 나쁘지 않지만 작은 문제가 있습니다. 복잡한 장면 등 무슨 이유라도 렌더링하는 -데 시간이 오래 걸린다면, 장면의 좌표는 페이지의 다른 컨텐츠에 비해 더디게 내려올 겁니다.

-

각 가상 요소에 테두리를 넣고

-
.diagram {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-+  border: 1px solid black;
-}
-
-

각 장면에 배경색도 넣어줍니다.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color('red');
-
-

그런 다음 빠르게 스크롤을 위아래로 반복해보면 -문제가 보일겁니다. 아래는 스크롤 애니메이션 캡쳐본의 속도를 10배 낮춘 예시입니다.

-
- -

추가로 처리해줘야 할 것이 있긴 하지만, 캔버스의 CSS를 position: fixed에서 position: absolute로 -바꿔 문제를 해결할 수 있습니다.

-
#c {
--  position: fixed;
-+  position: absolute;
-
-

그리고 페이지 스크롤에 상관 없이 캔버스가 항상 화면의 상단에 위치할 수 있도록 캔버스에 -transform 스타일을 지정해줍니다.

-
function render(time) {
-  ...
-
-  const transform = `translateY(${ window.scrollY }px)`;
-  renderer.domElement.style.transform = transform;
-
-

캔버스에 position: fixed를 적용하면 캔버스는 스크롤의 영향을 받지 않습니다. position: absolute를 -적용하면 렌더링하는 데 시간이 걸리더라도 일단 다른 페이지와 같이 스크롤이 되겠죠. 그리고 -렌더링하기 전에 캔버스를 다시 움직여 화면 전체에 맞춘 뒤 캔버스를 렌더링하는 겁니다. 이러면 -화면의 가장자리에 살짝 렌더링되지 않은 부분이 보일 수는 있어도 나머지 페이지에 있는 요소는 -버벅이지 않고 제자리에 있을 겁니다. 아래는 해당 코드를 적용한 화면의 캡쳐본을 아까와 마찬가지로 -10배 느리게 만든 것입니다.

-
- -

확장하기 쉽게 만들기

-

여러 장면을 구현했으니 이제 이 예제를 좀 더 확장하기 쉽게 만들어보겠습니다.

-

먼저 기존처럼 캔버스 전체를 렌더링하는 render 함수를 두고, 각 장면에 해당하는 가상 요소, -해당 장면을 렌더링하는 함수로 이루어진 객체의 배열을 만듭니다. render 함수에서 가상 요소가 -화면에 보이는지 확인한 뒤, 가상 요소가 화면에 보인다면 상응하는 렌더링 함수를 호출합니다. 이러면 -확장성은 물론 각 장면의 렌더링 함수를 작성할 때도 전체를 신경쓸 필요가 없죠.

-

아래는 전체를 담당하는 render 함수입니다.

-
const sceneElements = [];
-function addScene(elem, fn) {
-  sceneElements.push({ elem, fn });
-}
-
-function render(time) {
-  time *= 0.001;
-
-  resizeRendererToDisplaySize(renderer);
-
-  renderer.setScissorTest(false);
-  renderer.setClearColor(clearColor, 0);
-  renderer.clear(true, true);
-  renderer.setScissorTest(true);
-
-  const transform = `translateY(${ window.scrollY }px)`;
-  renderer.domElement.style.transform = transform;
-
-  for (const { elem, fn } of sceneElements) {
-    // 해당 요소의 화면 대비 좌표를 가져옵니다
-    const rect = elem.getBoundingClientRect();
-    const {left, right, top, bottom, width, height} = rect;
-
-    const isOffscreen =
-        bottom < 0 ||
-        top > renderer.domElement.clientHeight ||
-        right < 0 ||
-        left > renderer.domElement.clientWidth;
-
-    if (!isOffscreen) {
-      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
-      renderer.setScissor(left, positiveYUpBottom, width, height);
-      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-      fn(time, rect);
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

render 함수는 elemfn 속성의 객체로 이루어진 sceneElements 배열을 순회합니다.

-

그리고 각 요소가 화면에 보이는지 확인하고, 화면에 보인다면 fn에 해당 장면이 들어가야할 -사각 좌표와 현재 시간값을 넘겨주어 호출합니다.

-

이제 각 장면을 만들고 상응하는 요소와 렌더링 함수를 추가합니다.

-
{
-  const elem = document.querySelector('#box');
-  const { scene, camera } = makeScene();
-  const geometry = new THREE.BoxGeometry(1, 1, 1);
-  const material = new THREE.MeshPhongMaterial({ color: 'red' });
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-{
-  const elem = document.querySelector('#pyramid');
-  const { scene, camera } = makeScene();
-  const radius = .8;
-  const widthSegments = 4;
-  const heightSegments = 2;
-  const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-  const material = new THREE.MeshPhongMaterial({
-    color: 'blue',
-    flatShading: true,
-  });
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-  addScene(elem, (time, rect) => {
-    camera.aspect = rect.width / rect.height;
-    camera.updateProjectionMatrix();
-    mesh.rotation.y = time * .1;
-    renderer.render(scene, camera);
-  });
-}
-
-

sceneInfo1, sceneInfo2는 더 이상 필요 없으니 제거합니다. 대신 각 mesh의 회전은 해당 -장면에서 처리해야 합니다.

-

- -

-

HTML Dataset 사용하기

-

HTML의 dataset을 -이용하면 좀 더 확장하기 쉬운 환경을 만들 수 있습니다. id="..." 대신 data-diagram="..."을 -이용해 데이터를 직접 HTML 요소에 지정하는 거죠.

-
<canvas id="c"></canvas>
-<p>
--  <span id="box" class="diagram left"></span>
-+  <span data-diagram="box" class="left"></span>
-  I love boxes. Presents come in boxes.
-  When I find a new box I'm always excited to find out what's inside.
-</p>
-<p>
--  <span id="pyramid" class="diagram left"></span>
-+  <span data-diagram="pyramid" class="right"></span>
-  When I was a kid I dreamed of going on an expedition inside a pyramid
-  and finding a undiscovered tomb full of mummies and treasure.
-</p>
-
-

요소의 id를 제거했으니 CSS 셀렉터도 다음처럼 바꾸어야 합니다.

-
-.diagram
-+*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-
-

또한 각 장면을 만드는 코드를 scene initialization functions라는 맵으로 만듭니다. -이 맵은 키값에 대응하는 장면 렌더링 함수를 반환할 겁니다.

-
const sceneInitFunctionsByName = {
-  'box': () => {
-    const { scene, camera } = makeScene();
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-  'pyramid': () => {
-    const { scene, camera } = makeScene();
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

그리고 querySelectorAll로 가상 요소를 전부 불러와 해당 요소에 상응하는 렌더링 함수를 -실행합니다.

-
document.querySelectorAll('[data-diagram]').forEach((elem) => {
-  const sceneName = elem.dataset.diagram;
-  const sceneInitFunction = sceneInitFunctionsByName[sceneName];
-  const sceneRenderFunction = sceneInitFunction(elem);
-  addScene(elem, sceneRenderFunction);
-});
-
-

이제 코드를 확장하기가 한결 편해졌습니다.

-

-

각 요소에 액션 추가하기

-

사용자 액션, 예를 들어 TrackballControls를 추가하는 건 아주 간단합니다. 먼저 스크립트를 -불러옵니다.

-
import { TrackballControls } from 'three/addons/controls/TrackballControls.js';
-
-

그리고 각 장면에 대응하는 요소에 TrackballControls를 추가합니다.

-
-function makeScene() {
-+function makeScene(elem) {
-  const scene = new THREE.Scene();
-
-  const fov = 45;
-  const aspect = 2;  // 캔버스 기본값
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 1, 2);
-  camera.lookAt(0, 0, 0);
-+  scene.add(camera);
-
-+  const controls = new TrackballControls(camera, elem);
-+  controls.noZoom = true;
-+  controls.noPan = true;
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
--    scene.add(light);
-+    camera.add(light);
-  }
-
--  return { scene, camera };
-+ return { scene, camera, controls };
-}
-
-

위 코드에서는 카메라를 장면에 추가하고, 카메라에 조명을 추가했습니다. 이러면 조명이 카메라를 -따라다니겠죠. TrackballControls는 카메라를 조정하기 때문에 이렇게 해야 빛이 계속 우리가 -바라보는 방향에서 나갑니다.

-

또한 컨트롤을 렌더링 함수에서 업데이트해줘야 합니다.

-
const sceneInitFunctionsByName = {
-- 'box': () => {
--    const {scene, camera} = makeScene();
-+ 'box': (elem) => {
-+    const { scene, camera, controls } = makeScene(elem);
-    const geometry = new THREE.BoxGeometry(1, 1, 1);
-    const material = new THREE.MeshPhongMaterial({color: 'red'});
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
--  'pyramid': () => {
--    const { scene, camera } = makeScene();
-+  'pyramid': (elem) => {
-+    const { scene, camera, controls } = makeScene(elem);
-    const radius = .8;
-    const widthSegments = 4;
-    const heightSegments = 2;
-    const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-    const material = new THREE.MeshPhongMaterial({
-      color: 'blue',
-      flatShading: true,
-    });
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    return (time, rect) => {
-      mesh.rotation.y = time * .1;
-      camera.aspect = rect.width / rect.height;
-      camera.updateProjectionMatrix();
-+      controls.handleResize();
-+      controls.update();
-      renderer.render(scene, camera);
-    };
-  },
-};
-
-

이제 각 물체를 자유롭게 회전시킬 수 있습니다.

-

- -

-

이 기법은 이 사이트 전체에 사용한 기법입니다. 원시 모델에 관한 글과 -재질에 관한 글에서 다양한 예시를 보여주기 위해 사용했죠.

-

다른 방법으로는 화면 밖의 캔버스에서 장면을 렌더링해 각 요소에 2D 캔버스 형태로 넘겨주는 -방법이 있습니다. 이 방법의 장점은 각 영역을 어떻게 분리할지 고민하지 않아도 된다는 것이죠. -위에서 살펴본 방법은 캔버스를 화면 전체의 배경으로 써야 하지만, 이 방법은 일반 HTML 형태로 -사용할 수 있습니다.

-

하지만 이 방법은 각 영역을 복사하는 것이기에 성능이 더 느립니다. 얼마나 느릴지는 브라우저와 -GPU 성능에 따라 다르죠.

-

바꿔야 하는 건 생각보다 많지 않습니다.

-

먼저 배경에서 캔버스 요소를 제거합니다.

-
<body>
--  <canvas id="c"></canvas>
-  ...
-</body>
-
-

CSS도 바꿔줍니다.

-
-#c {
--  position: absolute;
--  left: 0;
--  top: 0;
--  width: 100%;
--  height: 100%;
--  display: block;
--  z-index: -1;
--}
-canvas {
-  width: 100%;
-  height: 100%;
-  display: block;
-}
-*[data-diagram] {
-  display: inline-block;
-  width: 5em;
-  height: 3em;
-}
-
-

캔버스 요소가 부모에 꽉 차도록 변경했습니다.

-

이제 자바스크립트를 변경해봅시다. 먼저 캔버스를 참조할 필요가 없으니 대신 캔버스 요소를 -새로 만듭니다. 또한 가위 테스트를 처음에 활성화합니다.

-
function main() {
--  const canvas = document.querySelector('#c');
-+  const canvas = document.createElement('canvas');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas, alpha: true});
-+  renderer.setScissorTest(true);
-
-  ...
-
-

다음으로 각 장면에 2D 렌더링 컨텍스트를 생성하고 장면에 대응하는 요소에 캔버스를 추가합니다.

-
const sceneElements = [];
-function addScene(elem, fn) {
-+  const ctx = document.createElement('canvas').getContext('2d');
-+  elem.appendChild(ctx.canvas);
--  sceneElements.push({ elem, fn });
-+  sceneElements.push({ elem, ctx, fn });
-}
-
-

만약 렌더링 시 렌더링용 캔버스의 크기가 장면의 크기보다 작을 경우, 렌더링용 캔버스의 크기를 -키웁니다. 또한 2D 캔버스의 크기가 부모 요소와 다르다면 2D 캔버스의 크기를 조정합니다. 마지막으로 -가위와 화면을 설정하고, 해당 장면을 렌더링한 뒤, 요소의 캔버스로 렌더링 결과물을 복사합니다.

-
function render(time) {
-  time *= 0.001;
-
--  resizeRendererToDisplaySize(renderer);
--
--  renderer.setScissorTest(false);
--  renderer.setClearColor(clearColor, 0);
--  renderer.clear(true, true);
--  renderer.setScissorTest(true);
--
--  const transform = `translateY(${ window.scrollY }px)`;
--  renderer.domElement.style.transform = transform;
-
--  for (const { elem, fn } of sceneElements) {
-+  for (const { elem, fn, ctx } of sceneElements) {
-    // 해당 요소의 화면 대비 좌표를 가져옵니다
-    const rect = elem.getBoundingClientRect();
-    const { left, right, top, bottom, width, height } = rect;
-+    const rendererCanvas = renderer.domElement;
-
-    const isOffscreen =
-        bottom < 0 ||
--        top > renderer.domElement.clientHeight ||
-+        top > window.innerHeight ||
-        right < 0 ||
--        left > renderer.domElement.clientWidth;
-+        left > window.innerWidth;
-
-    if (!isOffscreen) {
--      const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
--      renderer.setScissor(left, positiveYUpBottom, width, height);
--      renderer.setViewport(left, positiveYUpBottom, width, height);
-
-+      // 렌더링용 캔버스 크기 조정
-+      if (rendererCanvas.width < width || rendererCanvas.height < height) {
-+        renderer.setSize(width, height, false);
-+      }
-+
-+      // 2D 캔버스의 크기가 요소의 크기와 같도록 조정
-+      if (ctx.canvas.width !== width || ctx.canvas.height !== height) {
-+        ctx.canvas.width = width;
-+        ctx.canvas.height = height;
-+      }
-+
-+      renderer.setScissor(0, 0, width, height);
-+      renderer.setViewport(0, 0, width, height);
-
-      fn(time, rect);
-
-+      // 렌더링된 장면을 2D 캔버스에 복사
-+      ctx.globalCompositeOperation = 'copy';
-+      ctx.drawImage(
-+          rendererCanvas,
-+          0, rendererCanvas.height - height, width, height,  // 원본 사각 좌표
-+          0, 0, width, height);                              // 결과물 사각 좌표
-    }
-  }
-
-  requestAnimationFrame(render);
-}
-
-

결과물은 위와 다르지 않습니다.

-

- -

-

이 기법의 다른 장점은 OffscreenCanvas -웹 워커를 이용해 이 기능을 별도 스레드에서 구현할 수 있다는 겁니다. 하지만 아쉽게도 -2020년 7월을 기준으로 OffscreenCanvas는 아직 크로미움 기반 브라우저에서만 지원합니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/offscreencanvas.html b/manual/ko/offscreencanvas.html deleted file mode 100644 index 3b3a64462d0c3e..00000000000000 --- a/manual/ko/offscreencanvas.html +++ /dev/null @@ -1,977 +0,0 @@ - - - OffscreenCanvas - - - - - - - - - - - - - - -
-
-

OffscreenCanvas

-
-
-
-

OffscreenCanvas는 비교적 최근 도입된 브라우저 API로 아직 크로미움 기반 브라우저에서만 사용가능하지만, 갈수록 대부분의 브라우저에서 이 API를 사용할 수 있을 겁니다. OffscreenCanvas를 이용하면 웹 워커(Web Worker)에서 캔버스를 렌더링해 복잡한 3D 장면 등의 무거운 작업을 별도 프로세스에서 처리할 수 있습니다. 이러면 무거운 작업을 처리할 때 브라우저가 덜 버벅이도록 할 수 있죠. 또한 데이터도 워커에서 불러와 처리하므로 페이지 초기 로드 시 버벅임을 훨씬 줄일 수 있습니다.

-

사용법은 꽤나 직관적입니다. 먼저 반응형 디자인에 관한 글에서 썼던 예제를 가져오도록 하죠.

-

이 사이트 대부분의 예제는 스크립트를 해당 HTML 파일에 인라인으로 작성했습니다. 반면에 워커는 일반적으로 별도의 스크립트 파일로 분리해 작성합니다.

-

이 글에서는 offscreencanvas-cubes.js라는 별도 파일을 만들어 반응형 디자인에서 가져온 예제의 자바스크립트 코드를 전부 복사해 넣을 겁니다. 그런 다음 바꿔야할 부분을 바꿔보도록 하죠.

-

하지만 여전히 HTML 파일에 약간의 자바스크립트 코드가 필요합니다. 캔버스 요소를 참조하고 canvas.transferControlToOffscreen 메서드를 호출해 캔버스의 제어권을 offscreen에 넘겨줍니다.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-
-  ...
-
-

그리고 new Worker(워커 스크립트 경로, { type: 'module' })로 워커를 생성한 뒤, 워커에 offscreen 객체를 넘깁니다.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-cubes.js', { type: 'module' });
-  worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-}
-main();
-
-

스크립트를 따로 써야 하는 이유는 워커 안에서는 DOM에 접근할 수 없기 때문입니다. HTML 요소를 참조하거나 DOM 요소의 이벤트를 받을 수도 없죠. 일반적으로 메시지 이벤트를 통해서만 다른 스크립트와 통신할 수 있습니다.

-

워커에 메시지를 보내려면 worker.postMessage에 하나 또는 두 개의 인자를 넘겨주어 호출하면 됩니다. 첫 번째 인자는 워커에 전달할 객체로, 이 객체는 그대로 전달되지 않고 복사됩니다. 두 번째 인자는 옵션으로 첫 번째 인자 중 그대로 전달하기 원하는 객체를 배열로 지정합니다. 여기에 지정한 객체는 복사되지 않죠. 그대로 워커에 전달되지만 객체를 보낸 스크립트에서는 더 이상 사용이 불가능해집니다. 이것도 모든 객체를 전달할 수 있는 게 아니라 특정 타입의 객체만을 전달할 수 있죠. 당연하게도 이 중에는 OffscreenCanvas도 있습니다. 정리하자면 offscreen 객체를 전달하고 나면 이 객체는 이 스크립트에서 더 이상 쓸모가 없어집니다.

-

워커의 message 이벤트를 이용하면 메시지를 받을 수 있습니다. postMessage에서 넘긴 객체는 event.data에 담겨 리스너에 전달되죠. 아까 위 코드에서는 type: 'main' 속성을 객체에 선언해 워커에 넘겨줬습니다. 이 type 속성은 브라우저의 메인 스레드에서는 쓸 일이 없는 값으로, 워커 내에 다른 함수를 호출하는 키값으로 사용할 겁니다. 이러면 메인 스크립트에서 워커 내의 함수를 호출하기가 훨씬 쉬워지겠죠.

-
const handlers = {
-  main,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

type 값을 통해 호출할 함수를 찾고, 함수가 있다면 메인 스크립트에서 넘어온 data를 인자로 넘겨 호출하도록 했습니다.

-

이제 반응형 디자인에 관한 글에서 가져온 예제의 main 함수를 수정해야 합니다.

-

DOM에서 캔버스에 접근하는 대신 이벤트의 data 속성에서 캔버스 요소를 받도록 합니다.

-
-function main() {
--  const canvas = document.querySelector('#c');
-+function main(data) {
-+  const { canvas } = data;
-  const renderer = new THREE.WebGLRenderer({ canvas });
-
-  ...
-
-

워커에서는 DOM에 접근할 수 없다고 했었죠. 마찬가지로 DOM 속성인 canvas.clientWidthcanvas.clientHeight에도 접근할 수 없습니다. resizeRendererToDisplaySize를 그대로 사용할 수 없는 것이죠.

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
-  const width = canvas.clientWidth;
-  const height = canvas.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

대신 캔버스 크기가 변경될 때마다 워커에 메시지를 보낼 겁니다. 워커에 전역 변수를 하나 생성해 여기에 width와 height 값을 지정하도록 하죠.

-
const state = {
-  width: 300,  // 캔버스 기본값
-  height: 150,  // 캔버스 기본값
-};
-
-

그리고 size라는 함수를 만들어 해당 값을 업데이트하도록 합니다.

-
+function size(data) {
-+  state.width = data.width;
-+  state.height = data.height;
-+}
-
-const handlers = {
-  main,
-+  size,
-};
-
-

resizeRendererToDisplaySizestate.widthstate.height를 쓰도록 변경합니다.

-
function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = canvas.clientWidth;
--  const height = canvas.clientHeight;
-+  const width = state.width;
-+  const height = state.height;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-

마찬가지로 종횡비를 계산하는 코드도 DOM 속성 대신 state를 쓰도록 변경합니다.

-
function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-+    camera.aspect = state.width / state.height;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

메인 스크립트로 돌아와 페이지 크기가 바뀔 때마다 워커의 size 함수를 실행하도록 합니다.

-
const worker = new Worker('offscreencanvas-picking.js', { type: 'module' });
-worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-
-+function sendSize() {
-+  worker.postMessage({
-+    type: 'size',
-+    width: canvas.clientWidth,
-+    height: canvas.clientHeight,
-+  });
-+}
-+
-+window.addEventListener('resize', sendSize);
-+sendSize();
-
-

또한 직접 호출해 최초에 한 번 값을 보내도록 합니다.

-

여러분의 브라우저가 OffscreenCanvas를 완벽히 지원한다면 이제 문제 없이 작동할 겁니다. 그렇게 많이 바꾼 것이 없는데도 말이죠. 혹시 모르니 브라우저가 OffscreenCanvas를 지원하지 않을 경우 에러 메시지를 보여주도록 하겠습니다. 먼저 에러 메시지를 표시할 HTML을 작성합니다.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="noOffscreenCanvas" style="display:none;">
-+    <div>no OffscreenCanvas support</div>
-+  </div>
-</body>
-
-

간단한 스타일도 넣어주도록 하죠.

-
#noOffscreenCanvas {
-    display: flex;
-    width: 100%;
-    height: 100%;
-    align-items: center;
-    justify-content: center;
-    background: red;
-    color: white;
-}
-
-

그리고 캔버스 요소에 transferControlToOffscreen 메서드가 있는지 확인해 OffscreenCanvas의 지원 여부를 확인합니다.

-
function main() {
-  const canvas = document.querySelector('#c');
-+  if (!canvas.transferControlToOffscreen) {
-+    canvas.style.display = 'none';
-+    document.querySelector('#noOffscreenCanvas').style.display = '';
-+    return;
-+  }
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-picking.js'. { type: 'module' });
-  worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-
-  ...
-
-

브라우저가 OffscreenCanvas를 지원한다면 문제 없이 작동할 겁니다.

-

- -

-

하지만 현재 모든 브라우저가 OffscreenCanvas를 지원하는 것은 아닙니다. OffscreenCanvas를 지원할 경우에만 워커를 사용하도록 하고, 그렇지 않을 경우에는 기존처럼 메인 스크립트에서 렌더링을 처리하도록 하겠습니다.

-
-

OffscreenCanvas를 단순히 페이지를 반응형으로 만드는 데 사용하는 건 의미없어 보일 수 있습니다. 메인 스크립트에서 반응형을 처리할 때보다 워커에서 처리할 때 오히려 작업이 더 많이 들 수 있거든요. 하지만 메인 스크립트만 사용할 때보다 워커를 사용할 때 자원을 더 넉넉하게 활용할 수 있다는 건 분명합니다. 전적으로 여러분이 상황에 따라 결정할 문제라는 것이죠.

-
-

먼저 Three.js 관련 코드를 분리해 워커 관련 코드와 그렇지 않은 코드로 나눠야 합니다. 같은 코드를 메인 스크립트와 워커에서 모두 쓸 수 있도록 말이죠. 아래와 같이 3개의 파일로 나뉠 겁니다.

-
    -
  1. html 파일.

    -

    threejs-offscreencanvas-w-fallback.html

    -
  2. -
  3. three.js 관련 자바스크립트 파일.

    -

    shared-cubes.js

    -
  4. -
  5. 워커용 스크립트

    -

    offscreencanvas-worker-cubes.js

    -
  6. -
-

shared-cubes.jsoffscreencanvas-worker-cubes.js는 단순히 이전 offscreencanvas-cubes.js 파일을 쪼갠 것입니다. 먼저 offscreencanvas-cube.jsshared-cube.js로 옮긴 뒤, 메인 HTML 파일에 이미 main 함수가 있어 main 함수의 이름만 init으로 바꿔야 하죠. 여기에 추가로 initstate 함수를 export 시켜줘야 합니다.

-
import * as THREE from 'three';
-
--const state = {
-+export const state = {
-  width: 300,   // 캔버스 기본값
-  height: 150,  // 캔버스 기본값
-};
-
--function main(data) {
-+export function init(data) {
-  const { canvas } = data;
-  const renderer = new THREE.WebGLRenderer({ canvas });
-
-

그리고 Three.js와 관련 없는 부분을 잘라냅니다.

-
-function size(data) {
--  state.width = data.width;
--  state.height = data.height;
--}
--
--const handlers = {
--  main,
--  size,
--};
--
--self.onmessage = function(e) {
--  const fn = handlers[e.data.type];
--  if (typeof fn !== 'function') {
--    throw new Error('no handler for type: ' + e.data.type);
--  }
--  fn(e.data);
--};
-
-

방금 잘라낸 부분을 offscreencanvas-worker-cubes.js에 붙여넣고, shared-cubes.js를 import 합니다. 또한 main 대신 init을 호출하도록 합니다.

-
import { init, state } from './shared-cubes.js';
-
-function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-const handlers = {
--  main,
-+  init,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

메인 페이지에서도 마찬가지로 Three.js와 shared-cubes.js를 추가합니다.

-
<script type="module"></script>
-+import { init, state } from './shared-cubes.js';
-
-

이전에 추가했던 에러 메시지용 HTML과 CSS를 제거합니다.

-
<body>
-  <canvas id="c"></canvas>
--  <div id="noOffscreenCanvas" style="display:none;">
--    <div>no OffscreenCanvas support</div>
--  </div>
-</body>
-
-
-#noOffscreenCanvas {
--    display: flex;
--    width: 100%;
--    height: 100%;
--    align-items: center;
--    justify-content: center;
--    background: red;
--    color: white;
--}
-
-

그리고 OffscreenCanvas의 지원 여부에 따라 다른 함수를 실행하도록 합니다.

-
function main() {
-  const canvas = document.querySelector('#c');
--  if (!canvas.transferControlToOffscreen) {
--    canvas.style.display = 'none';
--    document.querySelector('#noOffscreenCanvas').style.display = '';
--    return;
--  }
--  const offscreen = canvas.transferControlToOffscreen();
--  const worker = new Worker('offscreencanvas-picking.js', { type: 'module' });
--  worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-+  if (canvas.transferControlToOffscreen) {
-+    startWorker(canvas);
-+  } else {
-+    startMainPage(canvas);
-+  }
-  ...
-
-

워커를 만들기 위해 사용했던 코드를 전부 startWorker 함수로 옮깁니다.

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-cubes.js', { type: 'module' });
-  worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');
-}
-
-

메시지에 'main' 대신 'init'을 보냅니다.

-
-  worker.postMessage({ type: 'main', canvas: offscreen }, [ offscreen ]);
-+  worker.postMessage({ type: 'init', canvas: offscreen }, [ offscreen ]);
-
-

워커를 사용할 수 없는 경우 다음과 같이 실행합니다.

-
function startMainPage(canvas) {
-  init({ canvas });
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');
-}
-
-

이제 OffscreenCanvas를 지원하는 경우에만 OffscreenCanvas를 사용하고, 지원하지 않는 경우에는 메인 스레드에서 직접 렌더링합니다.

-

- -

-

어떤가요? 생각했던 것보다 쉽지 않나요? 여기에 피킹(picking)을 추가해봅시다. 피킹에 관한 글RayCaster 예제에서 코드 일부를 가져오도록 하겠습니다.

-

먼저 shared-cube.js의 코드를 shared-picking.js로 복사한 뒤, 피킹 예제에서 PickHelper를 가져옵니다.

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // 이미 다른 물체를 피킹했다면 색을 복원합니다
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // 절두체 안에 광선을 쏩니다
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // 광선과 교차하는 물체들을 배열로 만듭니다
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // 첫 번째 물체가 제일 가까우므로 해당 물체를 고릅니다
-      this.pickedObject = intersectedObjects[0].object;
-      // 기존 색을 저장해둡니다
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // emissive 색을 빨강/노랑으로 빛나게 만듭니다
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-const pickPosition = { x: 0, y: 0 };
-const pickHelper = new PickHelper();
-
-

pickPosition은 마우스 포인터의 좌표를 기록하는 역할입니다. 이벤트를 통해 해당 속성을 업데이트하도록 했었죠.

-
function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // Y축을 뒤집었음
-}
-window.addEventListener('mousemove', setPickPosition);
-
-

워커는 포인터 좌표에 직접 접근할 수 없기에, 반응형 처리에 사용했던 코드처럼 포인터 좌표를 메시지로 보내야 합니다. 먼저 size 함수와 마찬가지로 mouse 함수를 만들어 pickPosition을 업데이트하도록 합니다.

-
function size(data) {
-  state.width = data.width;
-  state.height = data.height;
-}
-
-+function mouse(data) {
-+  pickPosition.x = data.x;
-+  pickPosition.y = data.y;
-+}
-
-const handlers = {
-  init,
-+  mouse,
-  size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

그리고 메인 페이지에 분기 함수를 만들어 워커 또는 메인 페이지로 좌표 데이터를 보내도록 합니다.

-
+let sendMouse;
-
-function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-picking.js', { type: 'module' });
-  worker.postMessage({ type: 'init', canvas: offscreen }, [ offscreen ]);
-
-+  sendMouse = (x, y) => {
-+    worker.postMessage({
-+      type: 'mouse',
-+      x,
-+      y,
-+    });
-+  };
-
-  function sendSize() {
-    worker.postMessage({
-      type: 'size',
-      width: canvas.clientWidth,
-      height: canvas.clientHeight,
-    });
-  }
-
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-function startMainPage(canvas) {
-  init({ canvas });
-
-+  sendMouse = (x, y) => {
-+    pickPosition.x = x;
-+    pickPosition.y = y;
-+  };
-
-  function sendSize() {
-    state.width = canvas.clientWidth;
-    state.height = canvas.clientHeight;
-  }
-  window.addEventListener('resize', sendSize);
-  sendSize();
-
-  console.log('using regular canvas');  /* eslint-disable-line no-console */
-}
-
-

다음으로 마우스 이벤트 관련 코드를 메인 페이지로 옮긴 뒤 sendMouse 함수를 쓰도록 수정합니다.

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // Y축을 뒤집었음
-+  sendMouse(
-+      (pos.x / canvas.clientWidth ) *  2 - 1,
-+      (pos.y / canvas.clientHeight) * -2 + 1);  // Y축을 뒤집었음
-}
-
-function clearPickPosition() {
-  /**
-   * 마우스의 경우는 항상 위치가 있어 그다지 큰
-   * 상관이 없지만, 터치 같은 경우 사용자가 손가락을
-   * 떼면 피킹을 멈춰야 합니다. 지금은 일단 어떤 것도
-   * 선택할 수 없는 값으로 지정해두었습니다
-   **/
--  pickPosition.x = -100000;
--  pickPosition.y = -100000;
-+  sendMouse(-100000, -100000);
-}
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-window.addEventListener('touchstart', (event) => {
-  event.preventDefault(); // 스크롤 이벤트 방지
-  setPickPosition(event.touches[0]);
-}, { passive: false });
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

이제 OffscreenCanvas에서도 피킹이 정상적으로 작동할 겁니다.

-

- -

-

좀 더 욕심을 내 OrbitControls까지 추가해봅시다. OrbitControls는 DOM에 꽤 다양하게 접근하기에 처리해줘야 할 것이 좀 많습니다. 제대로 작동하려면 마우스 이벤트, 터치 이벤트, 키보드 이벤트를 모두 처리해줘야 하죠.

-

여태까지는 전역 state 객체를 사용했지만, OrbitControls의 경우는 객체 속성이 너무 많아 그걸 전부 다 하드 코딩하는 건 너무 번거롭습니다. OrbitControls는 필요한 DOM 이벤트의 대부분을 인자로 받는 HTMLElement에 바인딩합니다. 이를 이용해 DOM 요소와 같은 구조의 객체를 넘겨준다면 어떨까요? OrbitControls에 필요한 기능만 살려서 말이죠.

-

OrbitControls의 소스 코드를 분석해보니 아래의 이벤트만 지원하면 될 듯합니다.

-
    -
  • contextmenu
  • -
  • pointerdown
  • -
  • pointermove
  • -
  • pointerup
  • -
  • touchstart
  • -
  • touchmove
  • -
  • touchend
  • -
  • wheel
  • -
  • keydown
  • -
-

마우스 이벤트 중 OrbitControls가 사용하는 속성은 ctrlKey, metaKey, shiftKey, button, pointerType, clientX, clientY, pageX, pageY이고,

-

keydown 이벤트의 경우는 ctrlKey, metaKey, shiftKey, keyCode 속성,

-

wheel 이벤트는 deltaY 속성만,

-

터치 이벤트의 경우는 touches 속성의 pageX, pageY 속성이 필요하네요.

-

이를 처리할 경유(proxy) 객체를 한 쌍 만들어봅시다. 한쪽은 메인 페이지에서 위 이벤트를 받아 필요한 속성을 워커에 넘겨주는 역할을 할 겁니다. 그리고 다른 한쪽은 워커 안에서 이 이벤트를 받아 OrbitControls에 넘겨줄 겁니다. 이벤트 객체가 DOM 이벤트와 같은 구조이기에 OrbitControls는 이 이벤트가 DOM 이벤트가 아니란 걸 눈치채지 못하겠죠.

-

아래는 워커 안의 코드입니다.

-
import { EventDispatcher } from 'three';
-
-class ElementProxyReceiver extends EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-}
-
-

위 코드는 단순히 메시지를 받았을 때 그걸 다시 내보내는(dispatch) 역할을 합니다. 부모 클래스인 EventDispatcher는 DOM 요소처럼 addEventListenerremoveEventListener 메서드를 제공하기에 HTML 요소 대신 이 클래스의 인스턴스를 넘겨줘도 문제없이 작동할 겁니다.

-

ElementProxyReceiver는 하나의 요소만 대신할 수 있습니다. 예제의 경우 하나만 필요하기는 하나 나중에 캔버스를 여러 개 사용할 수도 있으니 여러 ElementProxyReceiver를 관리하는 클래스를 만들겠습니다.

-
class ProxyManager {
-  constructor() {
-    this.targets = {};
-    this.handleEvent = this.handleEvent.bind(this);
-  }
-  makeProxy(data) {
-    const { id } = data;
-    const proxy = new ElementProxyReceiver();
-    this.targets[id] = proxy;
-  }
-  getProxy(id) {
-    return this.targets[id];
-  }
-  handleEvent(data) {
-    this.targets[data.id].handleEvent(data.data);
-  }
-}
-
-

ProxyManager의 인스턴스를 만들고 id값과 함께 makeProxy 메서드를 호출하면 해당 id에만 응답하는 ElementProxyReceiver가 생성됩니다.

-

이제 이 클래스를 기존 워커 코드와 연동해봅시다.

-
const proxyManager = new ProxyManager();
-
-function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-function makeProxy(data) {
-  proxyManager.makeProxy(data);
-}
-
-...
-
-const handlers = {
--  init,
--  mouse,
-+  start,
-+  makeProxy,
-+  event: proxyManager.handleEvent,
-   size,
-};
-
-self.onmessage = function(e) {
-  const fn = handlers[e.data.type];
-  if (typeof fn !== 'function') {
-    throw new Error('no handler for type: ' + e.data.type);
-  }
-  fn(e.data);
-};
-
-

Three.js의 공통 코드에 OrbitControls 모듈도 불러와 설정해야 합니다.

-
import * as THREE from 'three';
-+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-export function init(data) {
--  const { canvas } = data;
-+  const { canvas, inputElement } = data;
-  const renderer = new THREE.WebGLRenderer({ canvas });
-
-+  const controls = new OrbitControls(camera, inputElement);
-+  controls.target.set(0, 0, 0);
-+  controls.update();
-
-

위 코드에서는 이전과 달리 inputElement로 경유 객체를 OrbitControls에 넘겨줬습니다.

-

하는 김에 피킹 이벤트도 경유 객체를 사용하도록 바꿉니다.

-
function getCanvasRelativePosition(event) {
--  const rect = canvas.getBoundingClientRect();
-+  const rect = inputElement.getBoundingClientRect();
-  return {
-    x: event.clientX - rect.left,
-    y: event.clientY - rect.top,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  sendMouse(
--      (pos.x / canvas.clientWidth ) *  2 - 1,
--      (pos.y / canvas.clientHeight) * -2 + 1);  // Y축을 뒤집었음
-+  pickPosition.x = (pos.x / inputElement.clientWidth ) *  2 - 1;
-+  pickPosition.y = (pos.y / inputElement.clientHeight) * -2 + 1;  // Y축을 뒤집었음
-}
-
-function clearPickPosition() {
-  /**
-   * 마우스의 경우는 항상 위치가 있어 그다지 큰
-   * 상관이 없지만, 터치 같은 경우 사용자가 손가락을
-   * 떼면 피킹을 멈춰야 합니다. 지금은 일단 어떤 것도
-   * 선택할 수 없는 값으로 지정해두었습니다
-   **/
--  sendMouse(-100000, -100000);
-+  pickPosition.x = -100000;
-+  pickPosition.y = -100000;
-}
-
-*inputElement.addEventListener('mousemove', setPickPosition);
-*inputElement.addEventListener('mouseout', clearPickPosition);
-*inputElement.addEventListener('mouseleave', clearPickPosition);
-
-*inputElement.addEventListener('touchstart', (event) => {
-  event.preventDefault(); // 스크롤 이벤트 방지
-  setPickPosition(event.touches[0]);
-}, { passive: false });
-
-*inputElement.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-*inputElement.addEventListener('touchend', clearPickPosition);
-
-

메인 페이지에서 위에 열거한 모든 이벤트가 워커로 메시지를 보내도록 합니다.

-
let nextProxyId = 0;
-class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // id를 등록합니다.
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-  }
-}
-
-

ElementProxy는 이벤트를 우회할 요소(element)를 인자로 받습니다. 그리고 고유 id를 생성해 워커에 makeProxy 메시지로 id를 등록합니다. 그러면 아까 만들었듯 워커는 이 id에 새로운 ElementProxyReceiver를 생성하겠죠.

-

다음으로 이벤트를 처리할 핸들러 맵(eventHandlers)을 만듭니다. 이러면 해당 이벤트가 발생했을 때만 워커에 메시지를 보낼 수 있죠.

-

워커를 생성할 때 ElementProxy에 이 핸들러 맵을 넘겨 새 우회 요소를 생성합니다.

-
function startWorker(canvas) {
-  const offscreen = canvas.transferControlToOffscreen();
-  const worker = new Worker('offscreencanvas-worker-orbitcontrols.js', { type: 'module' });
-
-+  const eventHandlers = {
-+    contextmenu: preventDefaultHandler,
-+    mousedown: mouseEventHandler,
-+    mousemove: mouseEventHandler,
-+    mouseup: mouseEventHandler,
-+    pointerdown: mouseEventHandler,
-+    pointermove: mouseEventHandler,
-+    pointerup: mouseEventHandler,
-+    touchstart: touchEventHandler,
-+    touchmove: touchEventHandler,
-+    touchend: touchEventHandler,
-+    wheel: wheelEventHandler,
-+    keydown: filteredKeydownEventHandler,
-+  };
-+  const proxy = new ElementProxy(canvas, worker, eventHandlers);
-  worker.postMessage({
-    type: 'start',
-    canvas: offscreen,
-+    canvasId: proxy.id,
-  }, [ offscreen ]);
-  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
-}
-
-

핸들러 맵의 핸들러는 넘겨 받은 이벤트의 속성 중 넘겨 받은 키 배열에 해당하는 속성만 복사합니다. 그리고 ElementProxy에서 넘겨 받은 sendEvent 함수를 복사한 데이터와 함께 호출하죠. 그러면 sendEvent 함수는 해당하는 id와 데이터를 워커에 보냅니다.

-
const mouseEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'button',
-  'pointerType',
-  'clientX',
-  'clientY',
-  'pointerId',
-  'pageX',
-  'pageY',
-]);
-const wheelEventHandlerImpl = makeSendPropertiesHandler([
-  'deltaX',
-  'deltaY',
-]);
-const keydownEventHandler = makeSendPropertiesHandler([
-  'ctrlKey',
-  'metaKey',
-  'shiftKey',
-  'keyCode',
-]);
-
-function wheelEventHandler(event, sendFn) {
-  event.preventDefault();
-  wheelEventHandlerImpl(event, sendFn);
-}
-
-function preventDefaultHandler(event) {
-  event.preventDefault();
-}
-
-function copyProperties(src, properties, dst) {
-  for (const name of properties) {
-    dst[name] = src[name];
-  }
-}
-
-function makeSendPropertiesHandler(properties) {
-  return function sendProperties(event, sendFn) {
-    const data = { type: event.type };
-    copyProperties(event, properties, data);
-    sendFn(data);
-  };
-}
-
-function touchEventHandler(event, sendFn) {
-  // preventDefault() fixes mousemove, mouseup and mousedown 
-  // firing when doing a simple touchup touchdown
-  // Happens only at offscreen canvas
-  event.preventDefault(); 
-  const touches = [];
-  const data = { type: event.type, touches };
-  for (let i = 0; i < event.touches.length; ++i) {
-    const touch = event.touches[i];
-    touches.push({
-      pageX: touch.pageX,
-      pageY: touch.pageY,
-      clientX: touch.clientX,
-      clientY: touch.clientY,
-    });
-  }
-  sendFn(data);
-}
-
-// 키보드의 화살표 키
-const orbitKeys = {
-  '37': true,  // 왼쪽
-  '38': true,  // 위쪽
-  '39': true,  // 오른쪽
-  '40': true,  // 아래쪽
-};
-function filteredKeydownEventHandler(event, sendFn) {
-  const { keyCode } = event;
-  if (orbitKeys[keyCode]) {
-    event.preventDefault();
-    keydownEventHandler(event, sendFn);
-  }
-}
-
-

거의 다 된 듯합니다. 하지만 실제로 예제를 실행해보니 아직 처리해줘야 할 것들이 몇 개 더 있네요.

-

OrbitControlselement.focus 메서드를 호출합니다. 이는 워커에서 그다지 쓸모가 없으니 빈 함수로 대체하겠습니다.

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-    this.dispatchEvent(data);
-  }
-+  focus() {
-+    // 빈 함수(no-operation)
-+  }
-}
-
-

event.preventDefaultevent.stopPropagation도 사용합니다. 이는 이미 메인 페이지에서 처리했으니 이 역시 빈 함수로 대체합니다.

-
+function noop() {
-+}
-
-class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-  handleEvent(data) {
-+    data.preventDefault = noop;
-+    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // 빈 함수(no-operation)
-  }
-}
-
-

clientWidthclientHeight도 사용합니다. 이전에는 캔버스의 크기값을 따로 넘겨줬었는데, 경유 객체들이 이 값도 주고받도록 수정하겠습니다.

-

워커의 경우 다음처럼 코드를 추가합니다.

-
class ElementProxyReceiver extends THREE.EventDispatcher {
-  constructor() {
-    super();
-  }
-+  get clientWidth() {
-+    return this.width;
-+  }
-+  get clientHeight() {
-+    return this.height;
-+  }
-+  getBoundingClientRect() {
-+    return {
-+      left: this.left,
-+      top: this.top,
-+      width: this.width,
-+      height: this.height,
-+      right: this.left + this.width,
-+      bottom: this.top + this.height,
-+    };
-+  }
-  handleEvent(data) {
-+    if (data.type === 'size') {
-+      this.left = data.left;
-+      this.top = data.top;
-+      this.width = data.width;
-+      this.height = data.height;
-+      return;
-+    }
-    data.preventDefault = noop;
-    data.stopPropagation = noop;
-    this.dispatchEvent(data);
-  }
-  focus() {
-    // 빈 함수(no-operation)
-  }
-}
-
-

이제 메인 페이지에서 캔버스의 크기와 위치 좌표를 넘겨줘야 합니다. 하나 언급하고 싶은 건 예제에서는 캔버스의 크기가 바뀌는 경우만 가정했지, 캔버스가 움직이는 경우는 가정하지 않았다는 점입니다. 캔버스가 움직이는 경우를 처리하려면 캔버스가 움직였을 때 sendSize를 호출하면 됩니다.

-
class ElementProxy {
-  constructor(element, worker, eventHandlers) {
-    this.id = nextProxyId++;
-    this.worker = worker;
-    const sendEvent = (data) => {
-      this.worker.postMessage({
-        type: 'event',
-        id: this.id,
-        data,
-      });
-    };
-
-    // id를 등록합니다.
-    worker.postMessage({
-      type: 'makeProxy',
-      id: this.id,
-    });
-+    sendSize();
-    for (const [eventName, handler] of Object.entries(eventHandlers)) {
-      element.addEventListener(eventName, function(event) {
-        handler(event, sendEvent);
-      });
-    }
-
-+    function sendSize() {
-+      const rect = element.getBoundingClientRect();
-+      sendEvent({
-+        type: 'size',
-+        left: rect.left,
-+        top: rect.top,
-+        width: element.clientWidth,
-+        height: element.clientHeight,
-+      });
-+    }
-+
-+    window.addEventListener('resize', sendSize);
-  }
-}
-
-

이제 공통 Three.js 코드에서 state 전역 변수를 쓰지 않으니 삭제합니다.

-
-export const state = {
--  width: 300,   // 캔버스 기본값
--  height: 150,  // 캔버스 기본값
--};
-
-...
-
-function resizeRendererToDisplaySize(renderer) {
-  const canvas = renderer.domElement;
--  const width = state.width;
--  const height = state.height;
-+  const width = inputElement.clientWidth;
-+  const height = inputElement.clientHeight;
-  const needResize = canvas.width !== width || canvas.height !== height;
-  if (needResize) {
-    renderer.setSize(width, height, false);
-  }
-  return needResize;
-}
-
-function render(time) {
-  time *= 0.001;
-
-  if (resizeRendererToDisplaySize(renderer)) {
--    camera.aspect = state.width / state.height;
-+    camera.aspect = inputElement.clientWidth / inputElement.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-  ...
-
-

OrbitControls는 마우스 이벤트를 감지하기 위해 해당 요소의 ownerDocumentpointermovepointerup 리스너를 추가합니다(마우스가 창 밖으로 나갔을 경우를 위해).

-

또한 코드는 전역 document 객체를 참조하지만 워커에는 전역 document 객체가 없습니다.

-

이 문제는 간단한 편법(hack)을 써 해결할 수 있습니다. 다시 한 번 워커의 경유 객체를 이용하도록 하죠.

-
function start(data) {
-  const proxy = proxyManager.getProxy(data.canvasId);
-+  proxy.ownerDocument = proxy; // HACK!
-+  self.document = {} // HACK!
-  init({
-    canvas: data.canvas,
-    inputElement: proxy,
-  });
-}
-
-

이러면 OrbitControls가 에러를 던지지 않을 겁니다.

-

예제가 복잡해 이해하기 어려웠을 수 있습니다. 동작을 요약하자면 ElementProxy가 메인 페이지의 DOM 이벤트를 워커의 ElementProxyReceiver에 넘기고, ElementProxyReceiverHTMLElement를 가장해 OrbitControls와 공통 코드에서 쓸 수 있는 대체 DOM 요소로 기능합니다.

-

마지막으로 OffscreenCanvas를 지원하지 않는 경우의 예외 코드만 수정해주면 끝입니다. 간단히 inputElement에 캔버스 요소자체를 넘겨주기만 하면 되죠.

-
function startMainPage(canvas) {
--  init({ canvas });
-+  init({ canvas, inputElement: canvas });
-  console.log('using regular canvas');
-}
-
-

이제 OffscreenCanvas에서도 OrbitControls가 잘 작동합니다.

-

- -

-

아마 이 예제가 이 시리즈를 통틀어 가장 복잡한 예제일 겁니다. 각 예제마다 HTML 파일, 워커 파일, 공통 Three.js 코드 파일, 이렇게 파일 3개가 서로 연동되니 그럴만 하죠.

-

이 글이 너무 어렵게 느껴지지 않았다면 좋겠습니다. 또한 Three.js에서 OffscreenCanvas와 웹 워커를 활용하는 좋은 예가 되었길 바랍니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/optimize-lots-of-objects-animated.html b/manual/ko/optimize-lots-of-objects-animated.html deleted file mode 100644 index 6cd493ebf0403d..00000000000000 --- a/manual/ko/optimize-lots-of-objects-animated.html +++ /dev/null @@ -1,419 +0,0 @@ - - - 다중 애니메이션 요소 최적화하기 - - - - - - - - - - - - - - -
-
-

다중 애니메이션 요소 최적화하기

-
-
-
-

※ 이 글은 다중 요소 최적화하기에서 이어지는 글입니다. 이전 글을 읽지 않았다면 먼저 읽고 오기 바랍니다.

-

이전 글에서는 약 19000 육면체를 하나의 geometry로 만들었습니다. 이 방법을 적용해 렌더링 속도는 눈에 띄게 빨라졌지만, 각 육면체를 움직이기 어렵다는 게 단점이었죠.

-

구현하고자 하는 바에 따라 해결책은 천차만별입니다. 이 글에서는 여러 데이터 그룹(set)을 그래프로 만들어 각 그룹을 전환할 때 애니메이션을 넣는 경우를 살펴보겠습니다.

-

먼저 데이터를 그룹으로 묶어야 합니다. 프로그램 밖에서 데이터를 미리 가공하는 게 이상적이지만, 여기서는 데이터 2개를 따로 불러오겠습니다.

-

아래는 기존 코드입니다.

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(addBoxes)
-  .then(render);
-
-

아래와 같은 식으로 바꿔줍니다.

-
async function loadData(info) {
-  const text = await loadFile(info.url);
-  info.file = parseData(text);
-}
-
-async function loadAll() {
-  const fileInfos = [
-    { name: 'men',   hueRange: [0.7, 0.3], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc' },
-    { name: 'women', hueRange: [0.9, 1.1], url: 'resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014ft_2010_cntm_1_deg.asc' },
-  ];
-
-  await Promise.all(fileInfos.map(loadData));
-
-  ...
-}
-loadAll();
-
-

위 코드는 fileInfos 배열에 있는 파일을 불러오고, 각 파일의 로딩이 끝났을 때 해당 객체의 file 속성에 불러온 파일을 지정합니다. namehueRange는 나중에 사용할 속성으로, name은 UI에, hueRange는 색상 맵을 지정할 때 사용할 겁니다.

-

새로 불러온 파일은 각각 2010년도 지역별 남성 인구 밀도, 지역별 여성 인구 밀도를 나타냅니다. 믿을 만한 데이터인지는 모르겠지만 당장 크게 중요하진 않으니 넘어가죠. 중요한 건 값이 다른 데이터를 보여주는 것에 있으니까요.

-

여기에 2개의 데이터를 더 만듭니다. 하나는 남성 인구가 여성 인구보다 많은 곳, 나머지는 그 반대로 여성 인구가 남성 인구보다 많은 곳의 데이터입니다.

-

먼저 2차원 배열을 매개변수로 받아 배열 속 배열을 매핑하는 함수를 하나 작성합니다.

-
function mapValues(data, fn) {
-  return data.map((row, rowNdx) => {
-    return row.map((value, colNdx) => {
-      return fn(value, rowNdx, colNdx);
-    });
-  });
-}
-
-

Array.map 메서드와 마찬가지로 mapValues 함수는 배열 속 배열의 요소에 매개변수로 받은 fn 함수를 실행합니다. 이 함수는 해당 배열값과 행 인덱스, 열 인덱스를 매개변수로 사용합니다.

-

다음으로 두 파일을 배교해 새로운 파일을 만드는 함수를 작성합니다.

-
function makeDiffFile(baseFile, otherFile, compareFn) {
-  let min;
-  let max;
-  const baseData = baseFile.data;
-  const otherData = otherFile.data;
-  const data = mapValues(baseData, (base, rowNdx, colNdx) => {
-    const other = otherData[rowNdx][colNdx];
-      if (base === undefined || other === undefined) {
-        return undefined;
-      }
-      const value = compareFn(base, other);
-      min = Math.min(min === undefined ? value : min, value);
-      max = Math.max(max === undefined ? value : max, value);
-      return value;
-  });
-  // baseFile을 복사한 뒤 min, max, data를 새 값으로 교체합니다.
-  return {...baseFile, min, max, data};
-}
-
-

위 함수는 mapValues 안에서 넘겨받은 compareFn으로 값을 비교해 새로운 데이터 그룹을 만듭니다. 또한 값의 min, max를 계속 추적해 baseFile을 기반으로 min, max, data 속성을 교체한 새로운 파일을 만듭니다.

-

이제 이 함수들로 새로운 데이터를 만들어봅시다.

-
{
-  const menInfo = fileInfos[0];
-  const womenInfo = fileInfos[1];
-  const menFile = menInfo.file;
-  const womenFile = womenInfo.file;
-
-  function amountGreaterThan(a, b) {
-    return Math.max(a - b, 0);
-  }
-  fileInfos.push({
-    name: '>50%men',
-    hueRange: [0.6, 1.1],
-    file: makeDiffFile(menFile, womenFile, (men, women) => {
-      return amountGreaterThan(men, women);
-    }),
-  });
-  fileInfos.push({
-    name: '>50% women',
-    hueRange: [0.0, 0.4],
-    file: makeDiffFile(womenFile, menFile, (women, men) => {
-      return amountGreaterThan(women, men);
-    }),
-  });
-}
-
-

이제 간단한 UI를 만들어 각 데이터를 선택할 수 있게 합니다. 먼저 UI용 HTML 요소를 추가합니다.

-
<body>
-  <canvas id="c"></canvas>
-+  <div id="ui"></div>
-</body>
-
-

추가한 요소를 CSS로 상단 왼쪽에 위치하게 합니다.

-
#ui {
-  position: absolute;
-  left: 1em;
-  top: 1em;
-}
-#ui > div {
-  font-size: 20pt;
-  padding: 1em;
-  display: inline-block;
-}
-#ui > div.selected {
-  color: red;
-}
-
-

그리고 각 파일의 육면체 그래프를 만들어 하나로 합친 뒤, 이벤트용 요소를 하나 만듭니다. 이 요소에 마우스를 올리면 대응하는 데이터를 제외한 나머지는 숨기고 해당 데이터만 보이도록 할 겁니다.

-
// 선택한 데이터만 보이게 하고, 나머지는 숨깁니다.
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
-    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-  });
-  requestRenderIfNotRequested();
-}
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
-  const boxes = addBoxes(info.file, info.hueRange);
-  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  div.addEventListener('mouseover', () => {
-    showFileInfo(fileInfos, info);
-  });
-});
-// 첫 번째 데이터를 먼저 렌더링합니다.
-showFileInfo(fileInfos, fileInfos[0]);
-
-

추가로 이전 예제에서 하드 코딩했던 색상값을 hueRange로 쓰도록 바꿉니다.

-
-function addBoxes(file) {
-+function addBoxes(file, hueRange) {
-
-  ...
-
-    // 색상값을 구합니다
--    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const hue = THREE.MathUtils.lerp(...hueRange, amount);
-
-  ...
-
-

이제 4가지 데이터를 볼 수 있을 겁니다. 각 이름에 마우스를 올리거나 터치하면 해당 데이터로 바뀝니다.

-

- -

-

뭔가 앞뒤가 맞지 않는 데이터가 몇 개 보입니다. 대체 무슨 영문인지 모르겠네요. 어쨌든 일단은 이 4가지 데이터가 자연스럽게 바뀌도록 애니메이션을 넣는 데 집중합시다.

-

당장 떠오르는 방법은 3가지 정도입니다.

-
    -
  • Material.opacity를 이용해 페이드 효과를 준다

    -

    이 방법의 문제점은 육면체들이 완전히 같은 위치에 있기에 z-파이팅이 발생할 수 있다는 겁니다. 물론 깊이(depth)와 블렌딩(blending) 옵션을 주면 어쩌어찌 해결할 수 있겠죠. 자세한 방법에 대해서는 해봐야 알겠지만요.

    -
  • -
  • 보여줄 데이터는 커지게, 사라질 데이터는 작게해 전환 효과를 준다

    -

    육면체 그래프가 전부 중점이 지구본 중심이기에 1.0 이하로 크기(scale)을 줄이면 그래프가 지구본 안으로 파고들 겁니다. 얼핏 좋은 생각인 듯 싶었지만 높이가 낮은 그래프는 바로 사라져 다음 그래프의 크기가 1.0 이상이 될 때까지 한참을 빈 공간으로 남겠죠. 이러면 전환 효과가 굉장히 어색할 겁니다. 물론 복잡한 쉐이더를 써서 어느 정도 가릴 수는 있겠지만요.

    -
  • -
  • morphtargets 옵션을 쓴다

    -

    morphtargets는 geometry 각 정점에 새로운 값을 부여해 천천히 변형(morph)시키거나 두 점 사이를 선형 보간(lerp, linear interpolate)하는 것을 말합니다. morphtargets는 주로 3D 캐릭터의 표정을 묘사할 때 쓰지만 꼭 그렇게만 쓰라는 법은 없죠.

    -
  • -
-

그럼 morphtargets를 사용해봅시다.

-

이전처럼 각 데이터를 하나의 geometry로 만들되, 데이터를 만들 때 각 육면체의 position 속성을 추출해 morphtargets으로 사용할 겁니다.

-

먼저 addBoxes 함수가 합친 geometry를 반환하도록 수정합니다. 장면(scene)에 추가하는 대신 말이죠.

-
-function addBoxes(file, hueRange) {
-+function makeBoxes(file, hueRange) {
-  const { min, max, data } = file;
-  const range = max - min;
-
-  ...
-
--  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
--      geometries, false);
--  const material = new THREE.MeshBasicMaterial({
--    vertexColors: true,
--  });
--  const mesh = new THREE.Mesh(mergedGeometry, material);
--  scene.add(mesh);
--  return mesh;
-+  return BufferGeometryUtils.mergeGeometries(
-+     geometries, false);
-}
-
-

여기에 한 가지 예외 방지 처리를 해줘야 합니다. morphtargets에는 정확히 같은 개수의 정점을 지정해야 하는데, 예를 들어 정점 #123에는 상응하는 정점 #123 morphtarget이 있어야 합니다. 예제의 경우는 빈 데이터가 있고, 데이터가 비었다는 건 상응하는 육면체, 정점 데이터가 없을 수 있다는 것을 의미하죠. 그러니 모든 데이터를 검사해 해당 위치에 데이터가 하나라도 있는 경우든, 그냥 데이터가 없는 경우든 임의의 데이터를 지정해야 합니다. 일단은 더 간단한 후자를 선택하도록 하죠.

-
+function dataMissingInAnySet(fileInfos, latNdx, lonNdx) {
-+  for (const fileInfo of fileInfos) {
-+    if (fileInfo.file.data[latNdx][lonNdx] === undefined) {
-+      return true;
-+    }
-+  }
-+  return false;
-+}
-
--function makeBoxes(file, hueRange) {
-+function makeBoxes(file, hueRange, fileInfos) {
-  const { min, max, data } = file;
-  const range = max - min;
-
-  ...
-
-  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-+      if (dataMissingInAnySet(fileInfos, latNdx, lonNdx)) {
-+        return;
-+      }
-      const amount = (value - min) / range;
-
-  ...
-
-

다음으로 addBoxesmakeBoxes로 교체한 뒤, morphtargets를 설정합니다.

-
+// 데이터 그룹에 geometry를 각각 만듭니다.
-+const geometries = fileInfos.map((info) => {
-+  return makeBoxes(info.file, info.hueRange, fileInfos);
-+});
-+
-+// 첫 번째 geometry를 기준으로 다른 geometry를 morphtargets로 지정합니다.
-+const baseGeometry = geometries[0];
-+baseGeometry.morphAttributes.position = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('position');
-+  const name = `target${ ndx }`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+baseGeometry.morphAttributes.color = geometries.map((geometry, ndx) => {
-+  const attribute = geometry.getAttribute('color');
-+  const name = `target${ndx}`;
-+  attribute.name = name;
-+  return attribute;
-+});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-++});
-+const mesh = new THREE.Mesh(baseGeometry, material);
-+scene.add(mesh);
-
-const uiElem = document.querySelector('#ui');
-fileInfos.forEach((info) => {
--  const boxes = addBoxes(info.file, info.hueRange);
--  info.root = boxes;
-  const div = document.createElement('div');
-  info.elem = div;
-  div.textContent = info.name;
-  uiElem.appendChild(div);
-  function show() {
-    showFileInfo(fileInfos, info);
-  }
-  div.addEventListener('mouseover', show);
-  div.addEventListener('touchstart', show);
-});
-// 첫 데이터 그룹을 렌더링합니다.
-showFileInfo(fileInfos, fileInfos[0]);
-
-

위 코드에서는 먼저 데이터 그룹에 각각 geometry를 만들었습니다. 그리고 처음으로 생성한 geometry를 기준으로 삼아 각 geometry의 position 속성을 배열로 매핑한 뒤, 기준 geometry의 morphtargets position 속성에 지정했습니다.

-

이제 각 데이터 그룹에 전환 효과를 줘야 합니다. mesh를 사라지고 나타나게 하는 대신 mesh의 morphTargetInfluences 속성을 바꿔 애니메이션을 구현할 겁니다. 화면에 렌더링할 데이터 그룹의 influence(영향)은 1, 렌더링하지 않을 그룹의 influence는 0으로 설정하는 것이죠.

-

단순히 숫자 0, 1을 바로 지정할 수도 있지만 그러면 애니메이션이 하나도 보이지 않을 겁니다. 아까 썼던 방법과 전혀 차이가 없는 결과가 나오겠죠. 물론 직접 애니메이션 코드를 작성할 수도 있지만 원본 WebGL 지구본이 애니메이션 라이브러리를 썼으므로 같은 라이브러리를 사용해보겠습니다.

-

먼저 라이브러리를 불러옵니다.

-
import * as THREE from 'three';
-import { BufferGeometryUtils } from 'three/addons/utils/BufferGeometryUtils.js';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-+import TWEEN from 'three/addons/libs/tween.module.js';
-
-

그리고 Tween으로 influence 속성에 애니메이션을 줍니다.

-
// 선택한 데이터를 보여주고 나머지는 숨깁니다.
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
--    info.root.visible = visible;
-    info.elem.className = visible ? 'selected' : '';
-+    const targets = {};
-+    fileInfos.forEach((info, i) => {
-+      targets[i] = info === fileInfo ? 1 : 0;
-+    });
-+    const durationInMs = 1000;
-+    new TWEEN.Tween(mesh.morphTargetInfluences)
-+      .to(targets, durationInMs)
-+      .start();
-  });
-  requestRenderIfNotRequested();
-}
-
-

또 매 렌더링 프레임에서 TWEEN.update를 호출해야 하지만 좀 문제가 있습니다. "tween.js"는 연속 렌더링을 사용하도록 디자인되었습니다. 하지만 예제에서는 불필요한 렌더링 제거 기법을 사용했죠. 연속 렌더링을 사용하도록 코드를 바꿀 수도 있지만, 아무런 변화가 없을 때 렌더링을 하지 않음으로써 불필요한 자원 낭비를 줄인다는 장점을 버리고 싶진 않습니다. 여기에 불필요한 렌더링 제거 기법을 적용할 수 있을지 살펴보죠.

-

간단히 TweenManager라는 헬퍼 클래스를 만들겠습니다. 이 클래스를 통해 Tween을 만들고 애니메이션을 추적할 겁니다. 이 클래스의 update 메서드는 애니메이션이 진행 중이며 다음 프레임을 요청해야 할 때는 true, 애니메이션이 끝났다면 false를 반환할 겁니다.

-
class TweenManger {
-  constructor() {
-    this.numTweensRunning = 0;
-  }
-  _handleComplete() {
-    --this.numTweensRunning;
-    console.assert(this.numTweensRunning >= 0);
-  }
-  createTween(targetObject) {
-    const self = this;
-    ++this.numTweensRunning;
-    let userCompleteFn = () => {};
-    // Tween 인스턴스를 만들고 onCompelete에 콜백 함수를 설치합니다.
-    const tween = new TWEEN.Tween(targetObject).onComplete(function(...args) {
-      self._handleComplete();
-      userCompleteFn.call(this, ...args);
-    });
-    // Tween 인스턴스의 onComplete 함수를 바꿔 사용자가 콜백 함수를
-    // 지정할 수 있도록 합니다.
-    tween.onComplete = (fn) => {
-      userCompleteFn = fn;
-      return tween;
-    };
-    return tween;
-  }
-  update() {
-    TWEEN.update();
-    return this.numTweensRunning > 0;
-  }
-}
-
-

만든 클래스의 인스턴스를 생성합니다.

-
function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+  const tweenManager = new TweenManger();
-
-  ...
-
-

생성한 인스턴스로 Tween 인스턴스를 생성합니다.

-
// 선택한 데이터를 보여주고 나머지는 숨깁니다.
-function showFileInfo(fileInfos, fileInfo) {
-  fileInfos.forEach((info) => {
-    const visible = fileInfo === info;
-    info.elem.className = visible ? 'selected' : '';
-    const targets = {};
-    fileInfos.forEach((info, i) => {
-      targets[i] = info === fileInfo ? 1 : 0;
-    });
-    const durationInMs = 1000;
--    new TWEEN.Tween(mesh.morphTargetInfluences)
-+    tweenManager.createTween(mesh.morphTargetInfluences)
-      .to(targets, durationInMs)
-      .start();
-  });
-  requestRenderIfNotRequested();
-}
-
-

그리고 tween 애니메이션이 남아있다면 계속 렌더링 루프를 반복하도록 render 함수를 수정합니다.

-
function render() {
-  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+  if (tweenManager.update()) {
-+    requestRenderIfNotRequested();
-+  }
-
-  controls.update();
-  renderer.render(scene, camera);
-}
-render();
-
-

이제 각 데이터 그룹을 전환할 때 애니메이션이 보일 겁니다.

-

- -

-

여기서 살펴본 내용이 유익했다면 좋겠습니다. Three.js가 제공하는 모듈을 만드는 것과, 직접 쉐이더를 만드는 것 둘 다 morphtargets를 이용해 애니메이션을 구현할 때 자주 사용하는 방법입니다. 예를 들어 각 육면체 그래프를 임의의 요소에 두고 해당 위치에서 지구본 위로 이동하는 애니메이션을 줄 수도 있죠. 그것도 그래프를 표현하는 멋진 방법 중 하나일 겁니다.

-

혹시 위 지구본에 각 나라의 이름을 띄워보고 싶진 않나요? 그렇다면 HTML 요소를 3D로 정렬하기를 참고해보세요.

-
-

참고: 예제에서 남성 인구 비율이나 여성 인구 비율 또는 두 데이터의 차이를 견본 데이터로 사용할 수도 있었지만, 에제에 적용한 애니메이션은 땅에서 그래프가 올라오는 형식입니다. 비율로 처리한다면 대게의 값이 비슷비슷할 테고, 그래프의 높이도 2/1 정도는 더 낮아 시각적 효과가 그다지 크지 않았겠죠. amountGreaterThanMath.max(a - b, 0)에서 (a - b) 등으로 바꿔 두 데이터의 차이를 보거나, a / (a + b)로 바꿔 성비를 볼 수 있습니다.

-
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/optimize-lots-of-objects.html b/manual/ko/optimize-lots-of-objects.html deleted file mode 100644 index 51f69bf1b61e3e..00000000000000 --- a/manual/ko/optimize-lots-of-objects.html +++ /dev/null @@ -1,444 +0,0 @@ - - - 다중 요소 렌더링 최적화하기 - - - - - - - - - - - - - - -
-
-

다중 요소 렌더링 최적화하기

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글을 -읽고 오길 권장합니다.

-

Three.js에서 요소를 최적화하는 방법은 아주 다양합니다. 가장 많이 언급되는 방법은 geometry를 합치는 것이죠. Three.js는 사용자가 Mesh를 하나 만들 때마다 매번 시스템에 하나 이상의 렌더링 요청을 보냅니다. 결과물이 완벽히 같더라도 mesh를 1개를 렌더링할 때보다 2개를 렌더링할 때 오버헤드(overhead)가 더 많이 발생한다는 이야기죠. 그러니 이 mesh를 하나로 합친다면 오버헤드를 줄일 수 있습니다.

-

간단한 예제를 통해 이 방법이 어떤 경우 적합한지 알아보도록 하겠습니다. WebGL 지구본을 베껴 직접 구현해보겠습니다.

-

먼저 데이터를 작성합니다. WebGL 지구본 개발진은 SEDAC에서 데이터를 가져왔다고 합니다. 사이트를 뒤져보니 그리드 형태의 인구 통계 데이터가 있네요. resolution 값을 60 minute으로 설정해 데이터를 다운로드합니다.

-

받은 데이터는 아래와 같습니다.

-
 ncols         360
- nrows         145
- xllcorner     -180
- yllcorner     -60
- cellsize      0.99999999999994
- NODATA_value  -9999
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
- 9.241768 8.790958 2.095345 -9999 0.05114867 -9999 -9999 -9999 -9999 -999...
- 1.287993 0.4395509 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999...
- -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 -9999 ...
-
-

키/값 쌍 데이터가 몇 줄 있고 나머지는 격자점(grid point) 데이터네요. 데이터의 한 줄은 각 좌표에 대한 데이터입니다.

-

이해를 돕기 위해 데이터를 2D로 구현해보겠습니다.

-

먼저 텍스트 파일을 불러옵니다.

-
async function loadFile(url) {
-  const res = await fetch(url);
-  return res.text();
-}
-
-

위 함수는 url의 파일 내용을 반환하는 Promise를 반환합니다.

-

※참고: fetch API. 역주.

-

다음으로 텍스트 데이터를 파싱하는 함수를 작성합니다.

-
function parseData(text) {
-  const data = [];
-  const settings = { data };
-  let max;
-  let min;
-  // 각 줄을 쪼갭니다.
-  text.split('\n').forEach((line) => {
-    // 해당 줄을 공백을 기준으로 쪼갭니다.
-    const parts = line.trim().split(/\s+/);
-    if (parts.length === 2) {
-      // 2개로 나눠졌다면 키/값 쌍 데이터입니다.
-      settings[parts[0]] = parseFloat(parts[1]);
-    } else if (parts.length > 2) {
-      // 2개보다 많다면 좌표 데이터입니다.
-      const values = parts.map((v) => {
-        const value = parseFloat(v);
-        if (value === settings.NODATA_value) {
-          return undefined;
-        }
-        max = Math.max(max === undefined ? value : max, value);
-        min = Math.min(min === undefined ? value : min, value);
-        return value;
-      });
-      data.push(values);
-    }
-  });
-  return Object.assign(settings, { min, max });
-}
-
-

위 함수는 데이터 파일의 키/값 쌍, 좌표 데이터를 하나의 배열 만든 data 속성, 그리고 좌표 데이터를 기반으로 한 min, max 속성을 가진 객체를 반환합니다.

-

그리고 데이터를 렌더링하는 코드를 작성합니다.

-
function drawData(file) {
-  const { min, max, data } = file;
-  const range = max - min;
-  const ctx = document.querySelector('canvas').getContext('2d');
-  // 데이터와 같은 크기로 캔버스 해상도를 맞춥니다.
-  ctx.canvas.width = ncols;
-  ctx.canvas.height = nrows;
-  // 캔버스 요소의 크기를 두 배로 지정해 너무 작게 보이지 않도록 합니다.
-  ctx.canvas.style.width = px(ncols * 2);
-  ctx.canvas.style.height = px(nrows * 2);
-  // 배경을 짙은 회색으로 채웁니다.
-  ctx.fillStyle = '#444';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-  // 각 좌표에 점을 그립니다.
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const hue = 1;
-      const saturation = 1;
-      const lightness = amount;
-      ctx.fillStyle = hsl(hue, saturation, lightness);
-      ctx.fillRect(lonNdx, latNdx, 1, 1);
-    });
-  });
-}
-
-function px(v) {
-  return `${ v | 0 }px`;
-}
-
-function hsl(h, s, l) {
-  return `hsl(${ h * 360 | 0 },${ s * 100 | 0 }%,${ l * 100 | 0 }%)`;
-}
-
-

작성한 함수를 순서대로 실행하면 끝입니다.

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
-  .then(drawData);
-
-

결과를 볼까요?

-

- -

-

데이터가 잘 렌더링된 것 같네요.

-

이제 이걸 3D로 만들어봅시다. 불필요한 렌더링 제거하기에서 썼던 예제를 가져와 각 데이터마다 육면체를 하나씩 만들 겁니다.

-

먼저 아래 텍스처로 간단한 지구본 모형을 만들겠습니다.

-
- -

아래는 지구본을 만드는 코드입니다.

-
{
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/world.jpg', render);
-  const geometry = new THREE.SphereGeometry(1, 64, 32);
-  const material = new THREE.MeshBasicMaterial({ map: texture });
-  scene.add(new THREE.Mesh(geometry, material));
-}
-
-

위 코드에서는 텍스처를 불러온 후 render 함수를 호출하게 했습니다. 화면을 반복해서 렌더링하지 않고 필요할 때만 렌더링하므로, 텍스처를 불러온 뒤 다시 한 번 렌더링해야 합니다.

-

다음으로 데이터를 하나의 점으로 표시하는 대신 좌표 데이터마다 육면체를 하나씩 생성합니다.

-
function addBoxes(file) {
-  const { min, max, data } = file;
-  const range = max - min;
-
-  // 육면체 geometry를 만듭니다.
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-  // 중심이 아닌 양의 z축 방향으로 커지게끔 만듭니다.
-  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // 아래 헬퍼 Object3D는 육면체들의 위치 변화를 간단하게 만들어줍니다.
-  // lonHelper를 Y축으로 돌려 경도(longitude)를 맞출 수 있습니다.
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // latHelper를 X축으로 돌려 위도(latitude)를 맞출 수 있습니다.
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // positionHelper는 다른 요소의 기준축을 구체의 끝에 맞추는 역할을 합니다.
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-      const material = new THREE.MeshBasicMaterial();
-      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-      const saturation = 1;
-      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
-      material.color.setHSL(hue, saturation, lightness);
-      const mesh = new THREE.Mesh(geometry, material);
-      scene.add(mesh);
-
-      // 헬퍼들을 특정 위도와 경도로 이동시킵니다.
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-      // positionHelper의 위치를 해당 mesh의 위치로 지정합니다.
-      positionHelper.updateWorldMatrix(true, false);
-      mesh.applyMatrix4(positionHelper.matrixWorld);
-
-      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    });
-  });
-}
-
-

위 코드는 아까 만들었던 테스트 코드의 구조를 그대로 사용한 것입니다.

-

각 육면체를 양의 Z축으로 커지게 만든 건 지구본 위에 그래프가 올라와야 하기 때문입니다. 이 설정이 없다면 그래프가 지구본 안쪽으로 파고들어 가겠죠.

-
-
-
-
기본값
-
-
-
-
Z축을 조정한 결과
-
-
- -

씬 그래프에 관한 글에서 배웠듯 육면체를 다른 THREE.Object3D의 자식으로 두는 것도 한 가지 해결 방법이지만, 씬 그래프 요소가 많아지만 그만큼 성능이 떨어집니다.

-

lonHelper, latHelper, positionHelper를 계층 구조로 만든 건 구체 주위에 육면체를 배치할 좌표를 찾기 위해서입니다.

-
-
-
- -

위 예제의 초록색 막대lonHelper를 상징합니다. 자전축을 중심으로 경도(longitude)를 찾는 역할을 하죠. 파란색 막대latHelper입니다. latHelper는 적도 위 아래로 위도(latitude)를 찾는 역할을 합니다. 빨간 구체positionHelper로, 육면체의 좌표값을 나타냅니다.

-

물론 좌표를 계산할 때 수학적으로 접근할 수도 있지만, 이렇게 라이브러리가 대신 계산하도록 하면 복잡하게 머리를 쥐어짜야할 필요가 없습니다.

-

위 코드에서는 각 데이터 좌표마다 MeshBasicMaterialMesh를 생성했습니다. 그리고 positionHelper의 전역 좌표를 구해 Mesh에 적용하고, 데이터의 양만큼 이 mesh를 키웠죠.

-

아까와 마찬가지로 각 데이터마다 lonHelper, latHelper, positionHelper를 따로 생성할 수도 있지만, 그렇게 하면 성능이 훨씬 느려질 겁니다.

-

이러면 육면체를 최대 360x145개, 거의 최대 52000개를 만드는 셈입니다. "NO_DATA"라고 표시된 곳도 있기에 그걸 제외하면 육면체의 개수는 대략 19000개가 될 겁니다. 그런데 여기에 각 육면체에 따로 3개씩 헬퍼를 생성한다면 Three.js는 거의 80000개의 씬 그래프 요소를 계산하게 되죠. 대신 헬퍼를 공통으로 사용하면 연산 요청을 약 60000번 정도 줄일 수 있습니다.

-

lonFudgelatFudge에 대해 짧게 언급하겠습니다. lonFudge는 π/2, 90도입니다. 이건 크게 신경쓸 게 없네요. 그냥 텍스처나 텍스처 좌표가 다른 각도에서 시작한다는 소리니까요. 하지만 latFudge의 경우는 왜 π * -0.135가 필요한지 모르겠습니다. 그냥 좌표가 저 축을 기준으로 정렬되어 있습니다.

-

이제 만든 함수를 호출합니다.

-
loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
-  .then(parseData)
--  .then(drawData)
-+  .then(addBoxes)
-+  .then(render);
-

필요할 때만 렌더링 함수를 호출하게 해놨으므로 지구본과 육면체들을 추가한 뒤 render 함수를 직접 호출해야 합니다.

-

- -

-

위 예제를 드래그해 지구본을 돌려보면 뭔가 버벅임을 느낄 수 있을 겁니다.

-

개발자 도구를 열어 브라우저의 FPS 미터를 켜면 프레임율을 확인할 수 있습니다.

-
- -

제 환경에서는 평균 프레임이 20fps보다 낮네요.

-
- -

아마 더 안 좋은 컴퓨터에서는 이보다 더 심할 겁니다. 최적화할 방법을 찾아봐야겠네요.

-

예제의 경우 모든 정육면체를 하나의 geometry로 합치는 방법을 적용할 수 있습니다. 현재 거의 육면체를 거의 19000개 정도 렌더링했는데, 이를 하나로 합치면 연산 요청을 18999회 정도 줄일 수 있습니다.

-
function addBoxes(file) {
-  const {min, max, data} = file;
-  const range = max - min;
-
--  // 육면체 geometry를 만듭니다.
--  const boxWidth = 1;
--  const boxHeight = 1;
--  const boxDepth = 1;
--  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
--  // 중심이 아닌 양의 z축 방향으로 커지게끔 만듭니다.
--  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.5));
-
-  // 아래 헬퍼 Object3D는 육면체들의 위치 변화를 간단하게 만들어줍니다.
-  // lonHelper를 Y축으로 돌려 경도(longitude)를 맞출 수 있습니다.
-  const lonHelper = new THREE.Object3D();
-  scene.add(lonHelper);
-  // latHelper를 X축으로 돌려 위도(latitude)를 맞출 수 있습니다.
-  const latHelper = new THREE.Object3D();
-  lonHelper.add(latHelper);
-  // positionHelper는 다른 요소의 기준축을 구체의 끝에 맞추는 역할을 합니다.
-  const positionHelper = new THREE.Object3D();
-  positionHelper.position.z = 1;
-  latHelper.add(positionHelper);
-+  // 육면체의 중심을 옮겨 양의 Z축 방향으로 커지게 합니다.
-+  const originHelper = new THREE.Object3D();
-+  originHelper.position.z = 0.5;
-+  positionHelper.add(originHelper);
-
-  const lonFudge = Math.PI * .5;
-  const latFudge = Math.PI * -0.135;
-+  const geometries = [];
-  data.forEach((row, latNdx) => {
-    row.forEach((value, lonNdx) => {
-      if (value === undefined) {
-        return;
-      }
-      const amount = (value - min) / range;
-
--      const material = new THREE.MeshBasicMaterial();
--      const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
--      const saturation = 1;
--      const lightness = THREE.MathUtils.lerp(0.1, 1.0, amount);
--      material.color.setHSL(hue, saturation, lightness);
--      const mesh = new THREE.Mesh(geometry, material);
--      scene.add(mesh);
-
-+      const boxWidth = 1;
-+      const boxHeight = 1;
-+      const boxDepth = 1;
-+      const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-      // 헬퍼들을 특정 위도와 경도로 이동시킵니다.
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
--      // positionHelper의 위치를 해당 mesh의 위치로 지정합니다.
--      positionHelper.updateWorldMatrix(true, false);
--      mesh.applyMatrix4(positionHelper.matrixWorld);
--
--      mesh.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-
-+      // originHelper의 위치를 해당 geometry의 위치로 지정합니다.
-+      positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-+      originHelper.updateWorldMatrix(true, false);
-+      geometry.applyMatrix4(originHelper.matrixWorld);
-+
-+      geometries.push(geometry);
-    });
-  });
-
-+  // 생성한 geometry를 전부 합칩니다.
-+  const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-+      geometries, false);
-+  const material = new THREE.MeshBasicMaterial({ color:'red' });
-+  const mesh = new THREE.Mesh(mergedGeometry, material);
-+  scene.add(mesh);
-
-}
-
-

위 코드에서는 육면체의 중심을 옮기는 대신 originHelper를 새로 만들어 중심축을 옮겼습니다. 이전에는 같은 geometry를 19000번 재활용했지만, 이번에는 데이터마다 geometry를 새로 생성했죠. 또한 applyMatrix를 이용해 육면체 자체의 정점을 이동시키므로 메서드를 두 번 쓰는 대신 한 번만 썼습니다.

-

그리고 생성한 육면체를 전부 배열에 저장한 뒤 이 배열을 BufferGeometryUtils.mergeGeometries에 넘겨 하나의 geometry로 합쳤습니다.

-

물론 BufferGeometryUtils을 불러와야죠.

-
import { BufferGeometryUtils } from 'three/addons/utils/BufferGeometryUtils.js';
-
-

이제 제 컴퓨터에서는 적어도 60 프레임 이상이 나오네요.

-

- -

-

성능 문제는 해결했지만 육면체가 하나의 mesh이기에 이전과 달리 육면체의 색이 전부 같습니다. 여기서 색을 따로 지정하려면? 여러 방법이 있겠지만 정점 색(vertex color)을 쓰는 방법이 제일 간단할 겁니다.

-

정점 색은 정점마다 색을 지정합니다. 각 육면체의 각 정점을 다른 색으로 지정하면 육면체의 색을 다르게 지정할 수 있겠죠.

-
+const color = new THREE.Color();
-
-const lonFudge = Math.PI * .5;
-const latFudge = Math.PI * -0.135;
-const geometries = [];
-data.forEach((row, latNdx) => {
-  row.forEach((value, lonNdx) => {
-    if (value === undefined) {
-      return;
-    }
-    const amount = (value - min) / range;
-
-    const boxWidth = 1;
-    const boxHeight = 1;
-    const boxDepth = 1;
-    const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-    // 헬퍼들을 특정 위도와 경도로 이동시킵니다.
-    lonHelper.rotation.y = THREE.MathUtils.degToRad(lonNdx + file.xllcorner) + lonFudge;
-    latHelper.rotation.x = THREE.MathUtils.degToRad(latNdx + file.yllcorner) + latFudge;
-
-    // originHelper의 위치를 해당 geometry의 위치로 지정합니다.
-    positionHelper.scale.set(0.005, 0.005, THREE.MathUtils.lerp(0.01, 0.5, amount));
-    originHelper.updateWorldMatrix(true, false);
-    geometry.applyMatrix4(originHelper.matrixWorld);
-
-+    // 색상값을 계산합니다.
-+    const hue = THREE.MathUtils.lerp(0.7, 0.3, amount);
-+    const saturation = 1;
-+    const lightness = THREE.MathUtils.lerp(0.4, 1.0, amount);
-+    color.setHSL(hue, saturation, lightness);
-+    // RGB 색상값을 0부터 255까지의 배열로 변환합니다.
-+    const rgb = color.toArray().map(v => v * 255);
-+
-+    // 각 정점의 색을 배열로 저장합니다.
-+    const numVerts = geometry.getAttribute('position').count;
-+    const itemSize = 3;  // r, g, b
-+    const colors = new Uint8Array(itemSize * numVerts);
-+
-+    // 색상값을 각 정점에 지정할 색상으로 변환합니다.
-+    colors.forEach((v, ndx) => {
-+      colors[ndx] = rgb[ndx % 3];
-+    });
-+
-+    const normalized = true;
-+    const colorAttrib = new THREE.BufferAttribute(colors, itemSize, normalized);
-+    geometry.setAttribute('color', colorAttrib);
-
-    geometries.push(geometry);
-  });
-});
-
-

추가한 코드에서는 먼저 geometry의 position 속성을 가져와 정점의 개수를 파악했습니다. 그런 다음 색상을 지정하기 위해 Uint8Array로 변환한 뒤, 이를 geometry.setAttribute 메서드로 geometry의 color 속성에 지정했죠.

-

마지막으로 재질(material)이 정점 색상을 사용하도록 설정합니다.

-
const mergedGeometry = BufferGeometryUtils.mergeGeometries(
-    geometries, false);
--const material = new THREE.MeshBasicMaterial({color:'red'});
-+const material = new THREE.MeshBasicMaterial({
-+  vertexColors: true,
-+});
-const mesh = new THREE.Mesh(mergedGeometry, material);
-scene.add(mesh);
-
-

이제 색이 다시 정상적으로 보입니다.

-

- -

-

geometry를 합치는 건 꽤 자주 사용하는 최적화 기법입니다. 예를 들어 나무 100개를 하나의 geometry로 합치거나, 돌무더기를 하나의 돌 geometry로 합치거나, 울타리의 각 기둥을 하나의 mesh로 합치는 경우가 해당되죠. 마인크래프트의 경우도 모든 타일을 하나하나 다 렌더링하기보다 타일을 하나로 합쳐 보이지 않는 면은 제거하는 기법을 사용할 확률이 높습니다.

-

하지만 요소를 하나의 mesh로 합쳐버리면 별도의 요소였던 특정 부분을 조작하기가 어렵습니다. 상황에 따라 좋은 방법도 다 다를 테죠. 다음 글에서는 그 방법 중 하나를 살펴보겠습니다.

-

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/picking.html b/manual/ko/picking.html deleted file mode 100644 index 9560fbc6b0647f..00000000000000 --- a/manual/ko/picking.html +++ /dev/null @@ -1,396 +0,0 @@ - - - 피킹(Picking) - - - - - - - - - - - - - - -
-
-

피킹(Picking)

-
-
-
-

피킹(picking)이란 사용자가 클릭 또는 터치한 물체를 가려내는 작업을 말합니다. 피킹을 구현하는 방법은 수없이 많지만, 각자 단점이 있습니다. 이 글에서는 이 방법 중 흔히 사용하는 2가지 방법만 살펴보겠습니다.

-

아마 피킹을 구현하는 가장 흔한 방법은 광선 투사(ray casting)일 겁니다. 광선 투사란 포인터(커서)에서 장면의 절두체로 광선을 쏴 광선이 닿는 물체를 감지하는 기법을 말하죠. 이론적으로 가장 간단한 방법입니다.

-

먼저 포인터의 좌표를 구한 뒤, 이 좌표를 카메라의 시선과 방향에 따라 3D 좌표로 변환합니다. 그리고 near 면에서 far 면까지의 광선을 구해 이 광선이 장면 안 각 물체의 삼각형과 교차하는지 확인합니다. 만약 장면 안에 1000개의 삼각형을 가진 물체가 1000개 있다면 백만 개의 삼각형을 일일이 확인해야 하는 셈이죠.

-

이를 최적화하려면 몇 가지 방법을 시도해볼 수 있습니다. 하나는 먼저 물체를 감싼 경계(bounding) 좌표가 광선과 교차하는지 확인하고, 교차하지 않는다면 해당 물체의 삼각형을 확인하지 않는 것이죠.

-

Three.js에는 이런 작업을 대신해주는 RayCaster 클래스가 있습니다.

-

한번 물체 100개가 있는 장면을 만들어 여기서 피킹을 구현해봅시다. 예제는 반응형 디자인에서 썼던 예제를 가져와 사용하겠습니다.

-

우선 카메라를 별도 Object3D의 자식으로 추가해 카메라가 셀카봉처럼 장면 주위를 돌 수 있도록 합니다.

-
*const fov = 60;
-const aspect = 2;  // 캔버스 기본값
-const near = 0.1;
-*const far = 200;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-*camera.position.z = 30;
-
-const scene = new THREE.Scene();
-+scene.background = new THREE.Color('white');
-
-+// 카메라를 봉(pole)에 추가합니다.
-+// 이러면 봉을 회전시켜 카메라가 장면 주위를 돌도록 할 수 있습니다
-+const cameraPole = new THREE.Object3D();
-+scene.add(cameraPole);
-+cameraPole.add(camera);
-
-

그리고 render 함수 안에서 카메라 봉을 돌립니다.

-
cameraPole.rotation.y = time * .1;
-
-

또한 카메라에 조명을 추가해 조명이 카메라와 같이 움직이도록 합니다.

-
-scene.add(light);
-+camera.add(light);
-
-

정육면체 100개의 위치, 방향, 크기를 무작위로 설정해 생성합니다.

-
const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-  return min + (max - min) * Math.random();
-}
-
-function randomColor() {
-  return `hsl(${ rand(360) | 0 }, ${ rand(50, 100) | 0 }%, 50%)`;
-}
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-}
-
-

이제 피킹을 구현해봅시다.

-

피킹을 관리할 간단한 클래스를 만들겠습니다.

-
class PickHelper {
-  constructor() {
-    this.raycaster = new THREE.Raycaster();
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(normalizedPosition, scene, camera, time) {
-    // 이미 다른 물체를 피킹했다면 색을 복원합니다
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-    // 절두체 안에 광선을 쏩니다
-    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // 광선과 교차하는 물체들을 배열로 만듭니다
-    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
-    if (intersectedObjects.length) {
-      // 첫 번째 물체가 제일 가까우므로 해당 물체를 고릅니다
-      this.pickedObject = intersectedObjects[0].object;
-      // 기존 색을 저장해둡니다
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // emissive 색을 빨강/노랑으로 빛나게 만듭니다
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

위 클래스는 먼저 RayCaster 인스턴스를 만들고 pick 메서드를 호출하면 장면에 광선을 쏠 수 있게 해줍니다. 그리고 광선에 맞는 요소가 있으면 해당 요소 중 가장 첫 번째 요소의 색을 변경합니다.

-

사용자가 마우스를 눌렀을 때(down)만 이 함수가 작동하도록 할 수도 있지만, 예제에서는 마우스 포인터 아래의 있는 요소를 피킹하도록 하겠습니다. 이를 구현하려면 먼저 포인터를 추적해야 합니다.

-
const pickPosition = { x: 0, y: 0 };
-clearPickPosition();
-
-...
-
-function getCanvasRelativePosition(event) {
-  const rect = canvas.getBoundingClientRect();
-  return {
-    x: (event.clientX - rect.left) * canvas.width  / rect.width,
-    y: (event.clientY - rect.top ) * canvas.height / rect.height,
-  };
-}
-
-function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
-  pickPosition.x = (pos.x / canvas.width ) *  2 - 1;
-  pickPosition.y = (pos.y / canvas.height) * -2 + 1;  // Y 축을 뒤집었음
-}
-
-function clearPickPosition() {
-  /**
-   * 마우스의 경우는 항상 위치가 있어 그다지 큰
-   * 상관이 없지만, 터치 같은 경우 사용자가 손가락을
-   * 떼면 피킹을 멈춰야 합니다. 지금은 일단 어떤 것도
-   * 선택할 수 없는 값으로 지정해두었습니다
-   **/
-  pickPosition.x = -100000;
-  pickPosition.y = -100000;
-}
-
-window.addEventListener('mousemove', setPickPosition);
-window.addEventListener('mouseout', clearPickPosition);
-window.addEventListener('mouseleave', clearPickPosition);
-
-

위 예제에서는 마우스의 좌표를 정규화(normalize)했습니다. 캔버스의 크기와 상관없이 왼쪽 끝이 -1, 오른쪽 끝이 +1인 벡터값이 필요하기 때문이죠. 마찬가지로 아래쪽 끝은 -1, 위쪽 끝은 +1입니다.

-

모바일도 환경도 지원하기 위해 리스너를 더 추가하겠습니다.

-
window.addEventListener('touchstart', (event) => {
-  event.preventDefault(); // 스크롤 이벤트 방지
-  setPickPosition(event.touches[0]);
-}, { passive: false });
-
-window.addEventListener('touchmove', (event) => {
-  setPickPosition(event.touches[0]);
-});
-
-window.addEventListener('touchend', clearPickPosition);
-
-

마지막으로 render 함수에서 PickHelperpick 메서드를 호출합니다.

-
+const pickHelper = new PickHelper();
-
-function render(time) {
-  time *= 0.001;  // 초 단위로 변환
-
-  ...
-
-+  pickHelper.pick(pickPosition, scene, camera, time);
-
-  renderer.render(scene, camera);
-
-  ...
-
-

결과를 볼까요?

-

- -

-

딱히 문제는 없어 보입니다. 실제로 사용하는 경우도 대부분 문제 없이 잘 되겠지만, 이 방법에는 몇 가지 문제점이 있습니다.

-
    -
  1. CPU의 자원을 사용한다

    -

    자바스크립트 엔진은 각 요소를 돌며 광선이 요소의 경계 좌표 안에 교차하는지 확인합니다. 만약 교차할 경우, 해당 요소의 삼각형을 전부 돌며 광선과 교차하는 삼각형이 있는지 확인합니다.

    -

    이 방식의 장점은 자바스크립트가 교차하는 지점을 정확히 계산해 해당 데이터를 넘겨줄 수 있다는 점입니다. 예를 들어 교차가 발생한 지점에 특정 표시를 할 수 있겠죠.

    -

    대신 CPU가 할 일이 더 늘어난다는 점이 단점입니다. 요소가 가진 삼각형이 많을수록 더 느려지겠죠.

    -
  2. -
  3. 특이한 방식의 쉐이더나 변이를 감지하지 못한다

    -

    만약 장면에서 geometry를 변형하는 쉐이더를 사용한다면, 자바스크립트는 이 변형을 감지하지 못하기에 잘못된 값을 내놓을 겁니다. 제가 테스트해본 결과 스킨이 적용된 요소에는 이 방법이 먹히지 않습니다.

    -
  4. -
  5. 요소의 투명한 구멍을 처리하지 못한다.

    -
  6. -
-

예제를 하나 만들어보죠. 아래와 같은 텍스처를 정육면체에 적용해봅시다.

-
- -

그다지 추가할 건 많지 않습니다.

-
+const loader = new THREE.TextureLoader();
-+const texture = loader.load('resources/images/frame.png');
-
-const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    +map: texture,
-    +transparent: true,
-    +side: THREE.DoubleSide,
-    +alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  ...
-
-

예제를 실행시키면 바로 문제가 보일 겁니다.

-

- -

-

정육면체의 빈 공간을 통해 무언가를 선택할 수가 없죠.

-
- -

이는 자바스크립트가 텍스처나 재질을 보고 해당 요소가 투명한지 판단하기가 어렵기 때문입니다.

-

이 문제를 해결하려면 GPU 기반 피킹을 구현해야 합니다. 이론적으로는 간단하지만 위에서 사용한 광선 투사법보다는 좀 더 복잡하죠.

-

GPU 피킹을 구현하려면 각 요소를 별도의 화면에서 고유한 색상으로 렌더링해야 합니다. 그리고 포인터 아래에 있는 픽셀의 색을 가져와 해당 요소가 선택됐는지 확인하는 거죠.

-

이러면 위에서 언급한 문제점 2, 3번이 해결됩니다. 1번, 성능의 경우는 상황에 따라 천차만별이죠. 눈에 보이는 화면을 위해 한 번, 피킹을 위해 한 번, 이렇게 매 요소를 총 두 번씩 렌더링해야 합니다. 더 복잡한 해결책을 쓰면 렌더링을 한 번만 할 수도 있지만, 이 글에서는 일단 더 간단한 방법을 사용하겠습니다.

-

성능 최적화를 위해 시도할 수 있는 방법이 하나 있습니다. 어차피 픽셀을 하나만 읽을 것이니, 카메라를 픽셀 하나만 렌더링하도록 설정하는 것이죠. PerspectiveCamera.setViewOffset 메서드를 사용하면 카메라의 특정 부분만 렌더링하도록 할 수 있습니다. 이러면 성능 향상에 조금이나마 도움이 되겠죠.

-

현재 Three.js에서 이 기법을 구현하려면 장면 2개를 사용해야 합니다. 하나는 기존 mesh를 그대로 쓰고, 나머지 하나는 피킹용 재질을 적용한 mesh를 쓸 겁니다.

-

먼저 두 번째 장면을 추가하고 배경을 검정으로 지정합니다.

-
const scene = new THREE.Scene();
-scene.background = new THREE.Color('white');
-const pickingScene = new THREE.Scene();
-pickingScene.background = new THREE.Color(0);
-
-

각 정육면체를 장면에 추가할 때 pickingScene의 같은 위치에 "피킹용 정육면체"를 추가합니다. 그리고 각 피킹용 정육면체에는 id로 쓸 고유 색상값을 지정한 뒤, 이 id 색상값으로 재질을 만들어 추가합니다. id 색상값을 정육면체의 키값으로 매핑해 놓으면 나중에 상응하는 정육면체를 바로 불러올 수 있겠죠.

-
const idToObject = {};
-+const numObjects = 100;
-for (let i = 0; i < numObjects; ++i) {
-+  const id = i + 1;
-  const material = new THREE.MeshPhongMaterial({
-    color: randomColor(),
-    map: texture,
-    transparent: true,
-    side: THREE.DoubleSide,
-    alphaTest: 0.1,
-  });
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-+  idToObject[id] = cube;
-
-  cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
-  cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
-  cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));
-
-+  const pickingMaterial = new THREE.MeshPhongMaterial({
-+    emissive: new THREE.Color().setHex(id, THREE.NoColorSpace),
-+    color: new THREE.Color(0, 0, 0),
-+    specular: new THREE.Color(0, 0, 0),
-+    map: texture,
-+    transparent: true,
-+    side: THREE.DoubleSide,
-+    alphaTest: 0.5,
-+    blending: THREE.NoBlending,
-+  });
-+  const pickingCube = new THREE.Mesh(geometry, pickingMaterial);
-+  pickingScene.add(pickingCube);
-+  pickingCube.position.copy(cube.position);
-+  pickingCube.rotation.copy(cube.rotation);
-+  pickingCube.scale.copy(cube.scale);
-}
-
-

위 코드에서는 MeshPhongMaterial로 편법을 사용했습니다. emissive 속성을 id 색상값으로, colorspecular 속성을 0으로 설정하면 텍스처의 알파값이 alphaTest보다 큰 부분만 id 색상값으로 보이겠죠. 또 blending 속성을 THREE.NoBlending으로 설정해 id 색상값이 알파값의 영향을 받지 않도록 했습니다.

-

제가 사용한 편법이 최적의 해결책은 아닙니다. 여러가지 옵션을 껐다고 해도 여전히 조명 관련 연산을 실행할 테니까요. 코드를 더 최적화하려면 alphaTest 값보다 높은 경우에만 id 색상을 렌더링하는 쉐이더를 직접 만들어야 합니다.

-

광선 투사법을 쓸 때와 달리 픽셀을 하나만 사용하므로 위치값이 픽셀 하나만 가리키게 변경합니다.

-
function setPickPosition(event) {
-  const pos = getCanvasRelativePosition(event);
--  pickPosition.x = (pos.x / canvas.clientWidth ) *  2 - 1;
--  pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1;  // Y 축을 뒤집었음
-+  pickPosition.x = pos.x;
-+  pickPosition.y = pos.y;
-}
-
-

PickHelper 클래스도 GPUPickHelper로 변경합니다. 렌더 타겟(render target)에 관한 글에서 다룬 WebGLRenderTarget을 써 구현하되, 이번 렌더 타겟의 크기는 1x1, 1픽셀입니다.

-
-class PickHelper {
-+class GPUPickHelper {
-  constructor() {
--    this.raycaster = new THREE.Raycaster();
-+    // 1x1 픽셀 크기의 렌더 타겟을 생성합니다
-+    this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
-+    this.pixelBuffer = new Uint8Array(4);
-    this.pickedObject = null;
-    this.pickedObjectSavedColor = 0;
-  }
-  pick(cssPosition, scene, camera, time) {
-+    const {pickingTexture, pixelBuffer} = this;
-
-    // 기존에 선택된 요소가 있는 경우 색을 복원합니다
-    if (this.pickedObject) {
-      this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor);
-      this.pickedObject = undefined;
-    }
-
-+    // view offset을 마우스 포인터 아래 1픽셀로 설정합니다
-+    const pixelRatio = renderer.getPixelRatio();
-+    camera.setViewOffset(
-+        renderer.getContext().drawingBufferWidth,   // 전체 너비
-+        renderer.getContext().drawingBufferHeight,  // 전체 높이
-+        cssPosition.x * pixelRatio | 0,             // 사각 x 좌표
-+        cssPosition.y * pixelRatio | 0,             // 사각 y 좌표
-+        1,                                          // 사각 좌표 width
-+        1,                                          // 사각 좌표 height
-+    );
-+    // 장면을 렌더링합니다
-+    renderer.setRenderTarget(pickingTexture)
-+    renderer.render(scene, camera);
-+    renderer.setRenderTarget(null);
-+
-+    // view offset을 정상으로 돌려 원래의 화면을 렌더링하도록 합니다
-+    camera.clearViewOffset();
-+    // 픽셀을 감지합니다
-+    renderer.readRenderTargetPixels(
-+        pickingTexture,
-+        0,   // x
-+        0,   // y
-+        1,   // width
-+        1,   // height
-+        pixelBuffer);
-+
-+    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2]      );
-
-    // 절두체 안에 광선을 쏩니다
--    this.raycaster.setFromCamera(normalizedPosition, camera);
-    // 광선과 교차하는 물체들을 배열로 만듭니다
--    const intersectedObjects = this.raycaster.intersectObjects(scene.children);
--    if (intersectedObjects.length) {
-      // 첫 번째 물체가 제일 가까우므로 해당 물체를 고릅니다
--      this.pickedObject = intersectedObjects[0].object;
-
-+    const intersectedObject = idToObject[id];
-+    if (intersectedObject) {
-      // 첫 번째 물체가 제일 가까우므로 해당 물체를 고릅니다
-+      this.pickedObject = intersectedObject;
-      // 기존 색을 저장해둡니다
-      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
-      // emissive 색을 빨강/노랑으로 빛나게 만듭니다
-      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
-    }
-  }
-}
-
-

인스턴스를 만드는 쪽도 수정합니다.

-
-const pickHelper = new PickHelper();
-+const pickHelper = new GPUPickHelper();
-
-

pick 메서드를 호출할 때 scene 대신 pickScene을 넘겨줍니다.

-
-  pickHelper.pick(pickPosition, scene, camera, time);
-+  pickHelper.pick(pickPosition, pickScene, camera, time);
-
-

이제 투명한 부분을 관통해 요소를 선택할 수 있습니다.

-

- -

-

이 글이 피킹을 구현하는 데 도움이 되었으면 좋겠네요. 나중에 요소를 마우스로 조작하는 법에 대해서도 한 번 써보겠습니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/post-processing.html b/manual/ko/post-processing.html deleted file mode 100644 index e2911dcb909785..00000000000000 --- a/manual/ko/post-processing.html +++ /dev/null @@ -1,220 +0,0 @@ - - - 후처리 - - - - - - - - - - - - - - -
-
-

후처리

-
-
-
-

후처리(post processing)란 보통 2D 이미지에 어떤 효과나 필터를 넣는 것을 의미합니다. Three.js는 다양한 mesh로 이루어진 장면을 2D 이미지로 렌더링하죠. 일반적으로 이 이미지는 바로 캔버스를 통해 브라우저 화면에 렌더링됩니다. 하지만 대신 이 이미지를 렌더 타겟에 렌더링하고 캔버스에 보내기 전 임의의 후처리 효과를 줄 수 있습니다.

-

인스타그램 필터, 포토샵 필터 등이 후처리의 좋은 예이죠.

-

Three.js에는 후처리를 순차적으로 처리해주는 모범 클래스가 있습니다. 일단 EffectComposer의 인스턴스를 만들고 여기에 Pass 객체(효과, 필터)들을 추가합니다. 그리고 EffectComposer.render 메서드를 호출하면 현재 장면을 렌더 타겟에 렌더링한 뒤 각 pass*를 순서대로 적용합니다.

-

※ 편의상 Pass 인스턴스를 pass로 번역합니다.

-

이 pass는 비넷(vignette), 흐림(blur), 블룸(bloom), 필름 그레인(film grain) 효과 또는 hue, 채도(saturation), 대비(contrast) 조정 등의 후처리 효과로, 이 효과를 모두 적용한 결과물을 최종적으로 캔버스에 렌더링합니다.

-

여기서 어느 정도 EffectComposer의 원리를 이해할 필요가 있습니다. EffectComposer는 두 개의 렌더 타겟을 사용합니다. 편의상 이 둘을 rtA, rtB라고 부르도록 하죠.

-

EffectComposer.addPass를 각 pass를 적용할 순서대로 호출하고 EffectComposer.render를 호출하면 pass*는 아래 그림과 같은 순서로 적용됩니다.

-
- -

먼저 RenderPass에 넘긴 장면을 rtA에 렌더링합니다. 그리고 rtA를 다음 pass에 넘겨주면 해당 pass는 rtA에 pass를 적용한 결과를 rtB에 렌더링합니다. 그런 다음 rtB를 다음 pass로 넘겨 적용한 결과를 rtA에, rtA에 pass를 적용한 결과를 다시 rtB에, 이런 식으로 모든 pass가 끝날 때까지 계속 반복합니다.

-

Pass에는 공통적으로 4가지 옵션이 있습니다.

-

enabled

-

이 pass를 사용할지의 여부입니다.

-

needsSwap

-

이 pass를 적용한 후 rtArtB를 바꿀지의 여부입니다.

-

clear

-

이 pass를 적용하기 전에 화면을 초기화할지의 여부입니다.

-

renderToScreen

-

지정한 렌더 타겟이 아닌 캔버스에 렌더링할지의 여부입니다. 보통 EffectComposer에 추가하는 마지막 pass에 이 옵션을 true로 설정합니다.

-

간단한 예제를 만들어봅시다. 반응형 디자인에 관한 글에서 썼던 예제를 가져오겠습니다.

-

추가로 먼저 EffectComposer 인스턴스를 생성합니다.

-
const composer = new EffectComposer(renderer);
-
-

다음으로 RenderPass를 첫 pass로 추가합니다. 이 pass는 넘겨 받은 장면을 첫 렌더 타겟에 렌더링할 겁니다.

-
composer.addPass(new RenderPass(scene, camera));
-
-

다음으로 BloomPass를 추가합니다. BloomPass는 장면을 원래의 장면보다 작게 렌더링해 흐림(blur) 효과를 줍니다. 그리고 효과가 적용된 장면을 원래 장면에 덮어 씌우는 식으로 블룸 효과를 구현합니다.

-
const bloomPass = new BloomPass(
-    1,    // 강도
-    25,   // 커널(kernel) 크기
-    4,    // 시그마 ?
-    256,  // 렌더 타겟의 해상도를 낮춤
-);
-composer.addPass(bloomPass);
-
-

마지막으로 원본 장면에 노이즈와 스캔라인(scanline)을 추가하는 FilmPass를 추가합니다.

-
const filmPass = new FilmPass(
-    0.5,   // 강도
-    false,  // 흑백
-);
-composer.addPass(filmPass);
-
-

또 이 클래스들을 사용하기 위해 여러 스크립트를 불러와야 합니다.

-
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
-import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
-import { BloomPass } from 'three/addons/postprocessing/BloomPass.js';
-import { FilmPass } from 'three/addons/postprocessing/FilmPass.js';
-import {OutputPass} from 'three/addons/postprocessing/OutputPass.js';
-
-

대부분의 후처리에는 EffectComposer.jsRenderPass.js가 필수입니다.

-

이제 WebGLRenderer.render 대신 EffectComposer.render를 사용하고 EffectComposer가 결과물을 캔버스의 크기에 맞추도록 해야 합니다.

-
-function render(now) {
--  time *= 0.001;
-+let then = 0;
-+function render(now) {
-+  now *= 0.001;  // 초 단위로 변환
-+  const deltaTime = now - then;
-+  then = now;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-+    composer.setSize(canvas.width, canvas.height);
-  }
-
-  cubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
--    const rot = time * speed;
-+    const rot = now * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
--  renderer.render(scene, camera);
-+  composer.render(deltaTime);
-
-  requestAnimationFrame(render);
-}
-
-

EffectComposer.render 메서드는 인자로 마지막 프레임을 렌더링한 이후의 시간값인 deltaTime을 인자로 받습니다. pass에 애니메이션이 필요할 경우를 대비해 이 값을 넘겨주기 위해서이죠. 예제의 경우에는 FilmPass에 애니메이션이 있습니다.

-

- -

-

런타임에 효과의 속성을 변경할 때는 보통 uniform의 value 값을 바꿉니다. GUI를 추가해 이 속성을 조정할 수 있게 만들어보죠. 어떤 속성을 어떻게 조작할 수 있는지는 해당 효과의 소스 코드를 열어봐야 알 수 있습니다.

-

BloomPass.js에서 -아래 코드를 찾았습니다.

-
this.copyUniforms[ "opacity" ].value = strength;
-
-

아래처럼 하면 강도를 런타임에 바꿀 수 있겠네요.

-
bloomPass.copyUniforms.opacity.value = someValue;
-
-

마찬가지로 FilmPass.js에서 -아래 코드를 찾았습니다.

-
this.uniforms.intensity.value = intensity;
-this.uniforms.grayscale.value = grayscale;
-
-

이제 어떻게 값을 지정해야 하는지 알았으니 이 값을 조작하는 GUI를 만들어봅시다.

-
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-

일단 모듈을 로드합니다.

-
const gui = new GUI();
-{
-  const folder = gui.addFolder('BloomPass');
-  folder.add(bloomPass.copyUniforms.opacity, 'value', 0, 2).name('strength');
-  folder.open();
-}
-{
-  const folder = gui.addFolder('FilmPass');
-  folder.add(filmPass.uniforms.grayscale, 'value').name('grayscale');
-  folder.add(filmPass.uniforms.intensity, 'value', 0, 1).name('intensity');
-  folder.open();
-}
-
-

이제 각 설정을 조작할 수 있습니다.

-

- -

-

여기까지 잘 따라왔다면 이제 효과를 직접 만들어볼 수 있습니다.

-

후처리 효과는 쉐이더를 사용합니다. 쉐이더는 GLSL (Graphics Library Shading Language)이라는 언어를 사용하죠. 언어가 방대해 이 글에서 전부 다루기는 어렵습니다. 기초부터 알아보고 싶다면 이 글쉐이더란 무엇인가(The Book of Shaders)를 읽어보기 바랍니다.

-

직접 예제를 만들어보는 게 도움이 될 테니 간단한 GLSL 후처리 쉐이더를 만들어봅시다. 이미지에 특정 색을 혼합하는 쉐이더를 만들 겁니다.

-

Three.js에는 후처리를 도와주는 ShaderPass 헬퍼 클래스가 있습니다. 인자로 vertex 쉐이더, fragment 쉐이더, 기본값으로 이루어진 객체를 받죠. 이 클래스는 이전 pass의 결과물에서 어떤 텍스처를 읽을지, 그리고 EffectComposer의 렌더 타겟과 캔버스 중 어디에 렌더링할지를 결정할 겁니다.

-

아래는 이전 pass의 결과물에 특정 색을 혼합하는 간단한 후처리 쉐이더입니다.

-
const colorShader = {
-  uniforms: {
-    tDiffuse: { value: null },
-    color:    { value: new THREE.Color(0x88CCFF) },
-  },
-  vertexShader: `
-    varying vec2 vUv;
-    void main() {
-      vUv = uv;
-      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
-    }
-  `,
-  fragmentShader: `
-    varying vec2 vUv;
-    uniform sampler2D tDiffuse;
-    uniform vec3 color;
-    void main() {
-      vec4 previousPassColor = texture2D(tDiffuse, vUv);
-      gl_FragColor = vec4(
-          previousPassColor.rgb * color,
-          previousPassColor.a);
-    }
-  `,
-};
-
-

위 코드에서 tDiffuse는 이전 pass의 결과물을 받아오기 위한 것으로 거의 모든 경우에 필수입니다. 그리고 그 바로 밑에 color 속성을 Three.js의 Color로 선언했습니다.

-

다음으로 vertex 쉐이더를 작성해야 합니다. 위 코드에서 작성한 vertex 쉐이더는 후처리에서 거의 표준처럼 사용하는 코드로, 대부분의 경우 바꿀 필요가 없습니다. 뭔가 많이 설정한 경우(아까 언급한 링크 참조)가 아니라면 uv, projectionMatrix, modelViewMatrix, position 변수는 Three.js가 알아서 넣어줍니다.

-

마지막으로 fragment 쉐이더를 생성합니다. 아래 코드로 이전 pass에서 넘겨준 결과물의 픽셀 색상값을 가져올 수 있습니다.

-
vec4 previousPassColor = texture2D(tDiffuse, vUv);
-
-

여기에 지정한 색상을 곱해 gl_FragColor에 결과를 저장합니다.

-
gl_FragColor = vec4(
-    previousPassColor.rgb * color,
-    previousPassColor.a);
-
-

추가로 간단한 GUI를 만들어 rgb의 각 색상값을 조정할 수 있도록 합니다.

-
const gui = new GUI();
-gui.add(colorPass.uniforms.color.value, 'r', 0, 4).name('red');
-gui.add(colorPass.uniforms.color.value, 'g', 0, 4).name('green');
-gui.add(colorPass.uniforms.color.value, 'b', 0, 4).name('blue');
-
-

색을 혼합하는 간단한 후처리 쉐이더를 완성했습니다.

-

- -

-

언급했듯 이 글에서 GLSL의 작성법과 사용자 지정 쉐이더를 만드는 법을 모두 다루기는 무리입니다. WebGL이 어떻게 동작하는지 알고 싶다면 이 시리즈를 참고하세요. Three.js의 후처리 쉐이더 소스 코드를 분석하는 것도 좋은 방법입니다. 상대적으로 복잡한 쉐이더도 있지만 작은 것부터 차근차근 살펴본다면 언젠가 전체를 이해할 수 있을 거예요.

-

아쉽게도 Three.js의 후처리 효과 대부분은 공식 문서가 없어 예제를 참고하거나 후처리 효과의 소스 코드를 직접 분석해야 합니다. 부디 이 글과 이 시리즈의 렌더 타겟에 관한 글이 좋은 출발점을 마련해주었으면 좋겠네요.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/prerequisites.html b/manual/ko/prerequisites.html deleted file mode 100644 index 1d742eb2a15ccb..00000000000000 --- a/manual/ko/prerequisites.html +++ /dev/null @@ -1,321 +0,0 @@ - - - 먼저 알아야 할 것들 - - - - - - - - - - - - - - -
-
-

먼저 알아야 할 것들

-
-
-
-

이 시리즈는 Three.js에 입문하는 초심자를 위한 튜토리얼입니다. 이 시리즈는 -독자가 최소한 자바스크립트 기본 프로그래밍에 익숙하며, DOM이 무엇인지 설명할 -수 있고, HTML과 자바스크립트로 DOM 요소를 조작할 수 있다는 전제 하에 작성하였습니다. -또한 <script type="module"> 태그로 ES2015 모듈을 -불러올 수 있으며, CSS 셀렉터가 무엇인지도 -알고, ES5, ES2015, 약간의 ES2016도 알며, 브라우저가 자바스크립트를 이벤트와 콜백으로만 -실행한다는 것도 알고, 클로저가 무엇인지까지 안다고 가정했죠.

-

이번 글에서는 시리즈를 읽는 데 필요한 이런 기본 전제에 대해 간단히 환기하고 -넘어가겠습니다.

-

ES2015 모듈

-

ES2015 모듈은 스크립트 안에서 import 키워드나, 인라인 <script type="module"> -태그로 불러올 수 있습니다. 두 가지 예시를 동시에 써보죠.

-
<script type="module">
-import * as THREE from 'three';
-
-...
-
-</script>
-
-

모듈의 경로는 반드시 상대 경로나 절대 경로여야 합니다. <img>, <a> 태그, CSS 경로와 -달리 여기서 상대 경로란 ./이나 ../로 시작하는 경로를 말합니다.

-

더 자세한 것은 이 글의 마지막 부분을 참고하세요.

-

document.querySelectordocument.querySelectorAll

-

요소를 선택할 때는 document.querySelectordocument.querySelectorAll을 -사용하면 됩니다. 첫 번째는 CSS 셀렉터와 일치하는 첫 번째 요소를 반환하고, 두 번째는 -CSS 셀렉터와 일치하는 모든 요소를 반환하죠.

-

onbody를 쓰지 마세요

-

옛날에 개발된 많은 페이지가 body 태그의 onload 속성을 사용합니다.

-
<body onload="somefunction()">
-

이런 스타일은 더 이상 권장하지 않습니다. script 태그를 페이지의 끝에 삽입하세요.

-
<html>
-  <head>
-    ...
-  </head>
-  <body>
-     ...
-  </body>
-  <script>
-    // inline javascript
-  </script>
-</html>
-
-

또는 defer 속성을 사용하는 -것이 좋습니다.

-

클로저(closure)란?

-
function a(v) {
-  const foo = v;
-  return function() {
-     return foo;
-  };
-}
-
-const f = a(123);
-const g = a(456);
-console.log(f());  // 123 출력
-console.log(g());  // 456 출력
-
-

위 예제에서 함수 a는 매번 호출할 때마다 새로운 함수를 반환합니다. 이는 상수 foo에 -대한 클로저이죠. 자세한 건 여기를 -참고하기 바랍니다.

-

this 이해하기

-

this는 마법이 아닙니다. this는 다른 인자들처럼 자동으로 함수에 넘겨지는 일종의 변수이죠. -간단히 함수를 직접 호출하는 경우를 예로 들어보겠습니다.

-
somefunction(a, b, c);
-

여기서 thisnull입니다(엄격(strict) 모드나 모듈 안에서). 반면 . 연산자를 붙여 메서드로 -호출하는 경우,

-
someobject.somefunction(a, b, c);
-

thissomeobject로 지정될 겁니다.

-

많은 사람들이 헷갈리는 부분은 메서드를 콜백 처리할 때이죠.

-
 const callback = someobject.somefunction;
- loader.load(callback);
-

자바스크립트에 능숙하지 않은 사람이 보기에는 문제가 없을지 모르나, loader.load는 콜백 함수를 -. 연산자를 써서 호출하지 않으므로-loader가 별도로 this를 지정하지 않는 한-this는 null이 -됩니다. 콜백 함수를 호출할 때 thissomeobject로 지정하려면 명시적으로 this를 종속시켜야(binding) -합니다.

-
 const callback = someobject.somefunction.bind(someobject);
- loader.load(callback);
-

this를 이해하기 어렵다면, this에 관한 문서를 -한 번 읽어보길 권합니다.

-

ES5/ES2015/ES2016

-

var 대신 constlet 사용하기

-

constlet을 쓸 수 있는 환경에서 var를 써야할 이유는 전혀 없고, 지금 var를 사용하는 -것은 실력 향상에 전혀 도움이 되지 않습니다. 변수를 재할당할 일이 없을 경우 const를 사용하세요. -변수를 재할당하는 것은 흔치 않은 일이니, 주로 const를 더 많이 쓰게 될 겁니다. 변수의 값을 바꿔야 -한다면 let을 사용하세요. 이런 습관을 들이면 버그를 훨씬 더 많이 줄일 수 있습니다.

-

for(elem in collection) 대신 for(elem of collection) 사용하기

-

for offor in의 문제를 해결하기 위해 새로 추가된 문법입니다.

-

예를 들어 객체의 키/값 쌍을 반복문으로 돌릴 경우 다음과 같이 쓸 수 있죠.

-
for (const [key, value] of Object.entries(someObject)) {
-  console.log(key, value);
-}
-
-

forEach, map, filter 등을 적절히 활용하기

-

ES5에서 배열에 forEach, -map -메서드 등이 추가되었고, ES2015에서는 filter -메서드 등 여러 유용한 메서드가 추가되었습니다.

-

구조분해할당(destructuring) 사용하기

-

const dims = { width: 300, height: 150 }. 이런 객체가 있다고 해보죠. 객체의 -각 속성을 별도의 변수에 할당하고자 합니다.

-

기존 방법

-
const width = dims.width;
-const height = dims.height;
-
-

새로운 방법

-
const { width, height } = dims;
-
-

구조분해할당은 배열에도 적용할 수 있습니다. const position = [1, 2, 3, 4]. -이런 배열이 있다고 해보죠.

-

기존 방법

-
const x = position[2];
-const y = position[1];
-
-

새로운 방법

-
const [ , y, x ] = position;
-
-

또한 매개변수에도 구조분해할당을 적용할 수 있습니다.

-
const dims = { width: 300, height: 150 };
-const position = [1, 2, 3, 4];
-
-function distFromOrig([x, y]) {
-  return Math.sqrt(x * x + y * y);
-}
-
-const dist = distFromOrig(position);  // dist = 2.236...
-
-function area({ width, height }) {
-  return width * height;
-}
-const a = area(dims);  // a = 45000
-
-

객체 선언 시 축약 문법 사용

-

기존 방법

-
 const width = 300;
- const height = 150;
- const obj = {
-   width: width,
-   height: height,
-   area: function() {
-     return this.width * this.height
-   },
- };
-
-

새로운 방법

-
 const width = 300;
- const height = 150;
- const obj = {
-   width,
-   height,
-   area() {
-     return this.width * this.height;
-   },
- };
-
-

전개 연산자 ... 사용하기

-

전개 연산자는 매우 유용합니다. 예를 들어보죠.

-
 function log(className, ...args) {
-   const elem = document.createElement('div');
-   elem.className = className;
-   elem.textContent = args.join(' ');
-   document.body.appendChild(elem);
- }
-
-

또 배열을 인자로 넘겨줄 때도 유용합니다.

-
const position = [1, 2, 3];
-somemesh.position.set(...position);
-
-

배열을 얕은 복사할 때 사용할 수도 있고

-
const copiedPositionArray = [...position];
-copiedPositionArray.push(4); // [1,2,3,4]
-console.log(position); // [1,2,3] 기존 배열은 영향을 받지 않음
-
-

객체를 합칠 때도 사용할 수 있죠.

-
const a = { abc: 123 };
-const b = { def: 456 };
-const c = { ...a, ...b };  // c = { abc: 123, def: 456 }
-

class 사용하기

-

ES5 이하의 문법으로 클래스 스타일의 객체를 만드는 방법은 다른 개발자들에게 낯선 요소 -중 하나였습니다. ES2015부터는 C++/C#/Java 등 다른 객체지향 언어처럼 class 키워드를 사용해 -클래스를 생성할 수 있습니다.

-

getter와 setter

-

모던 프로그래밍 언어에는 대부분 -getter와 -setter가 -있습니다. ES2015의 class 문법을 사용하면 훨씬 쉽게 getter와 setter를 설정할 수 있죠.

-

화살표 함수(arrow function) 활용하기

-

화살표 함수는 특히 콜백과 프로미스를 처리할 때 유용합니다.

-
loader.load((texture) => {
-  // 불러온 텍스처를 사용
-});
-
-

화살표 함수는 this 값을 지정하지 않습니다.

-

(※ 원문에서는 "Arrow functions bind this.(화살표 함수는 this를 바인딩한다.)"라고 적었지만, -표준에 기재된 바 화살표 함수는 익명 함수로 this, arguments, super 또는 new.target을 지정하지 -않습니다. 혼돈을 막기 위해 달리 번역하였으니 참고 바랍니다. 역주. 출처: MDN)

-
const foo = (args) => {/* code */};
-
-

위 예제는 다음과 과 같죠.

-
const foo = (function(args) {/* code */}).bind(this));
-
-

프로미스(Promise)와 async/await

-

프로미스는 비동기 처리를 도와줍니다. async/await는 프로미스를 좀 더 쉽게 쓰도록 도와주죠.

-

이 둘은 짧게 다루기 어려우므로 다른 글(프로미스, -async/await)을 -참고하기 바랍니다.

-

템플릿 리터럴(Template Literals)

-

템플릿 리터럴은 따옴표 대신 백틱(backticks, 억음 부호)을 사용한 문자열입니다.

-
const foo = `템플릿 리터럴 문자열입니다`;
-

템플릿 리터럴은 문자열에 2가지 기능을 더한 것인데요. 하나는 여러 줄에 걸쳐 쓸 수 -있는 기능입니다.

-
const foo = `템플릿
-리터럴
-문자열입니다`;
-const bar = "템플릿\n리터럴\n문자열입니다";
-
-

예제의 foobar는 같은 문자열이죠.

-

다른 하나는 문자열 중간에 자바스크립트 표현식을 끼워넣을 수 있는 기능으로, -${ 자바스크립트 표현식 }처럼 사용합니다.

-
const r = 192;
-const g = 255;
-const b = 64;
-const rgbCSSColor = `rgb(${r},${g},${b})`;
-
-

함수를 실행하거나

-
const color = [ 192, 255, 64 ];
-const rgbCSSColor = `rgb(${ color.join(',') })`;
-
-

계산식을 넣을 수도 있습니다.

-
const aWidth = 10;
-const bWidth = 20;
-someElement.style.width = `${ aWidth + bWidth }px`;
-
-

자바스크립트 네이밍 컨벤션(coding convection, 코딩 스타일 규약) 지키기

-

코드를 작성하는 것은 여러분의 자유지만, 웬만하면 한 가지 규약은 지키는 것이 좋습니다. -자바스크립트의 변수, 메서드, 함수 이름은 전부 lowerCamelCase이죠. 생성자나, 클래스의 -이름은 UpperCamelCase입니다. 이 규약만 따른다면 자바스크립트의 세계에서 크게 문제될 -것은 없죠. 대부분의 린터(linter)나 린팅 프로그램이 위 네이밍 -컨벤션을 지키지 않는 코드에 대해 에러나 경고를 던집니다.

-

(※ 문서에 따라 lower camel case는 camelCase, upper camel case는 PascalCase로 부르기도 -합니다. 역주.)

-
const v = new vector(); // 모든 클래스가 대문자로 시작할 경우 에러
-const v = Vector();     // 모든 함수가 소문자로 시작할 경우 에러
-
-

Visual Studio Code 사용해보기

-

이 세상에는 훌륭한 에디터가 많습니다. 자신이 좋아하는 에디터를 쓰는 것이 가장 -좋죠. 하지만 아직 마음에 드는 자바스크립트 에디터가 없다면 Visual Studio Code를 -써보세요! 에디터를 설치하고 eslint를 설정 -하면-환경에 따라 시간이 좀 걸릴지 모르나-무수한 자바스크립트 코드의 버그를 -잡는 데 도움이 될 겁니다.

-

예를 들어 no-undef 규칙을 활성화하면 -VSCode는 ESLint를 통해 변수의 값이 지정되지 않은 경우 경고를 출력할 겁니다.

-
- -

위 예시에서 작성자는 doTheThing 함수를 doThing로 잘못 적었습니다. 그러자 doThing -아래에 밑줄이 생겼죠. 그리고 그 위에 커서를 올리면 해당 함수를 선언하지 않았다고 -알려줍니다. 미리 에러를 하나 줄인 셈이죠.

-

THREE를 쓸 때도 경고가 나타날 것이므로 코드 상단에 /* global THREE */를 선언해 -THREE가 미리 선언되었음을 알려줄 수 있습니다.

-
- -

위 이미지에서 ESLint는 대문자로 시작하는 이름은 생성자이니 new 키워드를 사용하라고 -알려줍니다. new-cap 규칙 덕에 에러를 하나 -더 줄였네요.

-

이 외에도 설정할 수 있는 규칙이 거의 100개 정도 더 -있습니다. 아까 var 대신 constlet을 쓰라고 했었죠.

-

아래 이미지에서 작성자는 var를 썼는데, let이나 const를 쓰라는 경고를 받았습니다.

-
- -

let을 쓰고 재할당을 하지 않자 const를 쓰라고 제안합니다.

-
- -

물론 var가 더 좋다고 생각하면 이 규칙을 꺼버리면 됩니다. 이 규칙을 쓰는 건 제가 성능과 -버그 예방 면에서 var보다 letconst를 쓰는 걸 더 좋아하기 때문이죠.

-

일부 파일이나 코드의 일부분에서 규칙을 덮어 씌워야 할 경우, 주석을 추가해 규칙을 끌 수 -있습니다.

-

구형 브라우저를 지원해야 한다면 트랜스파일러를 쓰세요

-

대부분의 모던 브라우저가 자동 업데이트 기능을 사용하기에 최신 문법을 사용해 생산성과 -버그 예방 두 마리의 토끼를 동시에 잡을 수 있습니다. 만약 꼭 구형 브라우저를 지원해야 -한다면 ES5/ES2015 등의 최신 문법을 구형 문법으로 변환시켜주는 트랜스파일러를 -사용하길 권장합니다.

- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/primitives.html b/manual/ko/primitives.html deleted file mode 100644 index 05a18112c3456f..00000000000000 --- a/manual/ko/primitives.html +++ /dev/null @@ -1,333 +0,0 @@ - - - 원시 모델(primitives) - - - - - - - - - - - - - - -
-
-

원시 모델(primitives)

-
-
-
-

※ 이 글은 Three.js의 튜토리얼 시리즈로서, -먼저 Three.js의 기본 구조에 관한 글을 -읽고 오길 권장합니다.

-

Three.js에는 다양한 원시 모델이 있습니다. 먼저 Three.js의 원시 모델이란, -주로 런타임에서 다양한 인자들로 정의한 3D 모양을 의미합니다.

-

원시 모델은 주로 구체로 공 모양을 만든다거나, 수많은 육면체를 모아 -3D 그래프를 만드는 데 사용합니다. 또한 3D에 입문한다거나, 모의 -프로젝트를 만들 때 사용하기도 하죠. 물론 대부분의 3D 앱은 그래픽 -전문가가 블렌더(Blender), 마야(Maya), -시네마 4D(Cinema 4D) 등으로 -만든 그래픽 모델을 사용합니다. Three.js도 이런 외부 모델을 불러올 수 -있지만, 이건 나중에 알아보기로 하고 일단 이 글에서는 사용 가능한 원시 -모델에 무엇이 있는지 살펴보도록 하죠.

-

앞으로 소개할 원시 모델들은 대부분 기본값이 있으므로 필요에 따라 -인자를 넣어주면 됩니다.

-
육면체(Box)
-
원(flat circle)
-
원뿔(Cone)
-
원통(Cylinder)
-
십이면체(Dodecahedron)
-
사각(bevel)을 주어 깍아낸(extruded) 2D 모양입니다. -아래에서는 하트 모양으로 깍아냈죠. ExtrudedGeometry는 나중에 설명할 -TextGeometryTextGeometry의 기초 모델입니다.
-
이십면체(Icosahedron)
-
선(line)을 회전시켜 만든 모양입니다. 램프, 볼링핀, 초, 초 받침, 와인잔, 유리잔 등이 있죠(물레로 도자기를 만드는 것처럼. 역주). 2D 형태를 점(point, Vector2 클래스를 말함. 역주)을 사용해 지정하고, Three.js에게 축을 따라 세분값(아래 예제의 segments 값. 역주)과 회전값(아래 예제의 phiLength 값. 역주)을 지정해주면 됩니다.
-
팔면체(Octahedron)
-
2D 격자값(격자 하나의 벡터값)을 받아 3D 값을 반환하는 함수를 인자로 전달하여 면을 만듭니다.
-
2D 평면(2D plane)
-
다면체입니다. 주어진 3D 점들(아래 verticesOfCube. 역주)을 중심으로 삼각형(아래 indicesOfFaces. 역주)을 구 형태로 잇습니다.
-
중앙이 빈 2D 디스크(disc)입니다.
-
삼각형으로 이루어진 2D 윤곽선입니다.
-
구(Sphere)
-
사면체(tetrahedron)
-
3D 폰트와 문자열로 만든 3D 텍스트입니다.
-
원환체(torus), 도넛(donut)
-
원환체 매듭(torus knot)
-
패스를 따라 이어진 원입니다.
-
다른 geometry를 받는 헬퍼 객체로, 각 면 사이의 각이 일정 값 이상일 때만 모서리를 표시합니다. 상단의 육면체 예제를 보면 육면체를 만드는 삼각형이 표면에 전부 표시된 것을 확인할 수 있는데, EdgesGeometry를 사용할 경우 표면에 있던 선들이 전부 사라집니다. 아래 예제의 thresholdAngle 값을 조정해 해당 값 이하인 모서리가 전부 사라지는 것을 확인해보세요.
-
매개변수로 받은 geometry의 모서리 하나당 하나의 선분(2개의 점)을 가진 geometry를 생성합니다. WebGl은 보통 선분 하나당 2개의 점을 필요로 합니다. 때문에 이 모델을 사용하지 않는 경우, 모서리가 없어지거나 추가되는 현상이 발생할 수 있습니다. 예를 들어 2D 삼각형을 만드는 경우, 대부분 3개의 점을 이용해 삼각형을 만들려고 할 겁니다. wireframe: true라는 옵션이 있기는 하나, 이를 이용해 삼각형을 만들면 (WebGl은 삼각형을 만들 때 6개의 점을 요구하므로. 역주) 출력되는 건 선 하나 뿐일 겁니다. 삼각형 geometryWireframeGeometry에 넘겨주면 6개의 점과 3개의 선분을 가진 새 geometry를 생성합니다.
- -

커스텀 geometry를 만드는 법에 대해서는 -나중에 자세히 다룰 것이므로, 지금은 각 원시 모델로 예제를 만들어 보겠습니다. -예제 코드는 지난 글에서 썼던 예제를 쓸 거에요.

-

먼저 배경색을 지정합니다.

-
const scene = new THREE.Scene();
-+scene.background = new THREE.Color(0xAAAAAA);
-
-

이는 옅은 회색으로 배경을 칠하라는 의미이죠.

-

모든 물체를 봐야 하므로 카메라도 수정합니다.

-
-const fov = 75;
-+const fov = 40;
-const aspect = 2;  // the canvas default
-const near = 0.1;
--const far = 5;
-+const far = 1000;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
--camera.position.z = 2;
-+camera.position.z = 120;
-
-

다음으로 x, y 좌표와 Object3D를 매개변수로 받아 씬에 추가하는 addObject -함수를 만듭니다.

-
const objects = [];
-const spread = 15;
-
-function addObject(x, y, obj) {
-  obj.position.x = x * spread;
-  obj.position.y = y * spread;
-
-  scene.add(obj);
-  objects.push(obj);
-}
-
-

물체를 무작위로 채색하는 함수도 하나 만듭니다. hue, 채도, 명도로 -색을 지정하는 Color의 기능을 활용할 거에요.

-

hue는 0부터 1까지의 색상값을 고리 모양으로 배치한 것으로, -12시는 빨강, 4시는 녹색, 8시는 파랑입니다. 채도(saturation) -또한 마찬가지로 0부터 1까지이며, 0은 색이 가장 옅은 것, 1은 -색이 가장 진한 것을 의미합니다. 명도(luminance)에서 0.0은 -검정, 1.0은 하양으로, 0.5가 가장 색이 가장 풍부합니다. 쉽게 -말해 명도가 0.0에서 0.5로 갈수록 검정에서 hue에 가까워지고, -0.5에서 1.0으로 갈수록 hue에서 하양에 가까워지는 것이죠.

-
function createMaterial() {
-  const material = new THREE.MeshPhongMaterial({
-    side: THREE.DoubleSide,
-  });
-
-  const hue = Math.random();
-  const saturation = 1;
-  const luminance = .5;
-  material.color.setHSL(hue, saturation, luminance);
-
-  return material;
-}
-
-

위 예제에서는 materialside: THREE.DoubleSide 옵션을 -지정했습니다. 이는 Three.js에게 삼각형의 양면 모두를 렌더링하라고 -알려주는 것이죠. 구나 정육면체 같은 물체는 보이지 않는 안쪽 면을 -굳이 렌더링할 이유가 없지만, 예제의 경우 PlaneGeometry나 -ShapeGeometry 등 안쪽 면이 없는 물체를 만들 것이므로 -side: THREE.DoubleSide 옵션을 설정하지 않으면 반대편에서 봤을 때 -물체가 사라진 것처럼 보일 겁니다.

-

중요한 건 side: THREE.DoubleSide 옵션은 렌더링 속도에 영향을 줍니다. -실제로 사용할 때는 필요한 물체에만 지정하는 게 좋겠지만, 지금은 -물체의 수가 많지 않으므로 일단 넘어가겠습니다.

-

다음으로 addSolidGeometry 함수를 만듭니다. 이 함수는 매개변수로 -받은 geometry와 앞서 만든 createMaterial 함수를 사용해 -무작위로 색칠한 물체를 만들고, addObject 함수로 씬에 추가합니다.

-
function addSolidGeometry(x, y, geometry) {
-  const mesh = new THREE.Mesh(geometry, createMaterial());
-  addObject(x, y, mesh);
-}
-
-

이제 이를 활용해 주요 원시 모델을 생성할 수 있습니다. -예를 들어 정육면체를 만든다고 해보죠.

-
{
-  const width = 8;
-  const height = 8;
-  const depth = 8;
-  addSolidGeometry(-2, -2, new THREE.BoxGeometry(width, height, depth));
-}
-
-

아래 코드를 보면 각 geometry마다 비슷한 단락으로 이루어진 것을 확인할 수 있습니다.

-

- -

-

몇몇 예외가 보일 텐데, 가장 크게 두드러진 것은 아마 TextGeometry일 겁니다. -TextGeometry는 텍스트의 mesh를 생성하기 위해 3D 폰트 데이터를 필요로 합니다. -이 데이터는 비동기로 로드되므로, 객체를 생성하기 전에 3D 폰트 데이터가 로드되기를 기다려야 -하죠. 폰트 로드 과정을 프로미스화 하면 이 과정를 더 쉽게 만들 수 있습니다. 먼저 FontLoader를 -생성하고, Promise를 반환하는 loadFont 함수를 만들어 요청을 Promise로 감쌉니다. -그리고 doit이라는 비동기 함수를 만들어 await 키워드로 폰트를 로드한 후, geometry를 -만들고 addObject 함수로 씬에 추가하죠.

-
{
-  const loader = new FontLoader();
-  // promisify font loading
-  function loadFont(url) {
-    return new Promise((resolve, reject) => {
-      loader.load(url, resolve, undefined, reject);
-    });
-  }
-
-  async function doit() {
-    const font = await loadFont('resources/threejs/fonts/helvetiker_regular.typeface.json');  /* threejs.org: url */
-    const geometry = new TextGeometry('three.js', {
-      font: font,
-      size: 3.0,
-      height: .2,
-      curveSegments: 12,
-      bevelEnabled: true,
-      bevelThickness: 0.15,
-      bevelSize: .3,
-      bevelSegments: 5,
-    });
-    const mesh = new THREE.Mesh(geometry, createMaterial());
-    geometry.computeBoundingBox();
-    geometry.boundingBox.getCenter(mesh.position).multiplyScalar(-1);
-
-    const parent = new THREE.Object3D();
-    parent.add(mesh);
-
-    addObject(-1, -1, parent);
-  }
-  doit();
-}
-
-

또 다른 차이점은 Three.js의 텍스트는 기본적으로 중앙을 중심으로 돌지 -않는다는 것입니다. 기본 회전축은 왼쪽 모서리로, 중앙을 중심으로 돌게 -하려면 Three.js에게 geometry의 bounding box(경계 좌표)를 계산해 -달라고 요청한 뒤, bounding box의 getCenter 메서드에 해당 mesh의 -위치값 객체를 넘겨주어야 합니다. 이러면 getCenter 메서드는 넘겨받은 -위치값의 중앙 좌표값을 자신의 위치값으로 복사합니다. 그리고 변경된 위치값 -객체를 반환하는데, 이 객체의 multiplyScalar(-1) 메서드로 전체 텍스트의 -회전 중심이 텍스트의 중앙에 오도록 조정할 수 있습니다.

-

만약 이대로 다른 예제처럼 addSolidGeometry 함수를 호출한다면 위치값을 -재할당해버릴 겁니다. 그러니 대신 Three.js의 씬 그래프의 기본 요소(node)인 -Object3D를 하나 만듭니다(Mesh 또한 Object3D의 자식 요소임). -씬 그래프가 어떻게 작동하는가에 대해서는 다른 글에서 자세히 다룰 것이므로, -당장은 DOM 요소처럼 자식 요소가 부모 요소를 기반으로 생성된다는 -것만 알아둡시다. Object3D를 생성해 텍스트를 감싸면 텍스트의 회전 중심은 -유지한 채로 위치값을 얼마든지 조정할 수 있습니다.

-

만약 addSolidGeometry를 그냥 사용한다면 아래 왼쪽의 예제처럼 -회전축이 아예 빗나가겠죠.

-

- -

-

예제의 왼쪽 텍스트는 회전축이 중앙에서 벗어났지만, 오른쪽 텍스트는 -중앙을 중심으로 회전합니다.

-

다른 예외는 2개의 선을 기반으로 한 EdgesGeometryWireframeGeometry입니다. -addSolidGeometry 함수 대신 아래와 같은 addLineGeometry 함수를 호출했죠.

-
function addLineGeometry(x, y, geometry) {
-  const material = new THREE.LineBasicMaterial({color: 0x000000});
-  const mesh = new THREE.LineSegments(geometry, material);
-  addObject(x, y, mesh);
-}
-
-

이 함수는 검은 LineBasicMaterial을 만들고 이를 기반으로 LineSegments를 -만듭니다. LineSegmentsMesh의 자식 객체로, Three.js의 선분(line segments, 선분 하나당 점 2개) -렌더링을 도와주는 객체입니다.

-

원시 모델을 생성할 때 인자는 차이가 있으니 공식 문서를 참고하시거나, -각 원시 모델 예시 위에 공식 문서 링크가 있으니 해당 링크를 참고하시기 바랍니다.

-

소개하지 않은 클래스 중에 위 패턴으로는 사용하기 어려운 클래스가 있습니다. -PointsMaterialPoints 클래스인데요. PointsGeometryBufferGeometry를 -매개변수로 받는다는 점에서 위 예제의 LineSegments와 비슷하나, 선 대신 각 정점에 -점(point)을 그린다는 점이 다릅니다. 또 점의 크기를 지정하는 size도 -PointsMaterial에 함께 넘겨주어야 하죠.

-
const radius = 7;
-const widthSegments = 12;
-const heightSegments = 8;
-const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
-const material = new THREE.PointsMaterial({
-    color: 'red',
-    size: 0.2,     // 글로벌 단위
-});
-const points = new THREE.Points(geometry, material);
-scene.add(points);
-
-
-
-
- -

sizeAttenuationfalse로 지정하면 -카메라로부터의 거리에 상관없이 점의 크기가 일정하게 보입니다.

-
const material = new THREE.PointsMaterial({
-    color: 'red',
-+    sizeAttenuation: false,
-+    size: 3,       // 픽셀
--    size: 0.2,     // 글로벌 단위
-});
-...
-
-
-
-
- -

또 하나 집고 넘어가야 하는 것은 Three.js의 물체 대부분이 -세분값에 대한 설정이 다양하다는 겁니다. 좋은 예로 구체가 -있죠. 구체는 얼마나 물체를 세분할지에 대한 값을 매개변수로 -받습니다.

-
-
-
-
-
- -

위 그림에서 첫 번째 구체는 둘레로 5개, 높이로 3개의 면으로 분할되었습니다. -이는 15개의 면 또는 30개의 삼각형이죠. 두 번째 구체는 24 x 10, 240면 또는 -480개의 삼각형입니다. 마지막 구체는 50 x 50으로 무려 2500면 또는 5000개의 -삼각형에 해당하죠.

-

얼마나 많이 세분할지는 필요에 따라 다르게 설정하면 됩니다. 위 예제만 보면 -많이 분할할수록 좋아보이나, 선과 플랫 쉐이딩(flat shading)만 제거해도 -아래와 같은 결과가 나옵니다.

-
-
-
-
-
- -

5000 삼각형인 오른쪽 구체가 480 삼각형인 중간 구체보다 훨씬 좋다고 -이야기하기 모호합니다. 만약 지구본을 만들기 위한 구체 하나를 만든다고 -하면, 10000개의 삼각형으로 구체를 만드는 것이 나쁜 선택은 아닙니다. -하지만 1000개의 삼각형으로 만든 구체 1000개를 렌더링할 경우, 이는 총 -천만개의 삼각형이 됩니다. 이를 부드럽게 움직이려면 브라우저가 1초에 -60프레임을 렌더링해야 하니, 결과적으로 이는 1초에 6억개의 삼각형을 -렌더링하라고 하는 것과 같죠. 절대 간단한 연산이 아닙니다.

-

물론 선택이 쉬운 경우도 있습니다. 예를 들어 평면을 분할한다고 해보죠.

-
-
-
-
- -

왼쪽의 평면은 2 삼각형입니다. 오른쪽 평면은 200 삼각형이죠. -구체와 다르게 평면은 대부분의 경우 퀄리티 저하가 아예 없습니다. -평면을 변형해 다른 것을 만드는 경우가 아니면, 평면을 분할해야할 -이유는 없죠.

-

그러니 상황에 따라 적절한 값을 선택하기 바랍니다. 물체를 덜 분할할수록 -성능도 올라가고 메모리 점유율도 낮아질 테니까요. 상황에 따라 어떤 것을 -포기할지 결정하는 것은 순전히 여러분의 몫입니다.

-

원시 모델 중 어떤 것도 실제 프로젝트에 적용하기가 어렵다면, -.obj 파일 또는 .gltf 파일을 -로드하여 사용할 수 있습니다. 또는 -커스텀 BufferGeometry를 생성할 수도 있죠.

-

다음 장에서는 씬 그래프와 그 사용법에 대해 -알아보겠습니다.

-

- - - -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/rendering-on-demand.html b/manual/ko/rendering-on-demand.html deleted file mode 100644 index 6925261ecce6ed..00000000000000 --- a/manual/ko/rendering-on-demand.html +++ /dev/null @@ -1,228 +0,0 @@ - - - 불필요한 렌더링 없애기 - - - - - - - - - - - - - - -
-
-

불필요한 렌더링 없애기

-
-
-
-

대부분의 개발자에게 이 주제는 너무 뻔할 수 있지만, 필요한 누군가를 위해 -글을 써보려 합니다. 대부분의 Three.js 예제는 렌더링 과정을 계속 반복합니다. -그러니까 아래와 같이 재귀적으로 requestAnimationFrame 함수를 사용한다는 -거죠.

-
function render() {
-  ...
-  requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
-
-

계속 애니메이션이 있는 경우에야 별 상관이 없지만, 애니메이션이 없는 경우라면 -어떨까요? 이 경우 불필요한 렌더링을 반복하는 것은 연산 낭비일 뿐더러 사용 -환경이 모바일이라면 사용자의 배터리까지 낭비하는 셈입니다.

-

처음 한 번만 렌더링하고, 그 후에 변화가 있을 때만 렌더링하는 것이 가장 정확한 -해결책일 겁니다. 여기서 변화란 텍스처나 모델의 로딩이 끝났을 때, 외부에서 -데이터를 받았을 때, 사용자가 카메라를 조정하거나, 설정을 바꾸거나, 인풋 값이 -변경된 경우 등 다양하겠죠.

-

반응형 디자인에 관한 글에서 썼던 예제를 수정해 -필요에 따른 렌더링을 구현해봅시다.

-

먼저 뭔가 변화를 일으킬 수 있는 요소가 필요하니 OrbitControls를 추가합니다.

-
import * as THREE from 'three';
-+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-...
-
-const fov = 75;
-const aspect = 2;  // canvas 기본값
-const near = 0.1;
-const far = 5;
-const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-camera.position.z = 2;
-
-+const controls = new OrbitControls(camera, canvas);
-+controls.target.set(0, 0, 0);
-+controls.update();
-
-

정육면체에 애니메이션을 넣지 않을 것이니 이들을 참조할 필요가 없습니다.

-
-const cubes = [
--  makeInstance(geometry, 0x44aa88,  0),
--  makeInstance(geometry, 0x8844aa, -2),
--  makeInstance(geometry, 0xaa8844,  2),
--];
-+makeInstance(geometry, 0x44aa88,  0);
-+makeInstance(geometry, 0x8844aa, -2);
-+makeInstance(geometry, 0xaa8844,  2);
-
-

애니메이션과 requestAnimationFrame 관련 코드도 제거합니다.

-
-function render(time) {
--  time *= 0.001;
-+function render() {
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
--  cubes.forEach((cube, ndx) => {
--    const speed = 1 + ndx * .1;
--    const rot = time * speed;
--    cube.rotation.x = rot;
--    cube.rotation.y = rot;
--  });
-
-  renderer.render(scene, camera);
-
--  requestAnimationFrame(render);
-}
-
--requestAnimationFrame(render);
-
-

그리고 render 함수를 직접 호출합니다.

-
render();
-
-

이제 OrbitControls가 카메라 설정을 바꿀 때마다 직접 render 함수를 호출해야 -합니다. 뭔가 복잡할 것 같지만 다행히 OrbitControls에는 change 이벤트가 있습니다.

-
controls.addEventListener('change', render);
-
-

또한 창 크기가 바뀔 때의 동작도 직접 처리해야 합니다. render 함수를 계속 호출할 -때는 해당 동작을 자동으로 처리했지만, 지금은 render 함수를 수동으로 호출하므로 -창의 크기가 바뀔 때 render 함수를 호출하도록 하겠습니다.

-
window.addEventListener('resize', render);
-
-

이제 불필요한 렌더링을 반복하지 않습니다.

-

- -

-

OrbitControls에는 관성(inertia) 옵션이 있습니다. enableDamping 속성을 true로 -설정하면 동작이 좀 더 부드러워지죠.

-

※ damping: 감쇠.

-
controls.enableDamping = true;
-
-

또한 OrbitControls가 부드러운 동작을 구현할 때 변경된 카메라 값을 계속 넘겨주도록 -render 함수 안에서 controls.update 메서드를 호출해야 합니다. 하지만 이렇게 하면 -change 이벤트가 발생했을 때 render 함수가 무한정 호출될 겁니다. controls가 change -이벤트를 보내면 render 함수가 호출되고, render 함수는 controls.update 메서드를 -호출해 다시 change 이벤트를 보내게 만들 테니까요.

-

requestAnimationFrame이 직접 render 함수를 호출하게 하면 이 문제를 해결 할 수 -있습니다. 너무 많은 프레임을 막기 위해 변수 하나를 두어 요청한 프레임이 없을 경우에만 -프레임을 요청하도록 하면 되겠네요.

-
+let renderRequested = false;
-
-function render() {
-+  renderRequested = false;
-
-  if (resizeRendererToDisplaySize(renderer)) {
-    const canvas = renderer.domElement;
-    camera.aspect = canvas.clientWidth / canvas.clientHeight;
-    camera.updateProjectionMatrix();
-  }
-
-+ controls.update();
-  renderer.render(scene, camera);
-}
-render();
-
-+function requestRenderIfNotRequested() {
-+  if (!renderRequested) {
-+    renderRequested = true;
-+    requestAnimationFrame(render);
-+  }
-+}
-
--controls.addEventListener('change', render);
-+controls.addEventListener('change', requestRenderIfNotRequested);
-
-

창 크기 변화가 일어났을 때도 requestRenderIfNotRequested를 호출하도록 합니다.

-
-window.addEventListener('resize', render);
-+window.addEventListener('resize', requestRenderIfNotRequested);
-
-

차이점을 느끼기 어려울지도 모르겠습니다. 화살표 키를 쓰거나 예제를 드래그해 보고 -다시 위 예제를 이리저리 돌려보세요. 차이점이 느껴질 거예요. 위 예제는 화살표 키를 -눌렀을 때 일정 거리만큼 순간이동하지만 아래의 예제는 약간 미끄러집니다.

-

- -

-

간단한 lil-gui를 추가해 반복 렌더링 여부를 제어할 수 있도록 하겠습니다.

-
import * as THREE from 'three';
-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-

먼저 각 정육면체의 색과 x축 스케일을 조정하는 GUI를 추가합니다. 조명에 관한 글에서 -썼던 ColorGUIHelper를 가져와 쓰도록 하죠.

-

먼저 GUI를 생성합니다.

-
const gui = new GUI();
-
-

그리고 각 정육면체에 material.color, cube.scale.x 설정을 폴더로 묶어 -추가합니다.

-
function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-
-  cube.position.x = x;
-
-+  const folder = gui.addFolder(`Cube${ x }`);
-+  folder.addColor(new ColorGUIHelper(material, 'color'), 'value')
-+      .name('color')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.add(cube.scale, 'x', .1, 1.5)
-+      .name('scale x')
-+      .onChange(requestRenderIfNotRequested);
-+  folder.open();
-
-  return cube;
-}
-
-

lil-gui 컨트롤(control)의 onChange 메서드에 콜백 함수를 넘겨주면 GUI 값이 바뀔 -때마다 콜백 함수를 호출합니다. 예제의 경우에는 단순히 requestRenderIfNotRequested -함수를 넘겨주면 되죠. 그리고 folder.open 메서드를 호출해 폴더를 열어 둡니다.

-

- -

-

이 글이 불필요한 렌더링 제거에 대한 개념을 조금이라도 잡아주었길 바랍니다. 보통 -Three.js를 사용할 때는 이렇게 렌더링 루프를 제어할 일이 없습니다. 대게 게임 또는 -애니메이션이 들어간 3D 컨텐츠이기 때문이죠. 하지만 지도나, 3D 에디터, 3D 그래프, -상품 목록 등에서는 이런 기법이 필요할 수도 있습니다.

- -
-
-
- - - - - - - - diff --git a/manual/ko/rendertargets.html b/manual/ko/rendertargets.html deleted file mode 100644 index c7dd3fafa1caff..00000000000000 --- a/manual/ko/rendertargets.html +++ /dev/null @@ -1,173 +0,0 @@ - - - 렌더 타겟(Render Targets) - - - - - - - - - - - - - - -
-
-

렌더 타겟(Render Targets)

-
-
-
-

Three.js의 렌더 타겟이란, 직접 렌더링할 수 있는 텍스처(texture)를 말합니다. -한 번 텍스처로 렌더링한 뒤에는 다른 텍스처처럼 사용할 수 있죠.

-

간단한 예제를 만들어보겠습니다. 반응형 디자인에 관한 글에서 -썼던 예제를 가져오도록 하죠.

-

렌더 타겟을 만드는 방법은 기존 렌더링 방법과 유사합니다. 먼저 WebGLRenderTarget 인스턴스를 -생성합니다.

-
const rtWidth = 512;
-const rtHeight = 512;
-const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
-
-

그리고 CameraScene(장면)을 추가합니다.

-
const rtFov = 75;
-const rtAspect = rtWidth / rtHeight;
-const rtNear = 0.1;
-const rtFar = 5;
-const rtCamera = new THREE.PerspectiveCamera(rtFov, rtAspect, rtNear, rtFar);
-rtCamera.position.z = 2;
-
-const rtScene = new THREE.Scene();
-rtScene.background = new THREE.Color('red');
-
-

위 예제에서는 렌더 타겟의 가로세로비(aspect, 종횡비)를 canvas가 아닌 렌더 타겟 -자체의 사이즈로 구했습니다. 렌더 타켓의 가로세로비는 텍스처를 사용할 물체에 맞춰 -정해야 하기 때문이죠. 예제의 경우 렌더 타겟을 정육면체의 텍스처로 사용할 것이고, -정육면체의 모든 면은 정사각형이므로 가로세로비는 1.0입니다.

-

그리고 이전 글에서 썼던 조명과 정육면체 3개를 추가하겠습니다.

-
{
-  const color = 0xFFFFFF;
-  const intensity = 1;
-  const light = new THREE.DirectionalLight(color, intensity);
-  light.position.set(-1, 2, 4);
-*  rtScene.add(light);
-}
-
-const boxWidth = 1;
-const boxHeight = 1;
-const boxDepth = 1;
-const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-function makeInstance(geometry, color, x) {
-  const material = new THREE.MeshPhongMaterial({color});
-
-  const cube = new THREE.Mesh(geometry, material);
-*  rtScene.add(cube);
-
-  cube.position.x = x;
-
-  return cube;
-}
-
-*const rtCubes = [
-  makeInstance(geometry, 0x44aa88,  0),
-  makeInstance(geometry, 0x8844aa, -2),
-  makeInstance(geometry, 0xaa8844,  2),
-];
-
-

이전 글의 SceneCamera는 그대로 둡니다. 이 둘은 canvas를 렌더링하는 -데 사용할 거예요.

-

먼저 렌더 타겟의 텍스처를 사용하는 정육면체를 추가합니다.

-
const material = new THREE.MeshPhongMaterial({
-  map: renderTarget.texture,
-});
-const cube = new THREE.Mesh(geometry, material);
-scene.add(cube);
-
-

그리고 render 함수 안에서 렌더 타겟의 장면을 먼저 렌더링한 뒤,

-
function render(time) {
-  time *= 0.001;
-
-  ...
-
-  // 렌더 타겟의 장면 안에서 정육면체를 각각 회전시킵니다
-  rtCubes.forEach((cube, ndx) => {
-    const speed = 1 + ndx * .1;
-    const rot = time * speed;
-    cube.rotation.x = rot;
-    cube.rotation.y = rot;
-  });
-
-  // 렌더 타겟의 장면을 렌더 타겟에 렌더링합니다
-  renderer.setRenderTarget(renderTarget);
-  renderer.render(rtScene, rtCamera);
-  renderer.setRenderTarget(null);
-
-

canvas에 렌더 타겟의 텍스처를 사용하는 정육면체를 렌더링합니다.

-
  // 장면 중앙의 정육면체를 회전시킵니다
-  cube.rotation.x = time;
-  cube.rotation.y = time * 1.1;
-
-  // 장면은 canvas에 렌더링합니다
-  renderer.render(scene, camera);
-
-

붐!

-

- -

-

정육면체가 빨간 건 정육면체를 잘 보이도록 하기 위해 rtScenebackground -속성을 빨강으로 설정했기 때문입니다.

-

렌더 타겟의 용도는 무궁무진합니다. 그림자가 렌더 타겟을 -사용하고, 피킹(picking)도 렌더 타겟을 사용할 수 있죠. -많은 후처리 효과를 사용할 때 렌더 타겟이 필수 -요소인 경우도 있고, 차의 후사경(rear view mirror, 백미러)이나 모니터 화면 등에도 -렌더 타겟을 활용할 수 있습니다.

-

이번 글은 여기까지입니다. 마지막으로 WebGLRenderTarget을 사용할 때의 주의해야 -할 점 몇 가지만 살펴보고 끝내도록 하죠.

-
    -
  • 기본적으로 WebGLRenderTarget은 2개의 텍스처를 생성합니다. 하나는 색상 텍스처이고, 다른 하나는 깊이/스텐실(depth/stencil) 텍스처이죠. 깊이 텍스처나 스텐실 텍스처를 사용하지 않을 거라면 인스턴스 생성 시 옵션을 지정해 텍스처를 아예 생성하지 않도록 할 수 있습니다.

    -
      const rt = new THREE.WebGLRenderTarget(width, height, {
    -    depthBuffer: false,
    -    stencilBuffer: false,
    -  });
    -
    -
  • -
  • 렌더 타겟의 크기를 바꿔야 한다면

    -

    앞선 예제에서는 렌더 타겟을 생성할 때 고정 사이즈, 512x512를 사용했습니다. 하지만 후처리 등에서 렌더 타겟을 사용할 경우, canvas 크기와 렌더 타겟의 크기를 똑같이 설정하는 것이 일반적입니다. 예제를 바탕으로 이를 구현하려면 canvas의 사이즈가 변경되었을 때 카메라와 렌더 타겟의 사이즈를 변경해주어야 하죠.

    -
    function render(time) {
    -  time *= 0.001;
    -
    -  if (resizeRendererToDisplaySize(renderer)) {
    -    const canvas = renderer.domElement;
    -    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    -    camera.updateProjectionMatrix();
    -
    -+    renderTarget.setSize(canvas.width, canvas.height);
    -+    rtCamera.aspect = camera.aspect;
    -+    rtCamera.updateProjectionMatrix();
    -}
    -
  • -
- -
-
-
- - - - - - - - \ No newline at end of file diff --git a/manual/ko/resources/fonts/LICENSE.md b/manual/ko/resources/fonts/LICENSE.md deleted file mode 100644 index 3c20052f9a971e..00000000000000 --- a/manual/ko/resources/fonts/LICENSE.md +++ /dev/null @@ -1,73 +0,0 @@ -Link: https://www.jeonnam.go.kr/contentsView.do?menuId=jeonnam0603080000 - -# 제 1유형: 출처 표시 - -이 페이지는 공공누리 이용약관과 등록된 저작물의 유형안내에 대하여 이해하기 쉽게 요약한 것입니다. - -## 이용자가 가지는 권리 - -1. 온·오프라인 상에 공유 및 이용 : 온·오프라인을 통하여 공유 및 이용 가능 -2. 저작물 변경 : 2차적 저작물로 변경하여 이용 가능 -3. 이 저작물은 영리 목적으로 이용할 수 있습니다. - -## 저작물 사용 조건 -- 출처 표시 : 저작물의 출처를 표시하셔야 합니다. - -※ 공공기관이 후원한다거나 공공기관과 특수한 관계에 있는 것처럼 제 3자가 오인하게 하는 표시를 해서는 안됩니다. - -## 알아야 할 사항 - -### I. 이용조건의 표시 및 변경 - -1. 이용자가 공공누리 저작물 활용시 출처표시를 꼭 해주셔야 합니다. -2. 공공누리 저작물의 이용조건은 변경될 수 있습니다. 다만 이용자가 이용조건 변경전 사용하셨다면 해당저작물 한해 용도변경 없이 계속 이용할 수 있습니다. - -### II. 이용조건의 위반 - -1. 이용자가 공공누리 이용조건을 위반할 경우 그 즉시 이용허락이 종료됩니다. -2. 이용자가 이용조건 위반 후 지속적으로 공공저작물을 이용할 경우 저작권 침해가 성립되므로 형사상, 민사상 책임을 부담 하실 수 있습니다. - -### III. 공공기관의 면책 - -1. 공공기관은 공공저작물의 정확성이나 지속적인 제공 등을 보장하지 않습니다. -2. 공공기관 및 그 직원은 이용자가 공공저작물을 이용함으로써 발생할 수 있는 어떠한 손해나 불이익에 대해서도 책임을 지지 않습니다. - -### IV. 기타 - -1. 이용자가 저작물을 보유하고 있는 공공기관으로부터 별도의 이용허락을 받은 경우 공공누리 조건을 적용하지 않으셔도 됩니다. - ---- - -# 공공누리 제 1유형의 이용조건 - -위 공공누리에 따라 이용자는 다음에서 제시하는 조건을 준수할 경우 공공저작물을 상업적 활용 여부에 관계없이 무료로 자유롭게 -이용하고 2차적 저작물 작성 등 변형하여 이용할 수 있습니다. - -## 출처 표시 의무 - -1. 이용자는 공공저작물을 이용할 경우, 다음과 같이 출처 또는 저작권자를 표시해야 합니다. -ex) "본 저작물은 'OOO(기관명)'에서 'OO년' 작성하여 공공누리 제O유형으로 개방한 '저작물명(작성자:OOO)'을 이용하였으며, -해당 저작물은 'OOO(기관명), OOO(홈페이지 주소)'에서 무료로 다운받으실 수 있습니다." - - * 위 내용은 예시이므로 작성연도 및 해당 기관명과 홈페이지 주소, 작성자명 기입 - -2. 온라인에서 출처 웹사이트에 대한 하이퍼링크를 제공하는 것이 가능한 경우에는 링크를 제공하여야 합니다. - -3. 이용자는 공공기관이 이용자를 후원한다거나 공공기관과 이용자가 특수한 관계에 있는 것처럼 제3자가 오인하게 하는 표시를 해서는 안됩니다. -이용이 제한되는 정보 - -## 다음과 같은 정보는 공공저작물에 포함되어 있더라도 관련 법령에 따라 이용이 제한됩니다. - -1. 개인정보보호법, 정보통신망 이용촉진 및 정보보호에 관한 법률 등에서 보호하는 개인정보 -2. 신용정보의 이용 및 보호에 관한 법률 등에서 보호하는 신용정보 -3. 군사기밀보호법 등에서 보호하는 군사기밀 -4. 상표권, 디자인권, 특허권 등 다른 권리의 대상이 되는 정보 또는 제3자의 저작권 등이 있는 정보 -5. 기타 다른 법령에 따라 이용이 제한되는 정보 - -## 공공기관의 면책 -1. 공공기관은 공공저작물의 정확성이나 지속적인 제공 등을 보장하지 않습니다. -2. 공공기관은 이용자가 공공저작물을 이용함으로써 발생할 수 있는 어떠한 손해나 불이익에 대해서도 공공기관 및 그 직원은 책임을 지지 않습니다. - -## 이용허락조건 위반의 효과 - -이용자는 공공누리의 이용허락의 조건 중 어느 하나라도 위반한 경우 이용허락이 자동으로 종료되며, 이용자는 즉시 공공저작물의 이용을 중단해야 합니다. \ No newline at end of file diff --git a/manual/ko/resources/fonts/PureunJeonnam-Bold.ttf b/manual/ko/resources/fonts/PureunJeonnam-Bold.ttf deleted file mode 100644 index e6ad23fbc2dbf58b0e80bfe40fefdd2ba88fb2c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5398072 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 GQIDMVuRNNF?5yGg>(0u!*mwE- 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%0D|rq+Hop& zFE8$idE@#7s7HBqk96NWKhofDE(QQJ(l8YOdbDA{muDaVsB-!CAJXdIH*r0${^Prr z>XV`TSu6a}#K(=Ak$M0ipU7vgy2#qYxz`Kzon-o|tzz=dgar;678E+p@QHmL#A)u7 z0$WmCkL&XyD9nq%&SzpK-WK_pKhE|!Ef89;z6FhgvKtoOr-C1oCifLrk?d z4T4AXU$Gu!)G+Cv8nQAB_uha1>vZ)$6{#*y+;M&Qk_D7*QXUz4v|;=o zWj1wT+t?y4erD_|4cm6^jQjjUn{Tql+*IXox^-)HegR?W5g+4tDNeF#)-3?onZQNo zkd9q|WDmlQD%qH7=*S303SDbyAWJe329U6sAe}7kiqc`_my)K^$&n@vC zm+YTiQ@dy5rCSHbwp=(gl+d2sJ9&tNBsXVvk_WIQVM#(t;90RHDeC7H8W9ovCbIpq zElJ>8cnqtgR#L!|VYh*2BJO}^(kLm!UYRe`+l$jCTQhV>R{ZqtIcu8SGV6YJzmiFdOp{*1F-YjW1;aS(V_h?VBh$O6ebRZ@^S)F|*Zbm)XkaMl(m3?3J_ z1;n4l7;GT6Wiq*xR3R5(ldmH)o6jb=?CM3;{j(--DPhK)t+_&vf!TZ3G#zrrEO0N~F z3^%uojqIiWv>mlIx!fk_k-7z3Ds&_=;L`)N#5?FM?ip9D+kimFLMq#ddkrKn?K)@S z4T>ll^cRl`{l(N&{l()#8tFTU|7__&Yb9%Z-ig-Assj>dnbm|VO~lYiZ!%21;y$cS zJ4YJNoZmO;>A=Ul4KDiRXrke>f_grwx$A+qwsdieI{%BK*V{<>E1*KYbi|}lzh+pR2cFz zv-UM13~BGb{=|v-v8K7ldamj}JpQnmqmt0`5s8ll!oE$%$07y=3lK4Cwg6G}go-`R z;sRqMt{CV(v!u-Q{^+-rX(@?&*-{b|EG1sUjq-VLzm_Bl@qdm<@!v;GN~D9Z0g6mw z(r!u>>80!@3T!&m$gyLG4js}aw{1M-_C95|c=LUJpZSWiwH>x{kI^to#P5!&lVgeN zmE5txG3|;yKRDRYHEUnngSNQKT$pRJyf?nN!D{rBQOPNFs-+0tW$GPRZxI>4gVzNN zC-e>5Q5_j}l%OtVN72*7;i4DmAMw;dT8!gy;F?QPF8T|&FGBahu0&^A=2n}$M|fxG z`XauibDF509{UxBhKMnU5NU?|Wykiua%^56$MvYJQ3o2EY#Vo-su|tCf4>qt_Q=q= z$oPMS2o+FFl9;JIF-!Cr3HPK>JCSE=$WQWI{M~!PTv{upVa5aBio-IkjKt0i2S+ z!%6pc?hf{D^AF>H%7cfsgn)Er<2jY69>ED$&$_bnrlf~EJisA?Gn+N_p0R~vBZ=Rr zzC<{Q>eO{${agP@eeItkU#EgHl;Ak<8Cd_+Wj(nc14H)=%@a5ybfH;Z2mUH3sUTLX zhnkYmDO$4H#;7x;mP)U5yF+y=)OcSR(|$Skk|nig+)Ay_WGjj~wZFAIw%y+7!FMl{6tsG+q=Y?7Qh}GIC8arF0*oxIcTg0sem#y7U=P5DSRjcMxFP%I;di?mE_U1WD>r1P` zHAgLRug_|^zr3R%XfilUOSO>+?fcN%S3i*(JJ{V_u(aR%sR#-N-OnEFODRu#HN#`I+rd@K9PQ=cS zZ(H7cw!o~Im}~ziTeW^;wWru*Q)@q^v|X<~`Dvx?x>v@J963#_TU=97@2qkhV&2_D zyel;sT)|RpY@hb^@6bP%C7fmVQ<9}x+Ktc`;D1AwGNlLHW2pr9DkW7(R8&&1KI&+# zB@rW8@9#cnMyn`{jvSp%!qNBn_Y zqfLF1PQbvyAs-z-efoW_-leN*0+q!r{_9OHUvYuYVts#EN3`5*wA&pei5G@GdI!P= z`g+3|BCpafMgI9?#G^9$t-RlrW$br?68jxas}f_Vb3hygh%O+;#CQ?uV2&N&{Bqv= zxZ4TECrA$i+v}HC(C@KQQs7{{q>y<)CX{830YRqBl^UYPy^7RO@?1J~RHJi1 zUf0zXmaMsT`(W&>N68DQ`PN#u_UFzIY;gz7)<=eJZQlAi1?vY!$H$KpHO=Y|SJX$U zcjg0Wl7FgYu`}0M8YDebPdG;K(MWZp@E;fE{E2vpc@Kj(^seA3ZISu9kx5^FU_XEgq^&EJ};!t3t@}s2uLvps1_lAU4ZLC1fIq| zA-k+5J7LJVp%@zB@YF5>K+;J#impkElN}ld%Dw*FB4^cD_mE?TnNnL;qd}ubyGwbP z=1Tiz!_ZHvEJlOsDGeGeo?O$A8lP$Y5^sF?5kMhzor^P0UeV_fIu~c7LSi{1=}F5- znh2}NImYza6Jy!4XOnlMx4BR zw!X!6zOwqdYgonJ8)~f&>y3-Q!Is6#bmNXyxM<6n_ViZ2?GaMBcUr_LZCM&2!+toY?$E-@%UZon`B~zPVHGE$>l@Wf_QMahM~2F5 zJBHrIelX;;5nk?oil3sIr&ITP-uWp8A)0}7w2PpCp&@b@+x=x|W* zPf7TEs%r6uH;!y?c;4`J&&l`}Iw#>@_GwYWA#G>%(zQdKC8aeB%I~r0eZn8=AM#V4 zEA(`(*HIKS<=YEPd!PQKnn(Ne9Kzn+NBn}lg%c}ZAc-ra-w(UWKx4VOwlvUNqFM|& zKQWd^WBK}6fgCHKr(BZajIOvJxh}uF#xf?ZLB?w3HLUPPNi`DHEGZyhxg$Y7ak%3} z`bWREl|FNK0@kppqZrbnVY&&+Xa-vFI?wZLX)IUo)FSHE$w{;(P7H3_aK>W!ygSe7 zsCPfsaCNt%)MirN^!ZgoxODx_T@9Z%e7XE&t5q~Y()qqu=X)OQ`Hh68`5^HfSyb#a3US%2 z^F7t!B3F)KW(p;Rxk4o}M^=mFI4qz#N!1Y*l@$7{wMYulo=!=@I^`G->H>R+zdiI9 zy6N*A`aB2G3vS1hR>qdv%Y1YyhfQ>voQ}r^U;5DoiO$xA5$738{tHgGv%&d5P zX`xa1?=RjQJIS^DQJ>Nrf$~`t*#QS-~dmydm(C7K|S?}MDG&uBZvcs)GG}VwO9U<@> zU70HIhWdmytbBtGC0VX@5?7tN+EDDva~uf9t4qwrLVs{5H7A$s;yE#r-dU#4 z32cZ~ima{8`3}trPLyIRq9o0Vz&WfOi$q-9r_TiZ*m=!Pja8m#ih^euhB22xmuR|RnJgOgl-*Y+aEK|PTCfb zp^gk`7K!4onzyB+W6QkiYW{DP@)oP9jU#8={|qhF=y)u87+T7xT*#OzXsKJ~#pCnv z&lFu4_xs}uqtQk2;^O!swSVtl)mH8Mv71)-i#wXOLUUOhS9UKW%~c%QlbX2$m#Zf2 zxk!C|g#OXauz>d2VcIu<8|jvvLtsI}e-?iFyX$W3A-%|ZYzisTD#y^Rle-;OzsT7; zuEFO1A^aTbbh_me`gu##8(A-vp_E73UXZo_&QYjp&4bX9*bmgFI*%XkyjH7Uv*e7` z@)4WKRgm|_NP69&9k&3s?%x#niW-|Nn_QQwU4=Y`XSJA5NHy7SqvFPT4{BuRr zf2G!OpmJ*q6`v?d-K;J!-92}3b=3ogyDE>Xzx~Z05}TD3+85OO2txkUX`Aw`zMIwu zLnUp2x6CEJ z^Nul>xW_TO^lruJeo%V1Vo0}m67>OdX$Co7#pkmL8|Yc`fW&=>C*gb*8BfaIDR{mp zPLx^`I)ccQvX1l>;q#^z1f{utKCJwj`e*Oeifzj8zNk-`*12Hi%|-V)4bFzDtE#t0 z?LmjCR0q3DJ$^+E>oaw?;cO*A+HbAi@k_tWQ1iLx655YnR{mT2bJM{E#eu4t{kEt( zT6Lgl(4A-X2d`97!|ABbHx`(4$1bCJG7=^$)fc&*a_jSRzDzTPSSd%7M0XdgnVCBy zcgnslkYA1lvh5`5XH(IU%nr%b@<~LJI%x*jLK1mKQK!`+??bOZ8_j^QpAdcGJp>*q zV*-qN^l7@TF`T)**kmYrNJ?2TqVD_%&qM3Lnwu^8cR5vOebs^LZH*2rnEI&`p{&=Q zq9V~(w67X&{Kj_^KYrs4wL<$r>*19Zm4Rm8He1XctDI^58dp~D$-aa0RlvRRK; zEq!Z?VY9CLtLd%Q<(#M40Pp|zI|V~~am_R`z36_=6rwEHEto=;epFJhtf0^M8al?U zkkks&Zmaa2T3A#9H@!sOvxMFR+HLKN^iR*$CAC}nYLQ4Gwyi|>;VD=}0x|0K(5ZE# zvaZwayW)DXWDS8li#6tXt7OrNwRM!Fv9GV1RqwgkQgFA+;B+@Q4%Td^sVq{J#;H@O z{`QCG6L%}&->dNpU#>p1&>g6(+-GU<2fWtXf-SWrdU!#lZM}CDZ-=$n?aOsc zG-G;;Lnkt(_dT@KhzCpGTBG+4v5<_f$=RLrbaHOt(`N7NjQ7W0w4I)0YCGM>xkE-G zAsSC3#LoiaC;UTnI_GusD^;<;EWg|X5x-Mx??-7n4S8!@Qi#eX9IoH2KuJ0 z^1iKfALeX~u8gJTEUDpSKaOef)tpb$8@x|@9lqj>vv_GqYpwt0JkzC>H8IjhsxnMbx?SPTot0rvt?L?`0B3Yw8J}w}3>+wKptBotO@-F58t%AiRYhfS+&43BHUkHdq^b(DEU#%IAH8%+c6;-ZCf}Jt>kk~N!`5?olINR>aE#0Jks!@;fF;hn}$zO$YZE_aP3GJg*+CO-)3p{_$@{6n>P{!;OV0V zKZQJurdZn zQ@%^C^2VBr zs_a|O%kZrQb#dR?P2a+D$gy-mLGn7~wN#v9>MksvfLD#*#NP(23Nmiu)VV2je2i)& z6`ticPg(qsXv1Kp@0@7+%o(%!3vQ#^(cpT>H(R*PNp2^DMmn>V%TJypd#GXf^>Uk9 zGJKoY=c{w?w2;@F@3;yHjXa|*K!y-8+wG{fo$X5Rp zX=v0{u`MKeR6v$9J671~e)f{!VHZgXh$_?#@-;->D+Z5OEa%^~WZTL%TG{dm4zsFX1N;1x3u6qoBO^!s1Nk=>XWRn19z*<F5&LiMn%^>*ul~ z6M`sm4vqPeSv*9f1(iqFfTiGTur(}_!k$(tDM)#>q@Y>aB?V0IfTRX!=Fp*#y6Msk zV7?jmhRQ_om-^|6<&w%c2`$S`tY*PZ!l$!@e##^~-?6c`@{EO$JjQ~;M&Fx(g)7!Y z+<`p1dK+z#3$|}M<9g0*aycUIbH2`=IYCDWg{ViS&c}L3^X&d`c}-c_6$Op{fX8}! zh|I%0gR7+URdtW{FKuU+`iooRduc@w(CipxsLKklB93KD&~?OjmGV=6rrh6i#Mx>( z%Yy7TeFd;|i?|QlV!6aG)sxH{iQZ_brH;!Z^4OXZ!AzA8zju=$AB^It{0zFtzOEvcimEl^^J2*>De zpj)*_7fW!Mhnbgz5+XoMkh)ev-cVbM)*CYsb+dnU;p4w5>j|b|>h@mo$>7q+n(LH* z%?8$m4~>rQwL0j`)FiY{-MqKF!*ha|MfOWQ*;K%Yp_hAyfwi z0>7mE#7kt0({sb(Tfn`Lyc2p8oZ`O#PF2xRAfrq{Mjetumwm3Ifust5c{)kuYskqv zh$o`EM2&n3yH7+?0;`W5NqjHxA?Q6O5b9zac37*t3mJR#ZfU0(Xit6?c|1sVCyfJ< zos#UNp3Ii)%=CxSO07F+My}7qH7)!F%|@^%1Q43~1Y!G>SG0;GYE64<;uEviuRo!@ znhj_QZyX(6Z7DJVl$JP|#IC6Yo7<{K$>tS!9qugJu1BMw2f?8n(gA#0MhZ`wE61P@ zO_DMZ1wF|3V+D961w@}uQpi>Tl`Hz3RLd*qY=SQ0e1e9Md-0u+`?$Op(Oh&6VR`3o zY$I;BLFYo_CZ$}|S)}O{MK{=Lb&J3yvlJrm$~7uQ1g>R9sTbUvUlC z%6@qbme_nr%_rXX6Ym$%Y%ZeD(DeiKc_2-@%&hB${?YG{Xf}!l2~Be%8)&6#{@Jti zsj$xs&{Ce<^>Fvf{_B))O@perKY8F&MI)Rf$P1>z0*h{t%H2ny>2`iQRyeZ-W|M@(hwqZ;`X>J^(vuDhg8g2#tB z65q>nBq%XQJTJUH7SkLp7CI?u$fOoUGJxc1RkBj7=>>C{I;y;vOq@KsM~B8s@D}N) zq3ZcVU7f@8tE=Y^cXkcUubvbzuFqcn;o!2!^6P#*x)nAL0kuro7_RWR_IwuDE1tx1 zDK}pdYIh&d?d5S=Ge01i43lIsavprnB|IT_A`|uWB5sPBF>wuOkdUN8#1o@KPxzDX zETWpSDj=yol(X7{hE>{w+Su%|Wsx&f2~g;#`iVxD*7>1rj)2KzzE4>=F`<24o#pFW zw74SHLLtUmtW92@)AqsMVPCGrW~(5%fvvwwU+;yq7Dwr~12G1vu#nZuIYpeW4O|eP zFR9YJsdPP0UI#{q>teW58~SF7XMx|Xl~k>mZ^koF%2vE#7O0;Vpn6R6y~!{6#-wJ7 zZKr~VA|*Eocl;ADdG+oRb75>^zuKH+Ou}WXf04pC}8+o+XpWx3YhZD>PHfVSB5_KAVoJY&y3Y}Q>+Jdp6D2is8BxnEJeER zK=f1O^o?>9m_yWU3$Kp)@zKg>tc>VO3lB+r3u2`)Nx^&RY)!sCIW0Je)l)$oWkoV& z>cl_tN1pXRpy=S|iQhCe1ZSN5$5)PzuiUe(a3b2In%{2z!2`CleG~~mXDCs<;iP%w z_@R^DmTOuaatzjWp3VW-%x02*%zUA|UP#xOA9lJ1i9&S;<6tjVuMw8t0PJD2q?(}t zL^d~zchg8vGCAc=n!V}Vdp&WWd)tDVvy>&&vDem!=gpFVRT~<-0h9fap|cI!=Z}ug z|23g|>YOdzedQ(L%BtN)0t8$9Hp@*VF^W>=y7a{ZyMW~fdZJmEAZQBMSyr0;LS2G@ zWiSvAxF%MNrfOnEb_n``pAh|j$KT6w1TmXdQMdE02qGsgh0jX#WDO%5?7zFcy<7j*dVRk^ugiW}r8kG(0Xle&E=SYrV7?}F zFjH8Gs4-(oROm5<%mQl6n1ZE`dPSyciHb=I9#pfWxK38wiOTD2{he-4qWXchD`7~c z3U!iP6&v-X%{!LG&zkcTgVmzfqy06sV*RFCcS*jjxOrr8shc6Nr;o)xPYtZFgpl+3 zq6-zx(b9{WlbV_t0{fy?I#?@Bo)I)GA4 zj5IHDL}m1sYw0s&9G!9b*$7c>l0rsuwxnj$_cH1Zwc-Ntg-T^klgWTA)yAU^sDBN4eddTjdXwng@clX4O*?Ft}&eY;grj z6}5Zo*6z`X!p4r?vOs0HY%A3omN@gT4>VNL3UHUe@Duy~YZPngko!KgLq2iStBu}j_Xl1FZ=}~+kVc`RYD@lGV%txI23N1G_6G8bzQ1U6bkVlR){t%ckQ%kcX3Z<7 zLZB*#-1kqF#H)(o41ss4ecwmY)1}9JVKpJIl}o>z5xZ0MwOL-n?vE~T^bB!_rL2&o z6PWgPk~Rl@25J$QE`gW>%0tB0!Abrrf|E=MPBH~fHpx2?kHPoJYJsGZp#sZ{&d);C zh`mtOXQAb@aIqBAxKeN=vE!P2^^)B7?MoZZQbksNF_p7LJlb2KrE50SVK-EapHn{n z1cekgUb42RaL*pAW9=nMt+TZcn%h(7zO0}LJK}A@R;U(dNvW29IrzJnup0f81IwdT z-==p6M(h_67L~@>DpiSx;{07PhMmtQ@37G`s1R`IoX(+l7uBskc@Mhn;lv1dE#h0? zwKPep36`hc(3W!F@`MLKK5OaBhw2n^CNrsJ=%4)J7bjn$<2MX$SM`;BlmBLTZS!N= znk^%Qs(rz$xLk4f1OD#W-F`=~(0JP@&`2;bXD_x8$rdx=^ssl~*}MLMVZ>2LJY-$nFq0exOT z_br$AEhlP?q}C8MDydQ8wNLb<@}*dtw&|rnOG?(H81g(cLX$E_opDwk&{0d~iSpW; za}BpLXld9PiALR(-gWNg<~YNa)K5%)>Qj^d2VfDGt0>;pS2p>Q;b%4L*00ePuir$G zg{M3wyS?6fm#<^?tP*!=LBVEwU2|_$prkaoJ-DkgtG3FKIYM)nn_vT*Fae7llWw5*CaGuBK%Xh1eBWu%ggQ3)mBISBxWjWT#mW@pNDa1^%IdK6A!ikFFyL%3W$5=oyuUgb<5L zmSO0~bOo!3CrJHpVQRvx?RDkXd@adu!nN&f9_gTqzly1Zt4gR9hPQqBUH?paVb zX}`^IYT>Pp3GFx3@%?k5VdXo<#K+Xt+J(sYVz191b#Eesp4VU>jm@z^g$)3e?x$)1 z!+m${$R&Z*=VGs6o38f}X^WF>4y^_WhZhZL7O@zGB#k3+iatw%LcJd1ZkP)(#?=6V z%B%(m%DcGYTik`ndy~9|cyfoN7;(Z_XmoNG&j2HVdNI)-2&fc+xuP|IWddzxdTwm9Kp?fYYke1JVKlT-50eKaLl8#@f!X+BUtRzgxZ zkn^83AIKFk%FUnLi-Ev0QTBs(W@PvBB?aymND4VxyQB~o0$#u9MUJ~UZleVptEZLvnSE8J+qYH8J^R`opTqR$ur&NaX9K-2WxgUI!i2h z$}O2I>ye?O)tg=_wi)7ye|HWmA2cR@u9p9~ZhODi=dN-rr)of7LD9Bo4=pZ#aG{*Z z!w2=nWumzh=gUIR)l>ehKj&LXO^5l*CGBF=_YWZ2;i;wTIKCou98;M(j>n+myz-mi zw?!nS$A5{_h%GnCQP`ysnhmx!+T=KJ*RAv`I_U}2Ekx)ucTXqHO!xQcdlae)P!&RR zq$g_Ab)8Y-8sBzeIL@QY8d0x!A~`3w-Awz;?cO3so%?WjsL@qgI7Qhh5$%3L*L_EO z*>GdxOQiC?Y)m|(4rt5I+KUKvzRVKy5UglxWVW65|IlJNCwJVsBUkHKKS1#_%!}x8 z2E{&St+Y@efTcs$>k2IF!0*jIO3snR?i>l?%swx*0%2Mk@?li-Lh3Jz&UDKV!UG@*56~zGTFU5_MbGIH~exrIW6nP&-lLXHMrez z_x%k==I9;^*;!4h%k3^P`tr4(DCK+2*Eij^vohS@dC(RQ1XSm#o|ULfM(^bLWMkp1 zxd2(MU3w2c#M=~CtWtsJMuFg~;6>R_xYKyHA)RQLN*82%dC)zDuE(ggW|@BH={en=4Cg(zF4q&ONZ zt|3y^D6cgV)hQ`p&^c-$Y9w3aH9a;=oJzNH{guuhZ+}-+RcW{IY#=acPir?|y4N9H?u$S2&1o!R09) zpF9Dk!`_5kGKRlON6Vv{3kZI2C5QB#OP5QwbOeQ+vRqy(Cq9I9y(qFcR(TDwStuz) zcF>iRV-d*Wa5Xo)t$_Xw>0VW}d=7hML{f-X#w3LZeOyxT)i_wyP#?; z5@nfkaL&rDadxRW@HFU=6@ens3F+C$t4pMoQ8 z&=q17x}scCu7NgbTm%%=HJpvRF|Y65AX_LpQQ6X>>*&^wERyibVSn3AC{BLUMh4XzaNzDKJ;cVM!rk9Fr7!`T*6Js&A>6*AQ21l@!l`_+?#mZHc_LBt42}%(T5x z2cXA-bWQZO@wzX!j||kGDO8LB3o-pd%eh@Tob~3($!|^F2DHwttIp&Zll$yF-mYHW zXE!+FUH#SdP34uBS{l8jPU~%LE1bDh1MnKv0Njw8w}jBRT;*dL3#s~vlin{R1c zY`!!XSTEd9y^c7wh$5MvrMYUPxq^%uXpHgLob4Bs$o6AL5M$6`PDvs1hFZ~7gkRi; z2!BA{hd%d_7t!SzmA~SiC{Znv0_wP5Qi#L?8NO7X*8qKjZBG6YS7T)GCEy(yz_hc=@jq^zEo?9!n`=K4qzT~R8~glALq9ie`cW!H_jdfP8qSH0eDxV>BcWnMlWY3Y}yAX=06+%CMMpxC_Ig%EFGT~&pAqO2iysMTa-Kuj*H=xcDAR{ zsXk>-i|fLkrZ_LXF>-ylPuMXtqt)2P<{lYI{4RItyeM)Fy*z-?_C_frhR{>&WjX&saxN@1cJ#(Hb478*snSz1?!cuOQ?zzb9^!E67CZ* zs&rfwJhT5dR1@O|Ij)fwXA+%HljtykPaz;hW}*{pl`U!azfQc}rnjZN7{*B{zUwaP zU=$l(HafcO7X%we2l)Hra)0jNMRD)gU_ zFOKY3NbayxT@3kzbD}emPpl_7@=e(y9R(!>FpW>??T`Uo*6l0GB!@2ykN?cD>L;Ub zhlAR5*If^6{prZ~_{ckgLVa&UmqqmOeT8=7TG|_6Nulxpd#sr(b?%T0UZ|vXuwRQY z)Q2(GfKw8YH~uVEq*dOHb?%ZBycMsc7_BV67deJHd99A9R!Lz8Z<7?T5B-wDiGy@( z4)STlx3I@3a&qsmWhbDjD-$Q4G^~0m@$uGeOQUD4N>Q=NfDRVKvKYc zQ3hzfMHJ0NpO?_8SVB)>d?|fiin&N3f!cZ7)~6*U?jo0y#9bvDXmO0Jv&BbK*`eMW zC>5xnl0f+jhE>lczVVLGL5I4Vz8k;JH>WO%4T{&z@f{rBZ=s5!MB2Eh*J29#rG&T_)Gd}2oJ@aR3BWOurGH?CT1bPR8f?y+ zsTA@@`}Wb_PVJ|3;smYSmGsNtuOp%|T_;ErS#cacL8hZjQt(;QdpYuHR{9=E(WBI4 zWwdIirD7zs5cWoD?0*qVx50AZ$p)T<}#c^?d_Sz)3k>vun z`Ls=V&cH%21#M9&sY>ENka#anGGhFmb{k)hk-+kZ#B z6E2EOerc3=g#DWP$phEjP1zD;Qehdvr&LI4*{6g>+$$;g=N!!tyHPJ`A%Pk&$@_3p zB616iVG@yPSVsJJHpUgyyxj_^I7`Ha%}bYW~qm|!`1b*(q_4cTYLf-}$ma89W_ zu|Bf>^{~~LtJC*ZW;DGt`nMh0Buzt_-Nd>jnlqf#F0e^+Nq2~x8#1VZ z5_*NN3BAHpEpY{F5+2Gkw6gIDc@{oLk~_Pn$z7Hmqzj&I3!$z1MQk8eHy3n3_R@Ln{GNZE<`y54EhPvk~qUZwX{DE>LMTSTKA#rb~REuuhQXRD-O69y#( zEng=o*nRbqg6`^+6cAl~k`kv+r%+frsyn>~P;A2bg|s6_lKa@Pj?rb&+o<%4z<>pX z^=|F&!6j?AB-^vk2=-=STjyx)Sr86KTvg7?Em4B3TJJ7tt_|hu=3cpO?lpBykM}+= zbROG#E{cY9kUe{txLQJ7WVW--f=coI@<3-$Ey0(yv2hGG>T+MQb zrwmirT?y8W?YpeCva)ewxN!_*7k^cgjlZge79kce!GQ!Lxhn1h&!_Pq!69ishj;Aobw0oR9uC3S}Q5kI_e$s zx#BIgXQ#gmPP9g&sW;VrZN5$UXU#hNq&^#!-{8r(r~cqFo{YauPJU(2G27lDWozBe ziOV{wsy42Fgy-S|eG~QiTvVx)4X1Y*PUiaT`nzBk#=F2~G}7-&#fkDIm9iGGzj8HO z%5L-eB9r-)(j}}6 zhjm-qOV(n08;%sE25{}lxt=0#WKMm3AK}$M^8WWLp>u_Gi|TzY)mYiGr#sp-e|-Dt zBHQPA8qU=0U67mym-eP&{8Y&23kH3@ki9avb7!ccVpaozc4yt!I{N1(tHG%HZS@5< zr!hAcRX()p^E+Jb+T~Su@O0hZxs48#_J-WbClX)Xp`EABl>z!kc9Y0;8g>2FK=~Bb zaL^68#NU*ii1VSCLhKE?jVX9+unFt*nSsnU&?n-feyUQ+;+bx-8FZ6JSx2WrCjy;o zyMw14MgNky+>Gkqk!}1MA)b_c?Lps4cmWf`-YUR{a>iwxNUc9 zFt}mWo&2)*bq$B}3;dyg@~sQ!hga!!eDmMhq@VvBAj_ajuX;yz5?SLsqPc?r_9$eV znSx(gDJfX6$S?CXV5r4jmGK_Xkn)0Tw8gnhY`5!r)^`-24k!1nd+QJCdzbM<$H>Ck zGt|V}rxe=b?l)TBH-dAU)tj)HMR)JnN1NHE^~t^LvAO$epg+Uf1K!?6OT%@s%DOuW z8@&O$?ZZ9WsMBUiP_e7M*e7ynZ|0mBqLQt&#|@C|A`;AYSF6OY;mrjFy9{U@MvyRS zjJ-WbZm%x6*{5lytf=W^INgX+db3Xk{!Pc)?hx&Y-%9T2k%NonCZgRUjtwq}E$;}0 zI+n-c{9mOxvTNU^*yT4w9?jh4!_}%G(HQIMip4rRnGaaQOGwt~L_f;EHR-3sBR7aS z#|cc__dxW=q4A{T5+_LKA?t)3jL63z5^SS!Xl{>u8oN!sr0VGz+{Y+aiZx|b^VB9a z;}rS9LO?~2VZnCAb}(`3NTIs>#Qp=P%fHV2xjS-5=a0VXwNno%=e{|9mD4gYQQ*32 ze00tCCMqjeuSl-@_s`wSvJz4L>%yydf){E|0ojr`k0weI4S7J#BVx`uWKp+D@5U@C zpuB-|tD-mN7^=7rRl?{Ah<@wjabW6Abmlh9pO{k1r*G4lTQO>z=oC;~ymqyN5A0CO ztVOq2y@5bmL0{c`v)AV`U&0#B8wD2Zd(VB3Ha^tnvo=~6f=)0!(4Ns%h zYA(Ki(~u=Ew=mz7`{CF~lg(t#FLNAJY&Ujv^c0#=>T5H)hFhQ_%67kCjSULZmem)GNT9l8#Y zeDOWvd;oYSVyuI72XQMo?UjN_F=;RgLo!bni<fR{3}P;bn~28)w>m(d2k7%4tw7iy&yxKizH1fnc#S@`R*rE$ z?03vhmt1xs^h*kn7IjQ2HW;&Eup+)$Pn7yQJ&ScTGc}8PlfveR%STe8DMi6ns zi4QALgR&3@V!VqfxbW5JRm)piW3el#9L8(5=XrLAyS({^{JcEJ@5i;D<*DcPzOG_! z3dnbXOalScpK}w<4fZo&%YeS>PMaG+rRJtV-qAq(WE3)Fx{f%Hh(wFLF1oAo-pAkC zPIt_acL0OjO*56m_+-m9X#=&broC3*D5`Qc zy0+Sy>j~PLcI_H%YHD7w`MPCyEp2*cFP+VBEmd5+^clp(3^`WvKfp_>p{Ly79mGp? zW@7(iQHK8^sEhj_Mf5G~aUgCTlvI$oO=tzO&5MZJ+>ZmBK5F#qzZ z{-DL|Ewe^eu38(bty{BfBs9BsUUltz_kLM<33?Z(_oW z&s55ivuv9;kEnfGB26<#7UlarPD8)1r@FArpKs}#M~b;Tzzm(#z6C=)M|;e0b!^p& zN0Q3<$Wl7_JI_&YZSB&qmCidZT=_ZD&C6HppL_k{=!1KIuNp7BcIpV#ndR7${LH6a zWe$0hPm;u99kSg%XBxYGF5Sm=J7i46am5(oxITFYY7}_yE0bf$PM|_LMj8UvLK*R} zS)UJJKlz){cMh>O)bofjpcUZ*ETD0+fKm({TmP6+V9@H}0Buc#&g&hv(>kyUHf$Li|W3~uYa zW=Y+-z28&bxNv^`;$%$NOnnsChS-#|T|dJQrwS}3&gBrjG)>!Rg+1~* zPU#YL9$Vz-7UJxX&e>r(HvBHF2pI&F+h3YHPMe>^L$$rD-A{Wp+*#wk*>_oe-Ob*+ ziwa!cSka!cm5qgg0+YI?{*vfT1nr6MHS^0O|4^1yIbkM?MH1*F1N{f zv~FR*Y&4s4k46?1n{)FmRq6-#{zUnku4l~T>tK#tx}URFkKDtOU|(k-&DU|0-J6Or z`y>U~=h)sXIW~*NIG5w56~Hx5&(eM;zF{6+$LT4b(|sm^7kDS`wQ~3YGN%du~<_RbiI-GQl0}~;g=9zcC%hn0@MU*(sO96SFV*pNuehd zckN2|Guq_!HoDHe$2&*^bm)GXgwT1fXST4tw)87+zS^lsdZlN-Iy~+z?_Sm1w5q#Y`ERU}liD|w z&OgR#YU1&lnwa{tceUpx+%+ZJwv|@b&xv>`hNhm~`!CA365k%ueo|gpSx*1M9H}|} zWUV^RQ`ts)2dWAMu9ESV=;lCGrus~wn*(+XmT&fek>3*6k>A28ID9vHp<0Q%!t14T zM&(&&dFehP3>FXEL|yaXLza)IeyHo{(XJy~Z1z0`MS);EzsgbTQ%%Li9z(e!R$5R& z>bs}?I*T=0?4gs+&MOUc(%Gw8ond#)oStjvzV52G6dH?8JZNx7Xl0!@NwrNr zw(dWtotA|&*$Kn)lFhc=W(x%Bt#yuSuRUVTRcoD*VrzN8Qqa+SywKX@_bMw}jvZ?` z_P7>OFPT(-*50@!`d)XV&1Uj%40Qz@0DkYU>f3we{7AF1!=a~Fh{q5Jkoj9bd(LSdh zvCSLW`bjzw!)R12)}h{RtI_1J9ITjEZa2`We4D>{N#DH9n?@I$S=e{swxRETnj8*8 zPL%u&KI5&2BJRj9i_=L8NNcj^kdBcNV=1pgq0T(^X>GipUOqs7@11I-TvW!_-V8 zs&3SxHac1PpsjFgq0jBEw^SEZd-A;=XRcD`jQDI7#rXx}$L)pj24$%}8{~5|kH1Ae zhbP*wE^@+IXSJ%nm8Gq|eDbsN6-C)r+3mAAO6(7PrXgChqHfi`6AcCTJg7B%?|aIN zw4QTmJ&W_%nrS`H*E`jqI{^C}9T`4{pn#oWKZ5oc;t2O+2NqM@0W4;xq#*5W#6!+7 z1BpDFcnF&pJ_ch55iw0aTP>TL?|7B7r?GiN-K1UjZkGBd$=A@dCk)s84_5nyU!S}N zE^-<_^C@Ns+XuCc7e8raKJkS;1MJYk=MZD4qGkO_-$R@e`+Aprs*89%TTP|*7j+gHIsqVlrkqGGbCKCa3 z{k;@#LLy+^q|HW&lPj`4MCGr?=zo+ezEk*r>d$7aTKiZs26b)CQce(DS3f8d1l_Z0 zSJhuW|K#HCL}#|M_~AX<_FSjh)15#yr;PjyHW&WP0hJnnZf(D#dbZSJ&aI?jQNmC0!RjtGu~aabRyWD%rNO)klI_-sMRJVYo528Q%t&Km3z&WMZGLpichOkhY5AC@Bi}l z9q@5oRo;4UH0m0)Q5$JSQ>0NHX{1pbby?N2d21RMYQ|hz%g1CN`Y9HPBoJ8f&W7|2I2a|Z5^>VM%x;3jJK>DJ-Sj7c?o94IsM0> zwcr?SA;vMP+j66H4qxRPj5>!i zN?f^(n>TH3u5Z}3VM(AH^+wMRkKPS`m!D$!vG!44dlTscODTUMy6+%*zz4O1Xd-Rl zTsk`=WI=R4DptpkPZM4D9K&Br^r7d_GdQOc$g+F}@cK?Qf@Onzyj|iBS#J(CnmB(E znzXzVvI#yhuF|yb9BCW$tVwl#l17`=XfuuG)M$=oZJYQTgY@hrx;M@b{R%TyB%+;a zR)va@IHw5j4mF{a6Ga6V0&APbFYKZg?N@#L<685_avd9yK9E{iRM^rPu3Xgr9y5IP z)*St3uWEA7pPAPNjH7?+-v8%ja-)zDW3RMYv$Hbvv_);1CjR`7pZanRWIuIuCOZ@J zZxynCSYTVAFx#2EadxI00o$_Ej7X0eXKTQZB#$B6pQHHFh|Uc}=LWh5a-Z*!a-T<1 z?z7#=783MB#$?UDmQpKR(~e;71!m~kZVEj!{%vjB!aG+kyUYwl6ISP|*clA_?~i`q z{4Zc~rl!=Ibj_rF2T?6d9M~#3CAbXH)P?lzKHfU6iiMSX_G)iku0Kub7?*Y?)(QIt_M%OJ; zhRrsu13)|6vWfAn){3kZ$L4AW$uHV_(bMv$#@R)!a+kiVXKt$!VOLLf34C@c97VUn zJzF*}4IG~e8-b^fzW4l3U~&rmWvAr^;^6>!>-P$5YcJ7)ZO*;Q=0rBI9L4G{@>p{H zrC;3>wND=-IVJCcg}O(L_7Fvvh@!7ngNgT!l3&l%w-u_TezZ%1uTjr2{xZIvTAyF# z_upZEE8|;7T^j=e-`eNiYT{dvGp|YuI{($q*Ns%yl(v=~ZaEaHu4!#O#Q@ih_2Ue1 zootw3fJq$y2ePJ!R`z<5%J9JmtB`1Dr6X)hLh{(v2ob|xHA40EGNLbV zba_4Mn*!OAy9TP7q5~LPq$4DIM(7z6>iVeN18a1~yps0?!gv$x7iEpU8o3i|=xEat z-IBJ<&yz`_!Lt79T%n-$nhL5|9>(is_@G^xE>pm{rt}xPk}0jH8m5)f+S%pb(r`H` zt(`{B^G81vscCL)Wu(iZFcjE0-2z2HYyps|6!MUDDxE(=jii;skz-sR9f%$S%5JWPqL}D93aOJGZkgXHX`=A%D3CMM7zWcHBoUSZWY3aa#{G@4Y2 zdar`yzv81nTfliC!B5C-lvqipx(3wkRU?UW|VWiZLlC6@ElhGb|_+ zLQ1?S#QW?TumFpR1w4H1h7DTjwfc`=4G!?chisH$dRp6g^igZ%TK!Im697XW}?Dp|l5Og=uFcBHRF^LR}llOwLhH;|nfEpo^1e*WAIYgBJ zX_eQ(k8A1_$Y~+miJa2dwq7Mhz$ID*tyf_Lr`CWGOkcHan`Xc2-o^VGmtSU9Ej&8M%Q`IQiJpial8c_-QT)H|h>fzIT zWDzGLmQFqeon7ncYGnEKtD{&S@M{At0IlWKi2Kqgoz_IRIH>v+8CvXo9r0|f56sLQ zKi*aIO7PaHvIgyHldB7kYftT3I2^fN%Nt%3xJBGQ)gF1*A~?G|a!kJmICK5Ws44I` zMNhPmuN2YJ96e+sx^YxBYDC&nngx~7w+gX{Tzi|3VQ&J03LlWv%n*6cIVJ4uiQVm? zW>Fv~#U2AdZPuy&097FHbWF|9-08ZZwdu}^57=_;rJ=mn^d7KL+*)c`hofq?BhO{G zXwPW-sUX2&ZFt+myIfT>8?GO@W5QLnVe)->O+|LA{ho!1ENiAU%{N)yyv>`LUgDg( z^U_Q2L7kZe!M+VmHU74iMc>jujlZXTF}u06%$83D z^KHkB=Z+e{*f77SWAH4!cbCYW#(M(+M_n|YKN(MtDl78X#oilL%=k{^C}8G0Y348R z?zG`C^cbt`;oT*)Yra3#L#Ow*C=s&|V!6N?EhkBdSZibk zKi51Eo$P*jU};S}ap(g_7SPmA@C52V{E}AeP|8i_T7dTrJkgqDE%32q^pHM}PIV{f z+M`C&`hrd%pAE~qm1t$g23&N-5c|YNfSZhiTTHSs#kSS$ugkBTSxY^*Z6P>pLs{6&{6Nn{Q$=N{{|p>{^J=2PQ)C1|-3d6@WT}{A5@q zK)Pn>%q(`YS2q*d1sp{btxtX;ls~eE);>GN&;vr1Ca7E2zyPxymS|3u0IWPzYVDI@}C*Em&n zO{_%VjGJV$CwGH3qAOnoJOmPvy?q=v^lJ764Qg8fx6EFvK#)DNe|2DgyfAQ8@dn|l zirXM4>t^8>##fe)E!jxFiqZpdRml1WJvjHqsd8^(>B0Fp7o!IxBwvLZUeZnotE2FT zF_qBuxBtRB$OYu4Xl#w37EdwB0?BHxxR1)V))Wcw+<`r7qSf-9#`_mv-txZjFtC5_ znT)+;m{#FolU5uz=~Qu(v9#h?%8StoJ1Sp=9TgFfj9J244BP$H?I;&&Z_MSa*2+=I zI~>c7cRxR{7*D&pdgimb`Zzv2NS%(y(GhRFxn-=mw6uAwrK!3)+WZc<9Ot>A57UN} zj}Seb!~$x$?ByIviuCvJkzg#Gh1B++W<39afpG&ESPhzyd?LG6xy zHNp&{f*b$ED3&~_j!n|P3-XdHj0t<+RBF7@{IJ@XJQ`MjmC4VUG_sSAg$l{{Y8|2C z0Zq@g-(<6wP&`|4+MvC|ompIzpQ`uSyM4KC!ifiiw`FEeR~Bn`-hTTE^*7S>oD%TfSa=re&A@<*Ko%cNGL|X_;BsSNVpW85WAa(k++y#=SX~LZ@xRLyOKT-=uGE z?=|b30pp2FjiBXta`gDBiZ80lNdchy6B!KCn#yY+_*97AVNbwxnlobvcjd>BjGlQYp^Ij{Q|fmG>^v$3f#>vLj~%zoQq# zsG#vk%4iIY<%nr4M^PGk=m~tihbWjYC|IwK)hEzhVoZp$ysTFv z)({@0XbR!qx(M}2NON29SZ_KJziV~+Si%IfH>|U{imf^B+Tyg^3b*FwrE8}Puaz?} zSV}YSJYud3A}<4g{f1T@orBkGTi=#Vb6~3(o7~t^UNP3c;0Sg0dde%N2CtQqu;8z{ zN>BggG2>DFUczBNa0lbCU6gB%dFW3$Mv=sjJ699Mc8htqI%RjvJjfBxgB(TYp^@(A z>tP93k?cVx4&tk&PPS29v60Tm>;uGqF*?VwV29|=L-hAwqpp4p&CumUdtL=s()lZ) zr^U|$8_}^2#-uYL>ldi)lopK2F3Ho<$ooe49?WtXGOy1>m&)fYU#$q0bh&x0)Y{W- z%gET6lb2yRU3i(CtKJev^G;*0v)x~EhwXBA-5u#^|G>`p{od`hIgb3@MNNUGB3ng9 zhNj<-In}14bGdz+udgI_LAiP=ca}D{b$Lq4#`})R+1%!F?4u>MR2=FZ@_4+})dze# zLLRTZy68Cj=C2N{%ePpIkC!!i%hRccS+-Zd{n&H54}PRh+H3aFoM)3pJtO=`|J|ti zDC#>wb^#-O@V&1Wv&L(VFfp1r#6GQ4*8t6(QKK2mYJ3d7m>i^Oo58${jYNSdQ{0i4 zg=)9~HnhnNMgL^ii4$Gd?aSYrlS3PCc8#qXsmS@3P(i?Ht13y)a(W6QJ1tmU*JhbJ>=^k+sNFNRxQVv)tIgpqrX#o5%Xgon%+`qL6m-fKFpq5owUHQL$=OPpQCm(iy2bk0>?|LN>|xJ%=H&(0=K@nTVPb2Im7 z)JAx&tkeqd(50g_y>`+SDsAq*;i={-PgiipKigO3arahSs^vfVROCm$`^~wWLQC;R zPvt?~VjRqC=^LwdRn>WyeLK5cRet{s+^+GO;Ba295qI#A_d>^D@9n6%0uiA@G^Z?& zWAr&QLIMd17gXm^CuEf>*Qs}xp0*VfXO@-~r%kNZhle_24nQz1>a_1~R z$Ubv`^th=FZ_aPdOV89Yv#;?DNk#58)#GlV$Zh@z6uI@)d!WdjeJ?^<$?l22p*Y$e3 z)nYHG7MkAS<%LyRM*H$eIblN3Cmy;Vat?Htaa|iI#^_$+@lEuOj0|mxLx$w&V#p9W ze8}sNpI)p+s9)kxBL`8vQb@$GI)=I#?3d$yXKb%fr$3q(mSwBsxnxfXliaIy3hB&; z%Ah8x6pJ7svg;@Dgzqfxsmw#luft!KeOpHQOj-VE+vReq`b#TY7G5}W=HA7-{QI6O zwP_!+6oKry8L9i$@AUT;WC zmF7Uk`HT=2&O1DEOQE@?(h=UDQI|MPjj+RHs}ZU~=BrUYQI~sfx2R*VPT9Uh5BjKI zZB$(W-bQW-*X9E1$2Pp#Vegf+H)Sjk#zsf}?OB;uNIDN>m)QiNR}7?@{KWXW_FR?vUI8gLO0o);)U-N^8folHLDbMBofj4@&BR_0Z5N(SvDrLH(_ zWK#{T4X4kXIcP((Y4`vjOTDJq>QnO)vCG_5{SGi&Sbe5 z)(1fn5B8D64tOb)qN(}GJ1cJt*5B!PfC0bDog3R2@$0N`ZR^OZDzfNT{qy;U{^|51 zr?uW~j}qj!e)`t2*Ae75wc$ey`Mo7D>toDs#vj~XotaVW{Pv}ne*EJf7dQucm^@7x z1*ogVG{E|e#WtJhjaUOg^<2&&=O~Yhy_di+Nj(rQ2(3WC5e2)p4&7OJQ-kkL``hxY zB_*wShkN!F`7=t}%ZHBTxe7IHo$(IKW-9%5eBy08YwLQ$r^45c)z%I5z0THJT%2aV zZTm=WVS#tdcc?!zyUZ1dXw65D8vhsj3+9vY%UtptTu$#IY)m1$s?3fh(4#f614G-@ ziPsT_mrfNubA*PKPUo%SJm&|~Gw8Zvx(<6vv$_uGAi90ak{D;Eu~9@ak{Epo#jgma=xaq*OpFtlI7~)h=4=I9xSoWMw;z@5!sSY zvki*_anI@Wrd;7P-}LfT(VNzitYM#DEscU|gsNHGIYa6)A$5*5O?e;oTVxo*hZU_j zN7PX{m&(qj#b8!}5iK=HZg`4I6%@K3;3tvi`d*^Wy^Ma|;-2y5IWn|m{~iI5Y7@ra z6Ayjpc@q!SJ|$4l`UXd9>E4;+^$pH$$9{%EuL=z2k^QS34>4Y99Di_m`N2mPKlK({ z3QO& z7YqgFB`kQjsmGR{lYMzBBZyd|Q5*$pbXedhSf!{knM3P|JG>xY+CsFk(9sNabajW9 z#I?zH%eBcP$Y6BP<7i@Z(BsG-?&`uAX^483vqNYt>s1q5+4&`taKDf2uk38BIGde$ zjoWuNC;Q!INP^E?vIlGTim(N}P82%-$(H5iEyh3Td&R=_*Ah=IRxb_sYpc4-7kJ?w zYaqH|;a*9GBH|c~{6q7IC6*XeCdr;b+Otss4&Ayqme`RbmUx)-V2&k5bq~Z6vyRIa z3*zwQd92qyHR_|QIU86;PYtSbgZPU?N9YVB_tZ8oX{fws(I$jc#xYLh5ea!+3sR~o z=#gI~3GHx=Ia70m@H=D%fM{W6*-NP=`sa-Y7GK(>EemS;su^JMRYw7qnvMbrR|Yk& zGNVF_f4Xvc`N}Vg&UjI*s)Q`Bd9iEM()*#iKo-fpLa{3#$5--Wx;naguc)Qf%YJ_ORx<;u0u)GA>s z`K@i-kv+M*Jej>?V+%J%(<0_(vl=cYlkaF;M8b<0 zGorOl$5^83#Ca@HGt@E2&m1+%p)1gD6EzFvU5GGo3hvIJIgogBhdPf4fnGI2bVal~ zdkWpbIoPniPC z#RYA)@$z0*PDx>|-s9-6%6Ao6va9OKGS3#wl-vKYw8Ua5Dyq49aOL}!U+jGU*>^4L zR~0u`4Y+R3YtFZ&7BANi+cWg^yv(CbqjvV~kB?6`HZ^y3?`t_Y*ksIFii?UJ)~o`n z@lCDy81=kXyrbgo5;hE%byfbkBl1zd)lUHCm#p_lTKWpf!SDk5RON zeAa%t_J|rCq0u#JbPe5kmALaV`Wu(gzkGrI-WBxw3R+nbY>AWTQpq4MK24$U<&*nR z#o4k0nbePDs2RuG$9S}&ErstbZ>w{hPPJU-u03tF-cx8Pum=jREUa&AEcDuU6t}en z@@$R_Qs3?`xHjKflpidZEbVp_)?`?Qn)~vcMS702x`^zbjLoHm+TAM;KfLlCvXiJk zHd^6UQ48W{{j+mhcjnc#^;J{&nj`msYdTn3R_M*&n@j!QvkH!s)HsXNavhgD8VRUN zP0P*kT83>Mt@~|_1qGS*9lq|O+#H*AaeZxOTCp?N)!#qp$+4BUmTj)x(U}wZS|!R` zkYAyY8zQFZx1HKg9TLGe{U#oePP2~A@edQo?&S}||?)=mfIU_|>>+!^2ifIN53!Ibnw`INE@}Bj#-l88m|MoZQ zU+Ezf^kjj*pg=3#9B#5%GA-7${bS8JdQqj#H#$C5*WJ_8xub1QcXu%&(v4o~m04I} zrDBD~*R;?vbaUTo%29MC8WGtOqCyW*DTR*6h(-8w&7o9PaT*bJ*{pktU3Yq69jIS4;7udY?_OstnUDlqlI?5yiq zRF0MRRtZrVt{kisqSD<^o<;iBba|0>x9TO|akTTyGt^7|KK+NGsH{9(N3v2QS-Bh- zD-iyhnz4!L#@3KCTzN^$p~2Sk?(u&2bEMd?v|9jGhXhaW6%&K>r7o zIUcrE#luD^*GyM(L@aBdas&+&l;fI$ed;PkyW~}jcFEBUQIczYP0+kd&`eCK`zA@c zk<22&CcR&Rl@n`|nu0IJ1x)sV|Xy_$te7Ly7O*vY6 zj;E&3dO9m}V_ClThG^IHAF^EdH;iUhl*4LX+%$XHM(4PNo4_5 z?yW2_zu%d=eNMy)!so)V@u)@KL30FqwwXS8L?J6t2!7>4%H(FL1bf*bC@Z7kqaLK_ zP92By#k-W?0bg5JGv&W=^z1}! z-Sp&rwkEqhz35GWEv7$gJ;lKL5Ci{B(WXz>r|d&&p|=T>SDKL>?0B%|SvNvte}U-{ zK~7Lejbx@1P&Rpm%xaDEdzj`qy|eNPCE7@2B2l9l`u_t-T|%x=X%|VSkX|bS;3J~Z z-516D2AWOBP@p-+G2~Y^k#r3iw^GwT?G#$y2^w%be50TNJfrXtHPI*0N7N*Cf9WIQ z5qw0gQ6?r@X1V<(fS{ zU)!HT|5-^!pikg0Y1On+)W-~E-hbWXDIia=Jmn_-m=HYWCThU%$RkL8bSssX9ej{{ zhV2nKLTo5vWr1ACh+3|3*h%z8+sRs?Ch5^FT>v)F`?m57NJ58$Av6 z+Et5;*z}d8)W3KrIO57JA{_kS8XR!iFD?`a{%g$CPbYG;pRRe5B6rVgmB#Cy3oib& zE-n^aTi9>RfARxD&Zp5FZZqd_geuo>CoA$$%5TkC+?-?N0Ib*3_mzyVo%{=kShh+N8Z^|FiSPc}G>1qr8gRo=5$Ws2PE%_#?y*r9@B0 zl1mkqOh<{rxwK~B=k-%{AV!(}G-^>J#JY5;5jv=Mh?NPPn0=AJi8%^Bz6WJgbBNtf z1*&Em9j5dX?ncp-a&10aOErke9V&lE!I7`VY5UZEulC#4sq=M2wN^DkhEiCKk^h8%>}0HKCE* zG|D&n#Hn1iBH9kQ&s5?3&$5?3yr4+yyfj0JU=Q4d}o17}7pUGU_i zw8P*URJ!H+K))_E!XDhCM#$4*{7QL@ILae=5EQ!-;;dVCBj`P)H;Di!>O(kEKWs*_ z7k5!4ds%w+P|L0Mjm|Q}-h7i{OUVf|_mS<-SbjG1Uj1vmlN;V3W1p^=>@j25uc)1< zqB{GPwoMN%hI>aQ5A3K`N8 zjjfO&kHK@mcopc$ksd%t<@x0HFX9P7PkB`jQFl;{5Dzh`M)1Cl)Afm#E>sx_53VXe z5{-3=3DpU;4d{9>J6i=6^cS~R7FK6khJ=wzu?JNY4svthwu*d&oSE@XKaPu2@Xzg- z)qmvnk9)3^K?OT~VS6rBAvoe6ERBX&yWAuFOQECdTq^KM+s5I$6s>buOC^sQ&x4GE z8YKS>*S|o7J8P69aT=u@T}-1yJdV6hpt&SzksY#89YsvF%x)W1N1@>$lAZNWM6z$B zHNjCItMp9iB{d`eR!;+@FrjFQ<2l?G^iPa`GJcS!!kc=EJKY6TXRW`qt4ahxIsL^M zr_$55=HzFl${@gK6c46?dQ?~M``2=t#ZfredPL61th>DwGqT^`YbT$BGq)<-KaP;7 zw$fe24b7pde4|8r$vC}gKCCHoDkcgs5M#75Pz@8hB=2M)wUfc;DMzTXTT7H?Ok5s? zKH9FX;rd4M9LHPAk&L(GNGMdvq`yb>hu?<~UXkIZB#n~F9q}n02~s9X^CBUyMI4mz zyMou|rx)h8KDeBEyt^d!$*nG1=;o` zceu=E%h&cz1~?MEe`uoFS=H6C7+4&3Mt(yu=b<-zt|l@s5#bHS{f__5&bR&LBil|yb{ z*V);7W%zANU)bMy{!t6}jSW)V33}SXzUdGcB5J6B6Hr4X`ewOm6y2Zv>KJ-zME$W6 zd4V5-pAhZK)uxWMF;!w+f$^?Z6`RFnLS*k*eX#15LOV)V+tW8Rj*0GD(b9jT^T(N<0!o&MRzTd9{*$N9U_#p&((O`ur^#mR0Ve##?lcR1x9qM59# zZly6xYe=R{HF~ApLEe>5ccJPMKck4K3e*%jxjg14O2Q)NY*bozL{;9o2h=sFPLp(h zh>tZ<8f224+OoySSkfLhhV>C+*rt8O_=DqkR%%*aRzY+AL}{-tubO&~tt%U-#h#E| z8!XQ}>p%m&v*_dW0jhLZjXq8rrfkJ`MitaYUrt%e zGA5dtJyp3?)0&sEVT<-^l5|7e^f2jdsP>PjE{;73Cy71jrRzBMMA|TjsgTFGj-4Du z>(~X=6^Jh5`1&lOX@F=7jUW97`KhQCi8z!*yT+2BsU#DKG215FHJ>v(GM#eWs^nrx zS7OcB?lX>AX2NJYrX_t>^Nt;FP{Ofh!pqXJVWTR*h1P^uLpT~i?U%9{lZAM3hsd>R zB%Nb@%5kD7bTIBqxIU&YA^OX3U&7dZLmo@MZ#1cU(AguTMv%PYYJ@%sO2>Fb?o*&f zl7_I!b`+{*=I2^wVn^{-KHs%_#D7G4(H{0LG#Bhh!j~w$n{A~Y zVpMv!y~EsM+Rr~#+&?i>9jXA9IBH9Z^ zNvDO)ji~dB*EfHRx+ck5=ExXD9b-g}$YbDSj(@ciPj(Sc0^I{LBr#~zl8fqc8^tP5 zQcEtnV+(I#EIPVs!N*mRTc21(?yqjevD2kp9^T5!2YggNJ3VVGeAZ^0b-N%pjk{$D zxzgro)G?o?R!JRBXU7Kph4#7mH%bmZQ9J3*q~@AgHwQKo2U8Z?;%6=iwfi^KUp0Kk zM99d|(<61w?d{FYp%7?oNf{%(4t-dQC=acX^j9FsyhB?l-=$t?c95@mYLsWvmNj0F zpt4_`1xMEj$`vJ4;p?(flkEY$qaBI*X|nt3m~Ut)99|sudWRRo;iVzpnf}g-24{Z0 zv!SB1U!S0yaP8snzVW)c@qJGhmWek5N0q7(BpI|g^dXj4RM0WrXI<);i=GEwsiA9`3XMtM z7;Zv>fy~P3R=mI2WPGM(Xg(C0AFinx#`jQ-J``=28u?;xFxZQap4u_j>vs3fb(r7A z^+%0Q=-)Z^Z+gye!^6X2`p|oCAU%zHj#bdVsa0rd74&bcq)$cMdsn1Xs`oCYx8zZ= zIiu+7E{~NFWjtyGDpt}Pa|RUNyXVX>HDR`ER%J%VE`<&LkzJwCt`Wcd*1wK~ z*%BiYNzh-4d}ye(bqF8r-@}V&06@I4Fhsq^77iaXzN}wQiAhgCX44&1R%~E!2AQTC zNFFl{){$R%yNFPOR~Zo}Q*ktyN*OR|KxgSqxZb(r9Q=ByCoRv{5LJBQEeGg+i9z(L z^N2*Np))K!-~o|$N)HGsR?1^QOF%bB73LYB)T`-6aW2Fq!uO2)a>AzDO2}G@!5W2c zv`ctXItpYmb1ZXhs98r$wR70-AKppKwXWvb?27KvQinzB+f{VGW^)%RjcKAUohKq7!Td+CGNl;|pLPVp*kbwAW~+o|t6UvLwqBhY!OO+69$2;C^nhdP}c5kGWmF8$3p_B=TQ@xVTw0nx*T#^t^eR)5i#dkXP-ds z@dk;jM2q4IHj;|Xx|~ni*d-ev_nGFrqo628fC$hjX1r?7wOc56`q5!~Nnl-L)4HZo zZ5%Ue6l9jRI_>3_)cpLs+QxvrCDfwky2UUw{WFe=3I{%Vdg9bOeXjX=XSFBXP*&Cu z)~`PHp!P)M=YPpewdi)lELyWNGc4)#0j*l=GAG?Qywmt&x!+&z@cVghpC$VUJdh{$ zn=Vm>1F>W5KWmJ$kmTrM77{9UMzcJsXb)ri2)K5Q8euK7zqn2vLq-64h(dmGt#e=& zvDQ(6N5thPk!Fyw>K2(=^>(7Q)UT+<#mH9GU(R@3>G>x zaD8NXN7qcJiQQvoE2gU%$wvlEj~dCUW#mUc$EZ&aJ)?|%W2Y=8ny@_t?B6A*8|}RHs+*S zEro@43f#*T_15*b9{Y^;^~gsL7zgx+)WoF4%u6}FeGlp8(C_Pk4 zl-AR#`O^L+77-sctLKZ_Xg9^L8SQH`Ijg2Da(Z4HG>*L7diX!kZ;L}qeKHukbHx*9ckF<%^I zi1|XjJRsxpo*i`0oR~xGN(1ix0YwUSzX#bysITov4W~KJ3$-M>5FZ3xmpw`zux)yjF0kKl8g6XJfrg&nkv`wxd`HLpkk2=S??IpbRS*&# zzTep0)*9|^YwM;~->JrZ`a9dV_jx>h+uJ+l@I80n*bj8={4ZX2%BHt=j*oZJ2XvV+ z>5@s75A2C9;W0vg74{g_B=H!9=t^39Vfcq7>J9Cf^W>nZ$@9?Es??~8u4Wt3tBzp> zmJ?Oj#sH`D9u1EXI=YydOC3~u#FJPJ4t7W4?yRw&NOtayJif~MdP1Tf<>s~6e;<11?&6B9Z2iV~a_N=?Gd1#)(xJ&IPjh=+ z?cKReC5}AXgME9-tOb=WY6oomR`36vG+t>Pf_B{39R8k3(yFhdRfs%xyyIjX?Iz7A zZP2couH~3*cr2t0MvXN-Dr>AgMjkqOOiE5v{9>wY75sETszqbNWc~@Hp!AN@57nyt zqJ*qoONa7LBv3Wc_>X)?bR@5D2#Sv6^nH`ky?OsXLrxPug z|2){fuRizCZhbC6c}_4~tSOt#eI(Dc^?F6U9#AWtsFgyLNf*?T6}ss-QO3ks&Jjn_ zmEFXdne;o8e(UtxM!#+JJCSnyBuP0Q#Z!)tC8r!eo9o%p?o#Yax2KCr4pi>aw8R}bNPuv-7JV8^d?2V273!C?0j@6zsja`~FV z?4w7simqAKhC*9=-0q&OA@lp-u^(zL{%hyJKqq}7ci&C?)JwkFCDK>2Y5xq7#)|AL zrcx?VCWR;iEBckXrWcUJW!4`w#1#bD$EvL*^R#sh>lSBVUKXa%Eo1tZ$zeCrJbju;*pL_RD)YVPw@1^hB zTKe|&HkFk%_4<5$(Cqre9x+e8-EG284c(ztC3pv$Qu&{s#$UJ_ZI)kb$Y->Tny^{CS>;nw@%}KmYsR=+?;MQR7qk z`#aZBOv5_V-P=q)-~%Ro>Pd6Bo45n?L9}}!ecW;M;gO^dk59;W(t(7HA5%k2UQ#ySg{Gwz7AGzPnxe`0&Y-!zZ;VvqePY zvihc`dVI9!yBFXmUg#!2F}}6nQ{Rc)K;M(GFJ3+uR7)NX}E#I~0= ziS5-z^kCZyk=Gf5HeRAf)b^6+p~Jb=)ovR3)ChVYRu zghx_F@@Tb;HOoR zePh$Lu4;dsY0*8ztVAqz|z#?L+fq%b|BXY&rDChJFmI3%1-C@lkZ2 z9*eW(}FZPV0Pt?>ouFQtLn?06HTh1i{ZMP?-t+I~S zVCTh%g;)k&wV6+ehViAB$MlOoTD7r>yY+cy8%4i(8&8R1>Q!5P3TS^bi!7>zby z-8|8PCJK@3i`_a}f^NPl%0mA?x6*$r#z4Nau|mdMR5UvCwNHijK^sS~h4|L4x&P?v zjv9ATs{Io_cC}LE1r+mM8FTUX=6gdgM_nWA(pbmXpQG!&Dn>6aCJD@Xc{KLGp^o9b znHH7m81w+28ofGgTv)xPUy!>}#cG+Wyk7bf+@F3$gk%_FvC$a9ZA#G?;`{4IE;(|G zo)g)Hpp5&%BO_t@kPJjThNKDh@Y_wAKo?J>32V>b1<-^?@igIM@igIMph=Co>(y)E zv2-y@&7uxjjHN=bGKCQATvsE%^{+E+qLCW?t*!m|XwQci2ff}w6{+#9BP&P#QG{wd z`(;wTMX1K~G#kzM(90n{$7uUVvzl!SK@*egE$WhcA&_I7R zMXbmM;xuTA?8V|^kdGJFxyi!KLXA}yVLRk&7RO_Gl%|+f5#8qt9@`$FR^d``4M&s7usHx4c4^@t^UKx>Oe>F!~ z@NbC{0}qsbRu}yp)^}XQg>E$hk5`jaXAM27Pj=8Twwh%$Mw_|^bvb&}sE6hRxmw6D zl7BYrGYWq3*Btg8ap@MWT1yxX`PHRlkrvja$ zV3#R4VyE;1NTxn^;wR1ZC)Pz?qCC&a`*Lc>OG`_1OF=>Fd|R+pzbSE+wJ)x-=_Ls> z{5#`vtuCPTA882gf4)A)qU$Ajc8Aqgkeb@stp7HC{v)>?oGlP`127x#0NY)_Y~TTa zOklgKCdTfnA-Y8EE_sHrEIEo|S#FXsY>T;RW)Kg6ZocvuEECvPJh!l|*vf(phPnYf zGmP3?1m8+ZWGpi+v|I0u^sh#2Okzecn@5drQSDz%H}2Q(OTZ(ZJaYKRwYufsOw=Lr zhQB*$BTB(P37SQ1Eo9ZfDrZ}(KB=uGk49}R@LAN>lII!clA|cjMNyUJbE}D-SSRoh z$YY4%hgS4ov9T^BflM3gA5I$;WMlP4zPQ>qX;M>pC$-NRPnbs5qIOGY7W*Cf%eUcs z+dm!Ie`H?!*>ghs85xPZURYSER0n^DDTmm;x|660T>vsDao=OvA@@BV#qWE3EPmhP zW7zlHwD0kVttvTMt5p?CtF>5F(;TTOBQ}R?^skvTyC*qF*4GydijS^!?f}_#barm< zcf0$yKXv59k$3BZ=RbczkZh@UbhMW~#G^BW+puhxIy}}jG;7%FA>zEKh82p#ZRCh? z8##*NHqB%cFqYFyd{iHOc4hYlaQM*9yX0-h0=PJ4SYedIkvVdx`_>9i!lbmXyQm`1;bRxlMb?D#B%$~#V?8E~l_v66LVId~_UuU5r@nAx+mSu7nh5j| z$*X>fhZ>-MFdIe9IoST#C)(n;wJk2HMvjt2)yQ))suPtc=7lfK`p4Pj#zNw@Dvl^vUaiRf4u$sW+-?0c+zYBEF+W zjilwqIuxS%I7SRO9P3b^A?j!#<43jIDX=EcP@*U$@kX2=r{UCBESXURsNBj2Rp#GcP`y(g*`HT8>f9~Ej=JIaF z4&J-;p1|@;z8rm1 zBG_V?m^K27i`rA?Ot9s$1=xPuOuQwk!w#lAPL%)ugBXC?5?cVZ|LfQRV-HOC|0;^0 zL1ri<;q+?X9~1mx>GPwK0uSYCd4q#LGtMk&&IRr7LR)|)Yzdj)nr-7Y!+!9f_Uj*Y z_V;(vCvyATWUiiifP|}_vWxI||wC-&}R^+DGl*ccd>c{g49Spd?ms=f! zO~v&%uu~ytA&LM{8xE>{THv!;kQ$IEA$L`e><+ih4mD&PU0FGjQ9nEz3hy4NK2zXs zs;Fpm7ZkY3v)AMU_&CQyHF!#*hrf?Pfdx_3GOUhot*n7nLxM|%WdkVQ0@S>#9 zJ64G|f{&(5jmqd>&v7mp>R1NdgPey#+AC0t+ojH+>k<%mRE?Dpk*KcCZ(T!`82L>* zOu1G{qHeXn&eF4TBBNnoV<0p?R0F%PX=b1y^Lh$+Y}2=`7_HJ>_q$&;jdk&zzy&|6tj_Rt=HTA>b#Cku+GJCR9S5i{e&O5{uWI%CA9eZk0C zDkc*dd5(QA{BUl!TBt4S8a@;G!I7J6#}@VB=u)NkStcC=bZ`i54e0Iv##%*Wsa(0z zLlcXPVzUc;$ zF!ZbVDhrYKsH_#?GAyaMF^Hhu$DKN!`L zRTrAoGk`C`yTLJe9IXZIfTd=93@P>r)ClL@*?=1Y4K8AK-^ctETFaIRy$%pf`%UhI;SrTvgn zhmx+FTj#ZY<5;9)|MN`==|cz135(qNf4)SSL#eb+9ujM*jC2}EVnk49)7yi?5q~7L zg-o(2U1G*yE9asTy@I5P?UDuWG6N0I4Mu0GLZ80Je46qb&>bVU5f(wDM4g$^Fv1ZvyEdx2c?Qc z-YQ(`$H-%@w}nSX!}I|y4w|%Jy@@kKpe+LNhStCcw$v7R6t6Y#v3RWkGDY5t>~$~k zkC&d^EV z(!6$a=g?3meIoy`b=*pgNtl23h}akhVOX0fTkA9CiVxG9Ca(B!+=}PX>J`t&A&arD zc?5a|)d-oHY?UD*Y=G!FK# zU7STtXVa(4`aHIZ>}3`#iP|T#m6yI6-0X;!3%_W;}PUB=niis?{e@=CQ@5k zgEDd{Ej>0AjA-3ilo0!261TrGD{k>0=-NG6dsl9@mQ|`}+gj`|h2FAIT5h#whw_}Y zWo5O_Jo&8|9XkfS7E9Ce zbMsyLLS@ivw|j$?<~R7?l5*hXU6zwVe?ykf9mM^R7|{G7G5Q4^rNrP-yu{#Ri4vn; z-3#PS_R8)jZVnSSV{PHL)FU7@IQs`ugR_4wU`ePpZ0bi$4p6$cIL(JnG@K7aRFCFA zk{~$=K@vdRKd?4akVFn_9J{0BG71c{zbQY*Ufg0^c8oS;W@;HZWwt$4TY`Bm8tjxA z0)P5t{YZ<$+mAezes6hTsP+@*A09e0>h-mD91JeEdwp%8o6!~CT6mLZ(3z2{QCHs^ zYsZ|KY1!Ex{j$!nu}=Dc_Sm~Nn0jC{c@oFP-UaHThY+aGJ%l9nc@$55K9)#*x4IWr zE~v{j6+m6iu1KG<1#q_D!R-L4E^$PMY2f|vds z|3h@IP!xn5j-3Try9|~d^e<#~OWFg2;{6o7&RPek&DP%qsqORBdZ?@mEWr5k1s9SP zD}gz`@ocJA(l|H1RmW@H}Gt=&hAH|rlTH4k3*2S`s_ zuWaTX#kJ59z_pxXF1eOR@m$Nt61f)C<1;c+gzW{6^^{T=c8Ihrob^h+nl#!Miq<&|JmSq`$h*!?PV&A7m@2L@m zODPM&A@;RW;+s^#OI~%%OUE+BF;uML>rkN(m<1s{QP(fKTcGNry;Wjxr~dKlCewV~ zGc7VvdGSiyl;%GXIhRvPiC2_xB@(cFrIdJe{_T2d8#%da$2r~Vs@?yQAzD>E;p3Q2 zpZSeFW22dKRYLCzk1%4n5#0{&C}t~a?>J3QCy+1Tgjw|ds1le%b`ASL<87ZpbsQdI z()i7*qR}2MbqrDwD~v6nL@#;N{t=ETv*Z?0DK=hfBcOn-m)QnRp6t)PY*wUP-7J!= zR!&Aogw%#t8L>I&o1#$`1k(j;q*#p*|HEqp zojUo7bh@XOI7(uvvhq`VXrz$F(r`F)I6}p$_UDk-wSM zP4({Hfq`E70E3Rwiq~bQ*zK?~5d)>sswo$%k!dAIv9yxMKr5`|L|T!5-FyZ-@a)}$ zcS0V8cOtq*`LAJ(f@Zu%K{Mt#MEM~`d&K4#qPOJoc|J)Go7xk^!jVxU{<CpdC)po`oVw8GLNGiP5ndev56qPmFfs|_)2#9*6r@?UGzM# zvhpF%QeW@xb-pt;SD?xjaM|eFRYl+0wK-Q_l}p7=_fOW>`L3r>rW>m3>nHbzDILDN zoYLXFefaM41{)q}5PFETi?BD;(Z34uws>pkXNmr3*21JeTIyuLva?Oy3y}+jYQ%b( zJSX)s);74ZbCf1Fq6x>@fI6|+NlCS{SdOt$FH8{V0Nf;>g1uL7PjpoVqDPi*)ZC@KpQONB(rY+V2_IY1~0-n*O$diHQMx3Oso$UZRgRSDG3DH7%i)CQ(znIs>o0Lye*ol9(4_ASC96 zDy$w_jo6ETtTHbFS!KE*zN=Mm8a(|mwq$}L65{%IjAX^SM@&8=Yw{DG#ZFmSwsX<_ z$(7sQuhrdVJn{jp?$)z1CRtm`xZ#G3KOXZ|yZh(6y5{>m)!xa-;Y*GC|4bkKoqglu zefW6Xw}F(jAILa~658uf;YjitblyZ>lR7VBA3VZJY$NXC5%x)5ZQwXQ#u~32NsX6z z4LU9(h2T0yqQGmhm}?BL)uNK7SyCV|7|vw4J-*>xo#93IM^{!p=3WSQ?i%)q2#S^L z4DHL2d-_|0{ry48YPuvf^}6dav_FJ*udA-B-W<8@o7J^i_3&ckk;U(PJUdG-n^?bo zVsdI~((WyIeGSt};?&T6+X&tJsJSj*4Xv;)nJ#i&CZ`hOOyrdp(|vj6vfc(7LWWVa z68&P|5vYlsLHe6xs441_f|}&KNCse=yeGi9wjJ)zt*m_2y`|;i7`C=CsTw6BdHZ*$BcTLW7l^SwFAD*)!rIt?ZeX=R8K{G zJ-9l)eiz$16Lj?ioyY7$Yam{r6tE|X6cF=vn~@TzW1nbk_o zdF@Uzuid6S&9a3@a$b2P=aom0Dz!v)9@WwlWj0$k&2~9a8a^ES<_gd}15&g1s5?FM z9G@B?_o9~Ogk=))nK>c^z0Fyox6qT}r|nSpAPWXF&K_E^L`9#m-iOv#B8Old1vNehFIN(?X)7X)La^E&7X1aY?qKl=Ysp;6~jRYeB?pt zCfB}2VEkt@PTpWi{ms=?9vKnk^Nf>!0EVv$U5vcp?DaOi-RHhFkGeTR*O7QUd{Rwf z*ZGJ^KiIyYA6ui6ems)&<54pD@fpysOg$sk_H9;2p+Up;W!kd04z%Sx2i7jzAfPDk zInZ@@&k<<-DqTlez!#!w2@&;CH`mvK0@*(A{!9#9uM|gu>usONyqR>z+-+4}Z~t5< zG}rI-xyK@Z5@zs%c1zdTSQmXFuSa}ukI!|po9VjuWyb7F$nu;f)N&!^Tc&ivdQRMR zI3rE&Iy{oniAPd8@d(n%MG}HXuzj1<2r-h#4kSMVNhkJDNW`|X%c%3R?0AOH;+(-S4LFIW69PFUyb!rs_tbEhrA0K1f&miSM+O=-VLk< zL{6FLN8)N&?cE^cnYcOY9uIL^w z*$4-y_6zX+5_*qK6e|Mn2JF%Qsg;6#oL36=ao(eOPn{671jlofFgTw192_58`z2xb zlwlOyREV78iT&#p!rz{Z(86r(T6BM6W#u2;gwqq=-?N5Np9>wKPzOHRoYi{EjcIyn zXl}q)@7rjkThrSB$;nQ93cdL!D`+n`U}F97g}`?= zB{&>2;ipfc%wnGtWEMOhJc9L=OA-Y=f1xq+Q7OB4R7fj=_ejv4xfxz1_SInrg|CkF zn{n|AbFp4fDV9wHO2W5774Jyk1OHV_da323OSy;b5c`yRB7?kb#FfZ!&YdNS!GX(nH<_=rxIt-7b z4#T5lGMUdvnam?eRqUR!zFsA9JUAbAphU2N?8x zPDc~{V|)hmu2k2-m+BBaDdje($?^l#g#17i5c%95x*q(>`FQN9hDU9bXpOoipfzhZ zpf%gZNwrAXV#P(7A>3mnR<0yw?8Z?3OI2HglG#IZRi9fi((SLI?A@&Fs_^DuD?wM= z6t{m(X6-gp=5F(AiT7_#)A|O;r$M#Ys0N$URoN3st8wnzXY&-*4g{Gehr~|eW0T%)AS;Q{2y9-uv{sZ%@7(6R z>ALGqJGX=on_y{55|f|}WN+SNwQ7&_QuWum>MPH`UAw|lL-7gPH6k$K>j{AgzSgEs z+XF&g%qSe*BcyOx;C;Z`7-jaF9yFj-9i&UM2d#tNGgWX~x;h3t1@W(prvQ_dS3{;3 z(3vRiEYHMxD7lUzKOepUU{)-Pfw-_NMwJvZHd!PqBq(?>{>nsnS&~$L;KbF=nE>E< z0QR9-=OK!F|C>nPeX8I@ZZDMU5J<|Qa(x;340zS5)ODzi;uNbLHaJJWBNi4`B>Xq>F6e!Do{S@c z3<-$)AVWgpmxX?@P- z7+pEqw+c@fRtfEERp~w5Rsyp^J3FbTPbfrHYu(Py^T(I&Yg&HMn?v}1qxQY0+xz<3 z+k1Q4y%pC~Vy&ks?AlIiowEzNMePLmD$tiqqurk)guu-fHDc<^bCA*SMM|`yNL^QC zQjTjpp&x_12mXOdH3C<|R_8fz&@Z;+L1{*?L1~uTpfu}!&@N(lJBHE}Jz;_CIC&g^ zG#SC!J$qz0z`@>2pW3Z&JdtC3-u6!l$Zkwc9q3CV(rTCYN!Q5e5QPL7#s?@O;6*+C z{4dU2XVW`OfUp-^oC~y-HECtMPABcnPY`D(j|{NTyR+8=v`tqd$cSi60Cxf5>k?%| znYt&|Q}W-768LNisLkGDND@SeUjPSxrN{yHNR<%Huc@30P#tROKDDu>byMZBcb_)$ zsY1~B=@UjugWunP50zVeEcZ}Ge=kU1zED{u1CndpLy;GZvrAgVF8!EMsQuwzWxf2n zW+!s>{%Y^7Q0qvpY$UtzGSV@MX$OKmvR)t}@Y*zYn6u>woDIE9a<*OF zl_+CM)EP)Ery3zM1(5~(w-8wXp6*f7gRK=%nf{?(sT{-8P??oEUh2}QH4d4H zXwpXE_leO4Q898uc)n#**zFE)Y6)#|9y8wGwR^1YuAB&m9Q@ibx_MV~X{j|WTYvqD z$X~gxb$yf8ls(j!PP8wc?DPx}SV!Pzjc@e)7wzG7)Q~H7_?G zkq1B1-T&UVetjQ4O||#XOz=FsPRzqPiU8l5vQtE5jSwY3jS-@5G@@@LrCrR)>c};D zhW%P{1lzEH?0&urmF4|vL^%Gmu~} zin(|druzlvWTQD1m!3FrlIP}DpG${IoL)?ZA0d0qmc-zN&)2O#G%#>zeVwy&CaCQ{|B!aLm88X) zVt+?fRfoS=err!t;enbODo4<|b*M4(=1VW7G}hs5t?tg+l9Jj^HxaeCxVDpIfrZ}d z0KM0F`gbB`;fVQW&<1kp-^zGAybk$llux>WO}ryl6yOXTxsN&2bx{O9m)AjrA^{s~+9m+p}l1`p~>~kY4!U&V$;6MyY<;it)^7clRhhdPnnAsIoFN z)x7b5ZG3ro+;+eiI%<4J|8`R_*d!uS@Sex$JzpZPIU)~UW47LkNKD9c!HZI+A8(2$a708 zHtiS2&{%i(7(RMaa2iG5r-NIT^A?tuccptnqmkvskKJw4w+GwXgDohfCFXZ8y|)27 zj-)-J1Q6j0eLRJtfmuUNp&8X_R-h@$W02yh#KWk*qmv|(8e^rpg5x~p^%uvwA-mav zL9Z29>ST!vCf8)@dNFyCianN#;M$fG;P|mTd`W&D;JLn8Nxu7lUA)qbL%nQ&K0}Vf}WMZ-J0$*btHj+x-NfcTlB-*K&<_JX^Q> zhZWfti=OlUc>4~(MyhLV&&ZPHCR>)=!tZNr?sS{IAhe+TWc%N&PhL0ASwlt-VV&XT9YHmWRbEL7Mt_((lcfp(PNu^{<1dL zmG+Q5!zx*`7wY<*s6k&Xe@>8>g=lMw#^XYyX^j)!rX;(Dw{8t@-6`KH5R+T4~)5`WJRAOPR*Lh^U)FYrE++N)VFpTNl3( z$m$u*5F4Z3U2922tg##_NnH7n+zqRp#j>Tgd7&%VByG)!N+0gd-M(SNwoAlLkZ%9O zA3jr6SXfo=OfRfTu`gb4*!@D8%_2K(4VgBFIXw_;sx02Pv7};T%^LaR+9pt3TmI%M zFLxD}$z?>QDjgr9Jt5@2kXmU8=N?CQ~|5r)(9%pwysz%ywe`knO;FAr-DWkT;}6 zcl}uTy8K;DB8;6mH)TtL1IK9~3mS0XD2*IFN+TW)EFZ2!7rY|g+7Ke>@T?J+0T{70 z2QXs!NW^6<1DT8!VlYxc=j74YNwOeJDK8}e=+*r#i2!OjqI`5(k~T|U6%d*q>&jK- z$4PCUAVMA2 zM37A=?{Qx^R8?1A`L66>QMo<)rq0dzCTDrMe1ooc;JlpBcrW}pt8_YpF9+u(`(_f) zOX06cO=o}^uYhe3aAE5o;KJ6wI{L+S6nK4yR)AGff_I`K2A9oc;1sqh^K^$|3Jh(3zY2qzW)Tdg$e(nno1>eWZR8kQ1IEV5#y z)PM9uaN4+<1uHHQyq@lfXN!!MM3v~4lJ?3EyK*fSSBdgw^S)i1s*3YuQ?|3?qWMjB z>y}toN6#?wFX3%ZvNjmv zoyjlNcT24yiTWy1HzzpHj3ei;XOKHa?p_<5qTcngoKsY{V`j$xWz#oH*X@??zv`+* zWgjJgcj63;J@VfS@<%Ux6uBDjGST9VVI!E_etDl z(UGF)wY<5wL^iq0x9vONf5P;XYt0lz*hC@}aWlOpIC-YxlXopHs?9ln*%DG?JzAt8 zQ<1$cJ2Tgse#Thd>_l*N#N~>t4o>XO8<8`V-_I-GlE1LH@fvvKu>%EUJ^B?? zse{A=PnlQ^PZ=_?*;9tdb8!V)qo1J4-ZEH?;9XC>XXC()g88&#qp2IkTuMO)EiDvO zIkh%8S)T~+iJkJ@0B=$3Z?ng2(uvp!0cP13WJ_9bVt@XWoI&+V?4ImQTbB8Znf!f~ z3(9}WcaVeU^Z#a(w>CC6H~N~J!J~&M_U2Ccj|Arkalut;L?-qzWcxJQTU^y1Q6lh? z^GNJt9vS<%PhZhTP+Wc=H|Xo2GX(UJQOUA_Ajv1An|{Ia0)K<}_dz9GksLd{;{<)^ zFUC$6Rcf%)M^sFlVy7>0T%N|BAD<+*O(a5fWTwW0laeW>%m@#rP5MrOy8B;m@%vj_ z{r(o|Ok?*C+P05Sm4p&1Vc9sc-PSK>#Qrw@KF{8t7u)2s7QQF_?GtW~$4wuC^)Tfs z-zon=<1g^^pb{}K1DF9b4ch6+nBkGY437-VRO#!{LxQ8EpjR6dK)Kx76T!j2RrndF z<|>HY=lu_?F8ku*h^7(q~a^A5rzlwiHiaAKFOPtLeS`OM58C#26WyetvQP=&P@fo!QewohQMswrl6Ek35Q7(_YlD zGOS@`H~}j>5?JApffY~%&n-t4zz460KNrLt&IQ0(oC|(^HBKo+2=Tp;H{0}48;#oa zQ9C^Y)UuYaf~Sc(TBqP!?b-<jO!cN;b=jpW-?A4z3vb_p?T*P7rCWzWFoQ7C_J&GvxRT9iNKo$=estX4_BN5#4!rL8gKg}%Jq@lsm1Y*BUx&l~pEIqM4c zdUiy;b@lb9iMs$8W@a^RyAgyXk~k0J(j4aJY+ z97A>ms3MK#xDP2y7-Ga&7NdA9i@A6#_Yp2cCR+TN)}TKfXJ&^!0uScXse$h7A&mCm z?;+ZQzD;|Bej!?cF}q&J?AFu5Y?59s&=;?s#G4$GXfqj=fACOlEoIbtz5MNw6d+Ey zYOtwk5TB3e)VbEcU}qu*+X#bS3XV3Flr)V7gR9_ITP2S!{9X>lihYfZKKe+CIQ&d$ zYqVI&Y|{9+qaZwqkiM7ea+0dANilJ2vr556d~goI8nF%q`Zf6BqxuMbHdN0>-Dq() zPD0p(19UHZ1c(w2(r;8_KzBU&&k$Fl75FE)+SFDAkL0rIO#=8o6*+Pwa@kN}X}-O9 zXzfPN&8GLehBvDH4mNaDZ5*!Z{jI+qF2{Pm{43>z)Ir4ro>N*)hhlfhu7W(5*^+5Z zpZ}=ioNc0g^0spvACXMbd2RjuZPYlKHaWe^2GSQNNnb>lM&YXjL|f?nJ4xQ-SPxWt z7J9XqOV+CmeWqBy4_q@*qZW4~UIe;}@OU-q_cYQKSesa91cZgo2)l~Nxs2-T4Ie1< z9QIWvc*j-UJQ48TxDG3y&s$gL#Yb-SjYi7LBcr~N-S%;r5+YS3m@_S=L+k9j|NP=Bu@kTVQf`P1 z&nw@NzgH6u*VJ-d3*cbEbeMEX;GmN{DezJP2VueiA_>CkZbc+PxjtGM`g{khp*8v) z$ZoCEN2%b?cg4dWwkq-OV_(N(pjE#DpGufu4+|<~pF#_LJ$5wHQSPAs&lKNs zqi=OvRaM(+-{_%&or!3gb{>?{|L~XCeyK}2A;16R71N)+*(PtXSG)4_Np7&$;2ZGV zKswMQogL(1CYnJ;^Y;j2sAi7yA)RDk<}ct*A=R(H1S#D<{bS{8 z@^^hBVV5gB;v1RH8%jjfsC^gc>D8BCl3gc%b;eGce4xhfuc`I>1y7qYP07Dg>1hLH zK>kRhr!|CwErhi-Dm`sU;AuR!GF9=KR6LEZq@pRlvXrKHKAEOq!Qm^Q{dRrSPNN=u z1gQWxgKU?|rjwG_+1+uylJxcO@vp_NEZ$dk>+SM$?T`K*7VF}PgT4e5&wHd zwEk>~K(|{x=%$50_nMB=t~i`-O2p|_`!2^GoS2W+>8d;n`Rk5;xe^O|I9Go%B)BJB8_X~6a#z=<$JyBF9&Od?x%z=^oV zov|myX^~*e=SWNkK`_2j+xvuuI6V>B3;1bP{O_7xw2n{7LB%WYSzII#J|`3kxmh>W z@39Ta7K@?%kL2xER+Hggnn^I*t1w(Jtyk^#b*f+FE`lNG{Qsq2#7(+7!xK?n(9Ai@ zkZsF+1?M&_l}#%B!_EQ?@RU}`;$^M$@;eh@IKe9T_CEKnHIco4I(Ez+`xAtt=VD)K z4Taj;LZMd4V`ylzd3)A{*b@?3yC;8Iw)~fFpP%%H!+zCB0-1HMX@h2;kGBH4E}xZ!`IZ7o@oZ1M5i zSvt$uzfHCsYsiCLQbNA$iOJl6Y#~eh^`3pdEVW5t>2II+Ha2?eNX%gw)Zhu|#EM$w zI0FG8a0RxL3$DPUmAL}1N#+XhH}MtN6_I(AiXRwz7*-0FJi#N_?hYQo*(|5v5e_wv z2wZllr9F;QG{{M(58r^wFNV^d)HsHh;0r$o+s%asibrf864&DGLt<{Z9iH044$l=o8J;VyTZ3IK zG-B*(;YG!+=2#8EMTpyAhDbxjJ!$MSeef#7oZv7b@@_Si8!A5xlKzFXbF0 z&<1jlPK}WydnqsxFZsm_)~CQqY>8<7*JH<&YlUF_sNh%9Y6C5UiD>B~w0t#5uKw>h zGpQ`;SV3OO?MlBZ>rrZQ+$ zqK^=V8_`F|Dd$)k)Suvpm!K1 zaq_{(>b(sjAF09PQI3l2Bk_HGPt$YZ*)z}lO3h4{$Vcj&sd*$R3rTq`|JwKEseDA_ zA|dCtj;L7l^Ws>{?4(#svaS$3pe>Y8MHCTn$=zGIZWGTTB7orliwRq80`%@|mx1*~ zc;7hFg-=X1x-i;WXGFDR6sBl?TFekZ9M;pdA}rPW?O0NZ(xt5pkNBRRyEW7&f>H;< zHz|LaSH7nwDg8cce03&)f%vJ&RVt*2NI&h0D`;1sb^tQS(&$||>s!POQVbx$0o5H) zBayEm0vGw(cyH_pF^@gL-MRn^&WOi85O#56PcSUlLbVhYq%#mO==@j9*T<7uF;!m1 z9sxvN>8Kyw)6uzmw7$aiGBS149Hzdpj*c;WE_ZtEH`m@XcSq}%@Y>e$^47Is->~aL z%HHWuTxXMagrm`LQ#5+gls+?qhFyRQ=Q247i(#_3KraAXkjW0X6l&)TN2411!=+zC z<~Hhk@k*orE%K^aA4M)NAOvr#Sl32SWBLKqIHshHpw>)qM{GKN3qQF`zguX&g(J$B z?jQ(Fsq1#e?WI=&BFV}3!(~&P-qlchi|4QVFAA&*jKD23Lg9OtDCX(o4SRm>vdN2D z#_*3VJv|nJ4{~fc<{R{dXy=x+t277#E`XqG83>l@*GdT%6)K+=FysBjcVd4rg#l6= z(TqK{l;^Cxzi4|&s!@|W=f&H*7)mw?8|>Le)N$^jQm}y+)Hv{?6#QL3)ZRXX&qe-* zk2)HjpSy}2R^!n!>bo0U6?w1Hxa%j%*X9tbG4F3`@{^wQmUW;%-9!LLfKes={b924 z->JcfbLK>CSA+Tl7b+qcaXuZSa;{y&e28bkhX6U)3dPEHnyXcz33%}y!>Px-znvf_ z_85NizGBF+ezcS_336(TI7l-gRFq{y2a_j*@B4nivHag(CQ$tD;zsAkosBQJBw-+)3}!Lw4$qXi(&u zZrNHDx1~@lB-n7xHc&MxVDX6K!^Mc>!^NnYRu1bchY6-ETLY%-qeU)t?+N-4X7F2h z>p`t7|D}XvoTMkCc5BLDa*g9H1!+v~*fZ96eXeB7$&oB(TccC?d+Ys)QRSC1d{69u zUwBL$4P)W=DHqsV`-iKl>ME))u@n>*XP4P?KGeD0neM14mp`C|m;XLJeRP!J4cbPW z`AN#)Y@oMaO|b`}A~doGLED~XXdB#-uYn7!*GKCKj_lV199c_*uaqGQ>SuXvJ;89C zU^`B*#qSCFJwd+#+qLw2ZE8+vxGUHw8c*ZNE%P+FW63EySvNA<(J?zxC%%u00CdSg ztqMznwGKyZu+$Z(bzFiI_{F&o1ba!Xp+NN2!GX|q%2Q1v!J?wzNE5LL`W}_f@P|Tv z`o!)msw}Wt3o47WZ)tDV$gp}oLuQ*JSiePbSQ*(tM`>s0()&UdODAnULxpoXK~GjG z+d?ov6_#TC8hqJYnG;$!YSxku$4;k0VZ0ZI!O|WVku1Gmxx=(kxkLF({n-BAUaHR{ zzK^Zx>sy1*ty10myz)c&-+A@v59TH2x!aRqnx=t}fD*7S#rx)WkC|zh!Q2 zi}H;8{h7muX9RB#G&ND~Q&XJ$gla3O26qmkg1ibo=OA0N90j`xEQ9f09&KxD=Y4TXiAhiSM(TIR?$Nq$EAJ;P zfBX+ZU`mnn9bN}{X`NF2skymNJv9C39dTLTz%R>5#Uwqpr@fcn9==HE-{|v{rsB7N z-Z!28T2zS;b9S1`P+@=yOICt|mF~eV;d^rFdbWB!kFG&aNuzfL)DY<`R@KugwveLx zE8FVLcyow7Q4JJyIHB=TG82g3?Ix#|+x<3ghqu%W@7ULbWF)>9MH0hZ)9-88)46|t z=g-S+@|A&6!~>27NH(HSm63qv&EWmdIp1D7-AC1EWmw6fWq1ilv@AX#D=Xp0W(|_{xngem5V0?#eOi=@b9^<_&o1>?>%`c42|u|kutlLTPJ`1=_(*8 zOV9Pb*+1RAES6&1KYfqL|7IN`mpFVq>89@@?t)rYuwCa+oJ6k5U2*_Hf{%%2t@^B$ z;A2r?nnl;L=vsw-4SOFMY|K@0F5=ukhb&=BMNKP2@rRp>34}T$iHmz+ZmS8pap&gA z8I6U!8T-Ca7(7F>U1<9veIj0ExP8};*UinXqfF87i(@6Y8mhzU*i)1-s%s38aSeSc zlg>VL;fSg-7i0mPl@f7Iw$ey6lR<9`386`!g47{g3{&r$L>9hLSd+vCsON16XVCXQdp ztK4n-qVnZZ6m3aO}_C$>kBDhrkoX_FxdBJNw!j}HM6l;d82G>%XCw5 zSw`O50-SPNJPdDHKR37jk2!Ubp4!54SNW7RP+sQDdQYjprX)j4E{&6OCRCZ9YrCvc zX%RV%h=J*z2(VTk+{kPqRbM+ZO1hp?eRK6I*ZgM5f=FCG;UOiI-K2+z8Z z5fS6Z*CAUX-i$|yGNP02@X{`ZH_E54@zE1m|cDr^z)tfD8K2T zuC@5c4XtaNi;J7rwzjUr_qy2PopbU#l~Gekb(J~GZdSf7wJc=Eg3)L&5RHQ8t)>{% ze)1szb~Pkj4y#oW0X=BpfL^r@J*PebWC2UQmKv5-`gNoFBqBd*33AB9ZP2g7Yl@gs zewq8=*v^8JgS`y9nnm&x;s>k(DraO5|2_E#-FYx;5B)@_@WXTt&L?18X6 z*3cg)DGBs9(06fhpkFz^is~1|D(029&=a7@2d!KHm@$ore@}|30~pG8%8cG+(;c zR8ml%m7SM)3?9(jN^dor6 zGU+sDZ7Gvrz}i8UJ_lY5oykVK5T}+{i&M*^k04dn=_AO!%qL)d;a`OWb#aPS(Qmfj zKTh(Icp~i5$V?EGa6I&zJ#dIl6svmZ*=)~&N17#8NEPtEkxfEqZCWMrWNi)gotY=C zL@uUHvDas$SCv{S(@{%B%wnU0Zp1g!&vQYuYzN^CR5Rgh-K;z(2PWqpQo_eRVzDK#IXqWV$@|2}ckj}f$-Akl%Uj_e%dZVk!?hT$r728yvg&H`h zBLLq4aF$L|2*>rpy9Ns+k06b~I>sYtBd|yE$cRnE87cfrhPD6<8JtVp#hgowk~tUa zG9pF*F~5u(@GaKzfE#cymR-geORAxKdE6}FWhB%j2mcPt$}_PY0w3a=@$zg6j`mLF zQ?@CAo7<(YKq z_+d{dBx&LAjF+Ux_1SUS#Vkpe>T}TMEAB(HE;=(TB|gPZ7PPzylGf4V$Q_jUF$ZFLM^HdvCxnS+I5)#dC5FNP7YVUqjfqg`L~Gv!hHV;`p|Pm^*cvt zG^UTn2;!`%LoyTAXW(-k-MNm|BFdQm%`G&V)km{*=d_BKNm@Bc*LLdHcG6!rO3&Cy zSMVD+JfyA#HJ(YoQrP)~mLT%+w31<{MoUF#GA!=67;b}kE+Nnrg^hGqq@nb|oh%+B1c&Typ3VRKonCi!7VC8?;_z`wk@q0e7j?C)!!@1i1q zU+k*9`be+GRaRcHr(&$lRYol~-en6poaTZv{hju7sy~)@W=TU;p~ak$o8y)w5?`KA z*dtfJ7klK93a__uu^U)DW0ae}S&|(=R$7lWb^9TJ!4X;}R5`lJuYiWqdF>2IT=k)8c!1+P<=&vaz_h zv9dsXKOoq2MsU#QbovH^!69E^p>Ie&l7xHZ($J*zE#;GO1pmHcD#zYmSe9?G8Nw`8Nx0!e4L<}q>Zz`9bSS0eFO`1jtWs&*4QQo zn}(<<4XvD_lTIK)iS>Pc3iSO-{VA~3l@La1)F&CIF4^hmZq~ZE>q0#}2~m-#V$8BD zw0?LB4Xq!w+$1##u+@zs#X=KM)vcw1=-zki-+#_I`}e;?>bdQ*%WjjteB@7sB>orJ z%U0FDH~%Kn9phJi&FAs>@R93g&OUo)=B%@nFHnZ_?KjFVtL+p9DaWdy%$$*(u6$YQ zTu6_FBav_zbu}y$x6Ao{4%)Tor~s*7m%?Jw2%JOpi$zzP zt{A=keou9^+g)Alkw-oKO=V?G)X$|aR8|)1i~V+9dEIm@_Nm$#={a-kUU`>thg@WL zXPPrj*B{@V{$+Q4y_-HNUlX~2uxr871pJ_ufbcaTvX^xxSV!&p2tELZK5}T-VqPcq zd#QdMToPCkm16(z^fd=PiMiqO7=rb6d5sw~LKx98V`yz!-0Ct~+xZlL5ekttb#8iQ zPHsPP)m4)3$n{$GpK=kSXrOMfbkTHV^!f*M6!p~)HMv|(L-iZ>?)`ggPk2Ulm}8sd z&yd=7?Kw8-R)L;dZrGjvyxZ@0yVdePD*fy=&Fgww6P+0A(*92P`QO&uyt+Q+CCt|A zBXAop!IJ%h;7uYU!%M%#`Gk3v`B4=}XlBSMYt={bS(}Wvt`pRQke=T`cZ=+E#0ZL< zCg^i4b3$jpX?ALTE*`5ZYv88&*iUApUn!;3X@J7re;vy&Zy65+R=1Rwx2z5X##_qe z$SFwguIUS_rk~BX$shD|!z9w}@pSu2N_^c<#$L;xlpZ$6ekj)|4-4#GeBSQ#hsr&k z@-he&8CqVa(CI*X(CS_%?4FKRhe$cr{82oC z`J))c^GA-yKNao$-)Vg-V~|yb1W{vTRz5dYDJYZt9H9_}O3Cf1ktcOXY7lmGt#%svB%^w>e^N>@y=A5UzNTBmX#WPR72}I{t@)Szo01yIRUnmh7-ukfW#j!c?$gw zl4q0tJe+erdJ;#+;BIlsA?i)oUVQXhL_b3VWDOp2BvYu6Hxqp}iCW=5i&^=(qp`P0 zF`SEi>~u*}3M;qf9?`L@e0%1_Zs~0etwf#vk`jOSmt)VC%t()#W6#JDS(tZ+Tf=9n&c1emaOJHjzD$CI6ohjh6=7pT<`X{) z@h9vR1zqtjfzHleQ6r~G_*LLjVg1Z-s>DY$FIM;NXlvVn;*R+4twxgQGo-(fnZI?u z?br`YzgTy-@|)JCrdE99s?fTQs;UmINsc|7wl6-xA zK3{JyU^Gs0eizwK5U+!3DTtMXKb+&eE0W^9;ZYZJ!lMp9s+fZxHD4d0TNwPDs9*s5 zlMyYBh#ig=M_y$>AHmL5LFa zFDPY`@()cvUH7SVR8iAh7d)#|x^6M{LQM~<;lZNM-|}Y`X||aS_s!n<^AF`%WfzsW zCj0!w%JcF|jVu&4HV%bKOG87{i@W1<)uCWjZ74+h4mE=oOcSb2s#vx84(mC0OEo9> zOIV*l%~)^|u@5WsE5HZzOhk#p!z}I)o+-Xxc&2!iY~N+i6kj`i&s2PgN3m0v@l0J) z%iyEPKNXC%@`H=y7U3Mym)VYMZ|)wfAp`q=tDdQ^5{M&_V6YiAQJTxjnn!)U5vWlk zO22$BJR_Icq#HDgKxSr!>5_M!LFS$3YNFAa+DHWYKi7X;OLDe{e5pMYd-??JUmw8> z-jOP@2e3Z`UOkRDLu572A;JMZ67HF8M4XB1BH|1@T+E?1M!^a8a>LrdPeK+GBr=Y> zW-klQckp|$2K*jpv9S4o_jBGq&Ty`2r~5o8QcCswwYLf9#u%dtSCi9@<+hzmuGAg@p(MG0C?6}I3ZJTG_%kCJ%^a#2`DLUcRZ$H7;?O*qB}_B+y0 z)W{w-w8S%(RD5M=(y7!vJHgClJ#{G2m`iMv;3?u8yk(Ib7<&YJxqbSlI}c@Mno60! z%u+?iXZ>8!#P8?uLFGx2dOFwO_t*Kgf}=xvV()B? zjsqc=8Zzh-{_duP0-e9Bma-)7uDK*0J{pV7Zcq{Nzy`tPH%dEW&r`4XHuR3a;LI~G zU=AOGV>TQPNgq@0%Y6hz8+RN+KTO8N1ySjR`ax*_gZ1n8?p0ow3m>fZ`>LpVOzbR@ zHi-+5Q=Y+oH69^MJYtlp?4d^{EHJ2_2nmC$^)h6|2+~JykEts2%x$W&lm09Y12jK?T;pKX$f zXQ|#_&0Hy=GMVO8K#x1*JH{*QO9Df#Ay0W!c+8{ZIq!_lj`^?4lQMF%Gc5T&=U-dy zo-HX#x8%sj7Z;yak=A@k|KeA1QY*g}gd%tNM^Wf!l*j_nwIi`RDNkWlZBa!{%@O1& zWR>OT-q|);XtrnBt6r7QQZAK&%AEZ4yYD=d{k%KeRO>}0E#PfJrGV!)$5sb&r1 zRD}22L>5}kNnrjYMh1Vf=_^nr+@X&Ui-;Inae^1?SHS;V`Uu|K4t<2$zlb9h))Uw+ z+3!Su58;MAt`R)#weje$X3R=|OLxDIVdR=jbWt3B*~koxhZR zLlZ0^Xp3_jl)!p9WOi82mipOXnOFah9NF=b`conuLVQcVKl-0X|C3^tPl)^oxgaSq zLiv>PG6gi!XMSE<6j>68N#?$IoFfrbGjm0jgrCks&XPbc8;Sl#(f?xk{0QPl^p+y- zb){Sh<}g8mO;BXcaNDjG^Clc5uON5goFAAr{$THNnG^n7ZmF5uH9x;gc{yeBgi^PQ zXwS$$g~o>b0pyc%tP8b|(LHsU#6x)`=#peG`n#clu08o zKRJA=+>7w><9AJ8*)To6d-wP&Wj6UL(RnX00{x8AFSzBNvUMCfgAqH;^abk>a#2BH z@Rc+Zg>fV~PFx|UTJ>3>_X>)lJV}C@*n6NZzI$mV5>|@5HuyO>Q^i7e^O-K9%LU0L z#!koYFqU@O305a(R3Od8o=+XRT1z43GslnLzU!6s2M(-Po|aFf3RGPmdCWQ82JqbEj#qoAOT73@368)p!%)sN>;gDy*Re?!saYL%QhA3rRt} zm?$+ieeB)uKIR^zz-eo*y<^ULp(E(N&BC>>J zKa%{oH%wAfqlEbL^oL9vKYit!FRS6_*-~C96;}2YDZecn-#Q&i3_tIjIdo`7tM#Ic z-MoMQ%{Slt@tlU%es^<6S=qtNKv`Kq_VKbNkISM4px+pv|AOpeGxAQUdKT@XG0GoB zzBJAYRA$H`uI^CxDk2}{6Ra5_Z<1%1Mxnd)Yi?~P!fzrvXCem#IwShMiD#^#b;C6G zXxbXW%WC>JR@1))DSa*dUQ53*zm9&dqw};FjoUQ9{wo3N?U7=_N89%sik>iSe4^M{ zNU5jo9Wx_!=_zSH-BAPYNR2~$U)&z~ezQF6zw+S0D+}A)O~Zl0!oaY+Fmv!AApw?` z)j^R}{cqG&DkH;QUZj10D0_UIJWI5{IbSN99c{Z7oLN5|`z&GaBM~Ddk<#XIAXX?N%FIGd}0w3Y$g4WvfQ5%gq^%3kaz$xoK z$Pq;(bUeYgm&zWaR7Z@d4hCQC)na-p#Eu7QOGOIERhpIEOCbvc$#y#aw!4mgt1U#@TB;2fs1< z9KfM)erl4JS|0^_F?rV}oQTMDMQs%7a7}NveFaJN$-8a8oRiEbs;m}QUf)(x(Y8Ju zZf_4awYRJ9#<{o6C)wLgI|le#7K2SAn}`GCnAfIzZ zXX|&e93h?q%TlR+4UmT~rJA0=9p8n=ihVI6CJh>J1FeDo09Fb9n>uJTppOO!@|;}? z>jPUPV0~bV1kO9=mi*+6^t6r8A4!66W}v(inT#lDjq^+)S2&|ZZDibz)=@rcYx4F4 zsl|t(B5~Lh@i~T+yE60a;f~&l+57L88b6lf+f-VfHDLECibw|*-}2q+ZvKTx&z1^; z!I!2!?8u#J$gx}DHhwW)Ha5}z z%~S0UyEN)WbRjrXrixD!L5pQ$n<|M*lKI|>tKa~Rs%WG$P7)i$C?b8Jh3=T zGVPoYRdzfhyD8^*#Ivnq?^wh24#}CDV=|j_sN3ip9rsS5+o;K|(#$KOjEUSTio#Gj zGWz7i?s2sAj<~DpJPl`>?S&=T<&NwdJGbPS9Ayt0_=v5c5GfTO#4S@Fo`gV-!;jm&-iPgvn60!6i|3ia-Y#f zv=_xkt^&N|E>Y7ZIELCTV?j~H<=;bN;gS+6t<%KcO@YS7fWNWvu>-ufxJHqKd{d~4 z`vDC)@abZ2)vBBXmQ2Lf@(6y$TH>{pL`A}?$^HVq4u1hM6?p`Hj%-98q01KN43e>! zL(KrLR)jrg55atme>?R2FnaOrz&aLI^@UL-30K8g)bFsaY zxf-v-9!FJv9vOK#fOBGWD`%7NI%Ja|Dr*JUo9eww^^9cDg9-dV9EIXrE-Gy;zs;3v zmb2|exys+}e_YcszOi1pMee1>tl5{S@HY<4eB~=rzdR-?yak3)aClhBuvgif>7J6@ zLYp~#yjxQ<3Oc+~_L8#K_P?OjepB4LR36H5yMs;>$b=#WXX!q7>iZIMO#H5YjHDXy z!wTB>6?6?z$h@l&Q-?@N?smy@i7_~khnbVIY?!RIPgbdlRB>RBK@7+!CQ z;&0i`FVQ=)PDUOLZO%+{Y}rNK3ijk8qm%CdA3!89j|_Mq?vUYuxLk%uJ7i={PA;se zU82<`A1HUrdlk3zqS9!SUX8su(_)eC*zO}nym&>+i8dlkaqBzQH`+ud^#W8HM z0v7FRJqthsl`GQdZMe3TQMC=)9CI%rBO_W)*dGyX#CaW@>&kZv$na<-$gm{aPCKrh zCD{y?WTSPh_3l$b$q{XLn_P2J*2S^C7iP+5tWG|L<@*yiP4%PF6Q4a}cYf~S!#Vcd zXGm8kohr)9``;D^%lxGjU(Pkx{z0-y9mSZSKl-Y)>z6%45Yf-n0Shc^!@`P)ssMaV zR0ZISYo3Fw6Mu?uQ~<|QKtAbE>8qB0v3>yi zv8O$*>FF|eeRsXXLCu$EW?$SXt<#cZV(+RhFR!j~xmflSy(S>Pgy@VugJ6rkd*JM5 z8ng5Pe@mV|N+ruw>sPC3ZJj=XG~K9=8VM_`xhKOcUQ$tW9N>NDAQc3-EqVucwzN#5 zz1n0;%g#aXv7YAU9(<%j#ia-n-1flsADDi!?xRxmv18KjTDBsVa4WUv#rL+Bj^W{s z_TgdWi0ni)9=l^9Q+e5R0bpQGTdT*hRS~ynC3_$0`r!M>&4IgbyW049QEzXs3(5Q38=AUG)NR|b^>=84K$-p0TXJKFG7Bi&H6)~B^vCtJ zwkkh0iZM&+mRIBtp-b_{7=C+Ah)uH-_kuTbRP_eHJ`MP#k+qYd!1fU_!k&Wdny+OM zgjjFPBA7S`CWtaXE&zM80b8+lsrM4l6IZ+Gx&8VGouv>VLJ?^MQMQHxw$SYpYF-QY zB_|vvY|Nx&efgYJkc>@=79QgJn5bwix5WNHNl!{Zo>T%h=_Tph1fX6ar+-F^6`(L- zSgnVGUXOKcs{?6k0z8k( zo-b-%mmulGWcVKoHa0ai`kIqD4m<*P0PXWAnf9Tp@D)%DI027<%>jJ`>(r3CmmyzI zsK3C8HmQ3#nWKtWCJPl*ic_AGVwuodKDqeH2gSY>-}!25D{F>i%gvTD%y~Yi@{h=! zS}@Zmjvf1!fi8`qDBm@1Xm` zWq$$^f2CJ)M_s`w%7g8v-bifEZzmkV>xg}h99XuM!b;`PN2%=kW;#-m&2dZY`u()! z%4!F8_x8>X*3=Bn_V(@`s6A$@3|3VJD{b^$Sw-JhQ{?$mo%_Zb8pif@if?xpLi@Yi zwVcpF`oS4${5k$^M1nS^?a=;mEB&o_FRM-n zv#nKpcMcAA(g*te0kvih-iz)0uoMC#@S@|r*dH$N!z1|3;nQY*k9T8!4{N`;BbBuu zA$W0_kb0ct(sL2-SEQt)ug}+GPWQl6d;6{dw|ih$d;8RYd$GNvv#qVOqy2pOVmicL zeB36Nbx!x!*7lRLYS%zbZU3&$zIE&R`q!?dcSuh=mul0jRreg*`(YnD^*bVpK)j9c zXOP@Z?+vRcLx8KV0RkMS1>2&yCzZt?qL2y!!Z1mgr>^fwa41l$Gt!roL3vmiv`J6J zyx#t8;pT1q_-+o<_hNf6*wGOTwo5+gYbW11{qIe4v09rv9@*GlS=qiZ64}^MQPHt6 z67BAeM!UM0U!G0=(Jq1s+fN(G^6)u=3jCLY^l{T0nNNU!f_J*p23L@u#8q&}dVQ^- zvkcO+*cJhKU93iil9#TqO#(fm$m2l&BD@Z$(+RDQ{ucVhx)Wb$_4lmK_32iRN_k`7=YTS0-L7oph`0QYp|(_`nw`xC0AdC zii%c(p@<+$r{6||lz0~8gCe>jc59V>KWeG2rYr2ZMlON4r-lA~&i+CM0M0Me84*`U z2@B@hR(lN{{Qz(htc$qYc7~;OCDSHQCGVY*qVHOlqqN?8ujHYsog;24t4bjE9PFH4 zw<4x)pQH|_XCM5pFXr6by8rE9PP#1H^_rdXz7=or?9 zveeQ42A=qSf{Z~A{b`-LEKx}7d4$-`Qhj9Tudrd1srW-od8PV`b7i4tiMyd^Mf4GR z1aP%G)-IsUCf45IXbwmZ<0?ir==W}*d%62!Ctcm5{(E7%d+G#zQqT+{+2W{!FoqHW zmbzB2p$4anWG4=$XWiAiZPF5Q8ocKosq*gJhEmMGYf=6#nLk%vT3S|8oJC4uGLb3Ag8P3HCZdu{Y>in|Ha9&K?5ioAnJKRv z-o9PBL3-$Ajm0Skrj=j2s;gb4lz~=BI5yMyjhqiYzroR()RVJ{`eDZ>6DP6gH;o2iMIVz5H@vR^23GWQgyzq46 zoh{lsTXd<#OmD&?$jpMjS=)sEOo+HR+Y z#?hln6(#4kD^J^$A1(_I$ximY|52`-mTG67*s&&8?rYuBSy|b+rB!@)c6WEuN0s4r znr2lxhoz*CD%7y81bJ8ydKZJjBWXUJ!kx61N31P~5wwLS{Ti~IA;q<+kO5t$*8bzA zdW5NQ*&_;50}qT(13V-7m1jGqhrHKiS*6TkQ;scE_~-DgdkV|4vgNCYiaslZJ~>_N z1noQaN>ShF8h0@2Y;+!@MzpR1+ebU6sMsYr!}8?bU+WttJ#FD1J5BFV;WMaaiOdju zM(Mqx^chWn&!`q32(N^P)^ZG>QLXB6Iw!=e$O#6YA{Y~7PLaEjx-t~$Jq#=Q(UJ_T z1yBEuXmkgaDAB$nHEs1p$BWNtY&f2sbz6RxqbQVrX7z?(t}DwT@2lDBw^d|j%bz01 zJ=_s)>QoDTnxmXt8P&dHCtUp_V>P60Mh}G#MH_u3&80_dVTaRFaJg^HWi?wZ>6iLe zmsry?vpv!o((m7B8y;?>5Az%3ZV34bo*ncMfP4jLx)Y%3)}fioJ|(U~zG@`S#jtL~ zlL(gVrNPN^YVRVTwh|9ovgLHHBd;g!l;Q5*+1|bra<=;IzN)Laxx2f$xogR$Yt?p@ z@}%@Xu|Q~DTV-Y2x=<5;H-$PnLLrL8foy)5a+BVr!pZP2qV5!Ap|%7lwQ2GYd&0yh zm9J4$hliI@tYa^u7#Uv1sJ;St0R^AFe^K9$@xgS-{RR(v25D;&3s>oR$Dl|4Y*BCB zr%ST4vfM>~TKB-_k`hyTu5<3|6Ury#^rF&CtAlps=exp9-Cf~umz=ySm0MkrlIDy+ znX4%C3~#$Fy&%U{VX55NbC{fq=gTI26PgLOhfL!HTfCI;)|ZjEGjC>u$v3N zGIU`y%bcC<&S^RC-S29d?^IqqQ>j#q;HI=7*(YwKzq^`b%8(kZ2Tclpxs}HJmy0-7 z;7H7Q=v+s2N6?CxYoIxwI_KBt{E!^!9Y|E9H-wA5h%EeS!*$ii9+J$e)xtq9NUs>} zY2UlHJ@+rtJIX4oxlJ{nv}Zc9ii-*}u4_NG7Nz%Od5_W#wsOT4i;Gf~XUq2ObqiG$ zO;dr(a>C9m^4MB$>e%hgux4l1etTYdNPceN4H@P2NzMq7%>wUQM%*x{dOW~akrQX3 z8IGp3&^vG@HFet6=8)Z1p^sppV4rNYJ|}oAKLb1#nQgHAQx$Itm`!~9xWk*#8fV?; zz4W^BKhfK}%$d!ehw^isg^}E=I*zZkmE}qD&+yVkN+#?ZU-`?XFU``MN9UurS0>FP9LqK z(MEl=5q~G$yH$nf%DYKQQa-e8B_-+bb**;nJ6#VUNjiS#<%Fv57d!8o_N&&bJ5RdH z*)KgdRJe1;jwxvsP@&i}i<>Kamh}Amyn27o*%Xy$6-AOCag~+1@R4f71`Y1?Um`Z> z2Riri235XQQ@(9mMRnh%P4b-!4@ytRo_!-T-DGYkEH#_6GOebJ#-LQxxLx_9v!=%B z*+VKmsYe&V8*xX-+lNI_qA^<(g;yQgJ$Hsc_OrMuGBV)%6mvM+pgST%NX#`8 z^{O6p>L&y5ImKlq?d5n%rnYD*4ZkG!DywbMV~Ty|L#HI?UjUF_JA9dKVOp9I&`L?p zQvJe@r5Mq1nCx<(<2;h1xd#t+GBhx%MVb(WD@Gy;m*vQ8bvGNeqD%Ch`;=8S>5H-2rk!iM^1=ID zRGXmUR-pe>-IZgJUjeM{n!c9|b)+|6Q`);~gO6B1{rb9d#NIl}GI~{P;VJ1^ zf=8I_b%0eB`O$hwww_4)nkJpY$6%!y_VdK^crj21h>FM| z53OZ;5YBs%aR?6)c!bDx0(TJ4K{Rf^K7#KKQYmW#{P#f{h|+T>PM`zYN@ogmB2{@_ zYEn`S6s=;LnpDHns#5{oME0fF6^3!C$dpkJ+md`autAn5Y1>MOP)aAIZsn}McI^8f z)xwldt$VU48+=;6b>T7T>65Q~>q|Lw;s~0iXi}9Xp=07Ch9xzfX1Jmntn0|m=8=uy z1l^j?V4h1ngLw`%Q`p_vHVRD&woze!TYj%X{xE>0>fX(>a(~QsdPKdbe9LzGv}9K9 zk{(-`uxl4ylKy`3wd*d2Q!btMEc3Ta(px}#?(c!f4-3LLLZGlXK$F*p$-U#a$HMe4Smg6ic~zP0rso-!ZG&DlP-9okHAGZYdsE zy{4wD#@ldXZlK7OXZuvo9x_;zSIWm0l(%K_TLD%(RagZ`+SsOgxy=NnViCVAY!WQ?8f7JP6|m*>j@0wr z?R8GJOBCJAW{Ja98v?3XVsG`95X=&dr$?5vW&I{qcvXgIt@5u46|N5AEvQq3$^|_HM`+zal66iccU771aYcr6ZuIsS@|3Nl^nxMl-u zAF8;be6TwV3r4uRB(%1rqM~JOsA+9$MMdjcsZBsEu+?{gpxbM^57em|iB!ArV_A+h zhFU2ohnl`%KW@`#caSXdh(8)9sG;tLiN-b+YOuW82pUosAYPhxbj^lG(yiL{ZVPQ!)iv1^OXZxH!W0i#czbX1}o42bx`n9c5LY z6mU;1I(ip=B~znoIjx@b^erS0WfS+u8JkY9h2Fat>?&*p34?pmFZT0&8<1k zqO8)=Ld&#&q1RUBH04CM4+S&7BmYYIl~i-`xb$mM;14xbRCHd}{~de4X33N?b3Q+C zUNGBQRF%_w{zd0U7C@KSUk9}JZ6s+K9p&)GINOrnIHc}1oUvwlBOU=VI0HFPFH@g~ z@1tBF89Obg&jkq<9PuYn%W^8OLBbZ*{Dy}pL^|4%GgPW)JAiyg*O4P#M_vh@*`HT# zw?(!M`7^&EH4#`cd^PX25nP({q-Ld3K4VdSgHV)k%Q3-Y(cvt)A{7Q@@awt>TVp+@ZPFs?g0*{-joanj=&Lc;L%bz@VtNnj|@08 z6C8LBatk^Zvc#pqLfs9^!$PjBm(*l`Qd(;?fc!Xk76W9*a6kYg;69$0?Z_@EDa;`M z{%>Iw_@Vs9OFxQTAPrI_go~Bq(J2iq(|cwBmgt#nmlIgBa!r;j<)Z2DeVzm^Q(A!Z zse`IMRYsY_=-7oSGOSNI6Z9!DT1lUxyNOl|AF{Xyozn_Q2W71ZkAQ7 zLIHgZx_UDeCF@tFrF%-{O-Xi^degz!A7`Xzm7u&s3EHF=|4ZFmFE^jto>yU)Y>k^n zBH3S~-BoSLYOJ^{kIenyyt}6F4$l3((q^i<=RU>%)Kk(4<&o&-GHXsrMP~WLrj4}( z$MBBELj*@>7QGJ3?%*kAiiB(;i2*qP$nj*^JxiC}X_nqo^enbg6eM#QXztni2)X3Y z+0n-cwG8MCJ;CQ_t-c0!!)o<9__7pHmNp})^)ppLxlaHPj?R}P{ zdPVt|>F5_8kNx$v*JODm@>9Nf>_S@{jL^d=O1lgeWgERI%k;JsGJPvSfMs<^Ud)A! zQxIHOTn87<(??tfM|3!Z|64>E)#+QCU~ zJX*@XcwX=?9vS@0M;PNd)MN%X;}PsZIuAPqKab1dGfdi~3!Dyze+G@mNez%$4R|Z^ zq1nQ6a=d}#KP{QQBb{6kW_K6&t(x$b*VZ+BfE9sH_UwV;R4&d$_E(}m;db>*1eazV zpm~W7!1Zs894N5@k@69O4eJbu>};aF#Pt{96>cM{g$_2ZuNkLZH>U2je?mVv-Q)8f z!*eM#g!!uVtRd)*%gj@6(OK1b>GrVm((TdJgG(DV^+5MsnzlavCB^#8GtwVc!UkXt z9yy`PA&47;egGa>LNH_fphVXXxMG=z{Vt;Ofi(xz)PxKs>cpVxC1fpF=EWN1PKEVR zn4rzQNKQw4SQ*Ts*-(9PT|+rN5|AaZSBBRN5{^AT4}8c-xq`L7*K_m$&p~@ zGg2D~FSb>SEW0%KG)H=RBF#OH;5amg@nCQbzSo%2AATbCyVswW{-oUAyxpB3%^Wy* zAqz8qQfru^%AfE#-9$VAmEy(-p2&i4BpATw)TnX+WD_BB2vv2(obWlp#xLeXAG}lg zp$cKUWM%#|d{I}@e~a>?D|(~a@0> z)weQi8MXSH@mBTvoQNfa|6AM(_=NS5*dr_16Lob)m~B;m)oCa#m(qU-w}rb((j5V* z^^?mFA3S`8Y>&-AT7^soUlrg`M*3Q_%I{%og^k8SGYu*n;(b+Oj(t^PWcaFT^}B@Z zz#dnA5`17meFbV#H4uHl8*pm>mAWO!b7w^8uI$5NuoNja$gBVHw`ILpcO1U@@PEpe zQ=qOYrqX-&ksk{%sieQPld2(Yrha2TrX7MvJLGX$X_m9ijU7^|&!KCbM;{6QCFT7S zpGFj2lYXs&ya<4wuSvbg-Eg{88o zz+Sh>*A&uRUgaev<@iYBX*Kcm1_GZq)T>CZcQ)QOy?A$8lzRJ?+>5{5p za(Mmy(56Fk((|!zznqa_l4Yl(xWt@oH=CP+Qbx_B@~2XltJGCeLbL#X5AY6uPj}jF zgmGj_v3}B>pr44*O8N;ZlZbV~-ve8)n8QwL)<=fNr%j&|dFAk6h`TxnSIJt+@|JbY zBq~T}sV68fxxPnug1qIo2s_lJJvVBeAjXE!RiqnA23D{2lDW8UUENv2>~v-4WQjSy zyi(eDc-`T{((^)B0W9HXh|u4U8a8TH3cYnY&9Fwoeg-j$_cMq&!_N@Z?-Dvc$G7p5 z5Z?wJh25TvU}PpoVny7=&(!xzXICtriILjSS6 z0yx2*i5j}+6PyOkrY*(OP*sTz^FXkX!EVW#*jSG3GOHYRsR)&-|EV!|g z?O0!HJ#wV=$WKh zR@3{Xk%U;Cq*r+LIb@2W#?z^E2#O|EJ6lUXKUFN-(~BSe@Tt^?lV6s8vmjN|-)2f{ z*K+O3sDehLYTZX97XEUoC!qc1hRj@~&lS;%Dt&~Ae6IIYtIyTaih6w{^a^MVBDPCt zh=#93i)%wgOfrD4zVK!jMRt^zTU|q+v{Rg8#C}5?1s0WBvt%Lxq~t9w-geufRKM;M zYv~-{z4OxCW~VdPepB0w+hWbmt^FRU2GZsKJ>iP=ZfVDp>&9L@o zNWnGw9DKfY`Uw0Kb};Z@aTk08hzo`U4C$XeJ{-H36rNbuLSdHb>lwm-Pv^dkUHKFR zbzxaWMozQ)QLDw2o#~9^-P(T5Mq8OR+mws?K{{!Us=&Q7riON zSzMf1m~H=f?_5KMB{Ro;u{5;sB543GJPsS!TB3dAb3-kK)tfu773YUo-aeH5ZmR3C|IR!gbckZ4lu2yHJ=7n8))JZEHbRV3$U(zL76 zTHJk0p}IY;XuW(j`5d#-+B&z?=jW;L;oWEVk-<+HO9#${-t($YOg-(rO}W+8ls&! zpguoD&s{_R#u`Z2YGBVwFfLw_mBiXlEBAzMjdIkFnl%=yTM_PuKJf{u@%~)bxJW3Q zr=Xvszy$^UQ0`c#a*p)p<&p7+=>FgN5_8I=IYQ9MSDt83Q$H`0+P_=ob1q_5U)+`1J(x}mAS zMaRh>K4xS!r{&wu*lkKho{ z&bu9^UBnN|h%fb~okP0^QMRy^SxC!bTUq>hC+2Y8mFp|Gwzjy2>S1mAHCQ-0^%3kW zarH@7IQy231A-@*PK=dK!)x27hwHA(7a>4zH{Y>awf)PBi#IKQIx5!{_KvOfRM)wU z;Gew!TBUsaso0ZJ(L7+5PBMbXuW6uUkxMX*Um=^K@p z+vz!MqfV@Y#??naYsk4I|58%kx)HCk{7I1ztuiE{R7BLu-+K10iK=v1ZY}Bi7?a^O zZP#p4r3#aTt)*Nql5Gm8uuEB4bWNyg31hH9jcd?=_Awz zMg23#C1Qmkm*BMEr;F2qN8+^LkvJ^~$^^`nf>wmQmc;2$9Yd$#>c|=`WaaOh9@xks zE0Mzorl{9|>{LTm%5`ZjH&pv62K)!wjJ$=jtj79_hBJ=;|p6)`Kwxj^?XcsoIHkizpx%c@m(TRy!neB`K? zC+0-Gyu`N+>erF&;MGTvV}b+~FF^?Lpg#Qy>NYi~REvC^l_OS61Qp1@DqO~b?-)#S z{bcxRk85!&UNvr|?xOwsCC^3D(a5Cc=Gn1pvJOEjha#7;pXZ5rNA5ziy7b zE!zn!#Jhyu0J;jQ)xd@V+Z{BVe9{6~H#6Yk)#vc0)wC<{PMovK@!7DGi2Gpo4C^D| z8G+O*Rz%_bT^1e*Q7Z%#RWVS3(wD+25OiOw$F6)ui(UERMSJ&3br(tRY!P8AGy7%% znCRKlf9f;A&+Cep)gRBV{ z7A9mCa9%3DfNG{TIu^M*$xogV{ zekV%x2{1F_TVihq&SKAOLRi_=8hNJk{>xDi;c}7+;FL#%BUVu88PQ9aLZx5CPX2QK z^XAx}<;;_>9euYg4rZAoaigMgXWCr^voP%kj&dOzsLHt{ni28EnM89ui&zYoK5`Kx zIW`J47+9}@UqY;gl-H<_VCO)W9%20q=~rM;MIIVgpy4d@R536A95nTq7v){21JP`X zdilO`)3lVoS&~*|0?6m=c5cdj)R4cA@(v$l1Q6Iqz8TgM=28viQxFX+^>X(ajiQk3N&`N-M zR+V{eQaZ=Gyh%m2AoEJEGyO_eE)O*2V};$rYe?{|@qADZb}2%dzG+NJdvX3t=GfO{ z@=~e$Q^a6E_CN@WhJfJO53$vyOOqOi&k29oAu&?%W7S~b}**I6q|re z2U85O2^esGngN@Tgz5wv5(xaX{B%pt|M~8jduLQuyK6#{I6LRQGMaPlJ-v{8AnAF& zT3|#fNXaFQLwMfIz4Nc#AnSo&-*n67CH27C<#4j@y7mF`THLA4Z>ha^s^>9j0egnDcM^5We|JJ;Eh6ijeUS2pr(BNI1LcO+i zOI0g;jrKH8GC z)-2V=!Rh51IDLzPWEBedz3iip{Nhf5KRCI#b5hC=y)@T)3HAu7BpgxLRY*9T%8-u7 zTQ&&Cqq}K*s6n_TqgGpW!DZy3UfxwqbHB!%bV9c5jao9v37Hk&xOHnG;{UrVw`^=Y zc9dF+y{&BKcM)>(z(>#hbWkgd)QVKqcG_86GOnU?ekQWak)NZ?!bty>*l(&c z&rk37Epz8*OF#eEmiA-UP;VXzQ_ms%oQ@+z=-)~^4mg5-Zld4887>k>4DpVW*CdYk z+WBzAS5r8uRPRP#n|k8h_4JL+Y8BcmV-A@r9L2wA%q?%?L)-046=Uy#*0WoL!y<*f z+zrNmT0?#cOUfiqTd})j zeQ^5jx`d*!&iT0*qwlrkc4hQ+9NFArhgUW)Gc<4w4(sChMU;*G;+_Db_P(BD2qQR) zvx@dj9Vj9H#MIQzoo&aiUHG^t8Ox2-i;^+=_xvSee8$a5b*y zMaHd0dkpb^a86!@2MKzti>@#Ym(1j>KYKIc0YjwGy zEqgL=InKL}Y-|)BxV%hzZNX*Y%-fdx=~Ta)A3m7m0{3+vFA|Qn?9zQ?`@=UrRl5z0 zV6m`vv?&s48m+D4f9q;%YHDj~Bp~+~flUV60=7Ra3*ZqJ0!MWidlIjeWCgGn7@7t0 zDj>Dx8l*PoQWUB+=|4f_OWr3f2(tZQ)Q5uS@eeJN&#?UUM{e5Jpj3NjZu>(Rs24j-nE0{i|*`-8dJE^~?{P+I?*1 zap@`|oba5tPl|{ybd?z41HK%cVz{N^oa1Dh6=WtTM?uhg0}4V-N{n_5y6z!kR=%MK z@1%8(qp&}XumMk_Xt29f)(TA};HOcXG#IL|MgMmD&hI%y``mKh@5Y`uNyL4|L_APCC;W6!mKCyM+2o3rUXXm=@_cd?LwYVIvLR+wV!rJOo|rj@5cRW^=JLv zrBC=>bYH;u&GyH}yg{?s;cuQjHePJJNB0I}?uQ6pN6u+8i((+1ekN2KDz}uy@*=jW zk`}w}cID(*oQdkj$jNZP6*9)AFTdRQ?X2-Nfji8n`&ZDG&JpbMT>7=h|J2C~&C{K* zV{8gS6dl^F^lNj!Ob2l&)SYSoG>9Ea{2)%6D^7vsIdE)eTUN^Hd zLTIDLh?(|xB=L4EITKGmUDw){SyL0unk`@NrU|5Z7I$4sN8U+qtkB4xx%p;eYT|vb z6M9<(#oo{8-xE2QZKkIQZ}>~0h0uhjCEhg&t?ga&sizPPh$sl!3Oq=N5Xd*7zj=hP z#dCqsD_33t9-)n}RZ*|j;l1Q+U1-j1T_IN>RhO~S2ZwsR^j*4ilPYX4o254#>L~tL zUXIOH8Z`cU>j(CfWoCFhjWg4Gvq!QcAWG_3hA{gmYj5opQ{CodLn!_?$~9 z{hZ6S<>%a|p7qh&@(6o~zR-IK!v(af3+VkN>K;Us6AFU12p=;1#`68x2j%oE$Hm|Y zl~>>iEur_1i1%~+A1hKff_5qIMF*P!x|jRXNiR*Gx(=TYdXUKeAMjV5pIT;-Cm?Bt z0efWU$UeTZQ)x>n)uj5H^lw~%gde2_ATyHV^nq#_zzo5=tK|M!yeb7 zG>>Z*NhkJ{!fWVO5d2^~EyttQz?a;FIayN^QCA{#rHF9O+^Jlxr|0&{?|~1XlHS7J z@74XXA+9@IMw#<+dm@RyX@Q3NHC{BsU!d`S4<2~I_(!wv0z7}u%*m6+-Ln&@J(PIO zBK;f|)#nMX@CSm=YjnO=dS#o{Dy$xx*zpdv2EOl85cE>o=WUT%c0L z{X0t6zdtEqjUAud0}1Q&H=H;+kys{Sf$+~6k4_ld^{ldrQWmn~O32y^D;n}x$R3(G zbjY}QxFeaHz;nV`M;Q`5hoGaNBEn1>0`~=%ItoMSyi4A(oOeM-;k#GrD7?N@N8z>Q zI!dK_3s*PFcf!-stgfMdS&M>Nl0M*zK{n+l35mRP00T-NNwrBlnMC|Aw|_{eHiY=u zqX$ZsA%0PBKeVCZK8NOXI5expRpB=lTi$;RgA7UEsR>muDGnAlCiNXhah23}cFr6< zYMk^muj|jxPsF3ICZ#fD&+|Cm+P=r1;fqlfB+dlp7k-EKF>*(?2wsEz#-8B%G*57d zECKceV<*QI1idCK_I^W%=|&?a#ipqQ{aH`s0pI?BJu(blHjV_;L!p zfGLUIg6iDd>H=>@?Ql&fR5M&#H-uSCL;AY|m4PxQ(t*;}Y^9Xehxoi4oH=;V_*8XC zNp&#pv)O!TH!bv2%uW0b@#I0OI(R-Q^RY8^l7(!|fp29g2znNKUolmO??ClAI+!_$ z4#?4f%;ziVGN0uzSv&l!oVA1g?s9F2-T^;9 zPm|~SHqv)&pzlyJ`~tiyB}i(uG6Gf@4(LS!!$E(xw*T>v(`G9P7{A^A;XO2#M0dNJ zW{*waSowq0J2B8)@KDfgvy}z9&-U#2W1JBwfb!8JlTNSi* z70$U-w_c)o(;VexXID}g3Dx>H0xj|PB=zk-ZvD{yge}ACX_z@OUc&meE!Yx&FygdY zBVpq=4M!)(@tew>CBWF_V+$ z0eqh*4lS6uYMtV$(xQ}6;1KD1={#0K={#1hE$6Y&75Q1nIndrcDmL)4qQJ5=)bc=i>cLj>8KVh9@Q*QBPS{x!+&jr9ZhAU5(dGkB$9! z-1tpFZf-$gC?t3<;&|xcn@JW=m#E4?g%Y%H9rR6llcXojt=3Y}=R&oHJbN)ET|8Ar zP>s5VEQm%0VP*s35Qw76Z$TbsGo7stqD}|SkL>@uv~P}oNyx&|%2P8i+Nnz;zSyIg zz0?kP@vBYyN83C<*N#LZ7F$ixLmrQ(*7HEu9sQJ!pKZ}KuuDfUv3GK+>M8S=D$iAJ z(|=`r`IJ#ZBaSxZt>3_fg*(dU?Dc_w(|t$lo)ATPoFxyN!yb3clI6;_&VArfGxb-> zpc>ty=C=?IBP78v7yj#X0wDX5qg+HQ`2rtOOOt*}B8-m9R}xU9KGJI<)Vg zf{@D^R}jt%M^#JJ8oYrO3aTIowGRAuK&mw<2wDAHr-({2wn3@JfIjmnSyu0nmS%{0 zPU229UR4%}gBCOtK1GUC`|gPSNIM>lXZe~Q@Y!6>O8+}M?;P-kv$FJ7qf$S>EseiQ z#K)u+u**PSchqJ1QBxOuK1+SWRdMXH6@b+W48XL0A|8MnEbr*?O&6#d;l}JK5TV z+-B<)(RyBk-yi<6RA#PQT}yGYpjyKT3n>UTK%s)b<=Pbly0HF;GbX=}&zOXo=$>|> z9pcsOe_lt_0@aaS(o3HqabW2tvqY4oo1&i53)%5bhwuF4^ReOkhO>)*B*S-V@dpz( z74R|4Dh}P`%XB%b{IBacN93bfOMkyQ`DTp2bN++z{>eXW(t0b8)Y4hZYl*aG)rUfU z*FGw*Adgw}<`t(8 zwP&2UE30&DbpJYWO;&TEH-5@%pQElr$H-L>>Jf_+1Y0bjAe^`w1wk6Y=fK|r-LyeL zusiw{)KAa`1)-n8W(94gzkI8pDR}1?(Q%A^-B$X%lRodH)3~&6_sZi(@uH?Q%Nafm zqA#g~V6H2Ub-5Z52Pr$c&=@KZ_zz2%^b1Xowb3N@`ktW zqTbq88i%%$&A!iH*VvRx#ErG*wP)3V(@s_n_$@iP(KB<#H}%UGKI3cX8Z2=Ki%PDv z(?FD<^Zs~adDLq5(MXgBQj~wyHR|kc6*Tt|e%lFG`%K>@s^gTfKG?4GLFfY#lKMc( zV~1J|*6>nMP&BIeLeKlfO<;m`rOBD zgr1d}{zm!?8xH#5c0p@obM2u|6k}axk1wfiSV?TO`Zup2YI-|%Ew^O-{?^w0m}MmX zEqQ+$$^9*N;OtiVA85O+KSlACtoNSvb#?3UpS5NXhWTJk%@D@C4{6UzdUtemXAw8{ zx(-&Z7v#Qa?)Q45u`5N<%jf7Ue>pk#9kSJI>LXoolJp!qX?fkE9s(8I7W!{_KdzMC z2u{ot;R=c6y(2jqTTGIhpD8A~v?@q?N@T1p#cR=@i=V)G?N$&b-KF=RT#JKRNH(_8 z;A+Z(kxGmH2)Y^FWRxGfBKVJ5OEgT4>GNOXAt_SjeO1#H^=^u0XzL>l;Xtn26YAf* zz2qMAx%%6wN9A)`JC(%$v(aKcZtNJkzlY-6WxFc(Q8`o4>AJFMtKaGfM?b1l*N=!d zhr*#*wv5^Lv(B>Nr*0wooB5zk~+vyEQ=v$5o%I>D`-AyZd z>EFHdS52z>CTSJ&?F3yp0jdO2JuxNEBWFmDCj5rroPsPzP9G_p;s4uP3w=wZNB>B zUR#c<&U<;&Rjr;}yH#s$Z32b;eVfNh-e|tJ{8s&EU;F0b_kQ*hJ-+Y{-uljgl33hd z<~v$E-WH38D*TtB>5J8Kd2OG|8M!96sxWBHusR*Zy1!_ugZOKAYjak0B;GR75@vJ>jn8oZxQq7i%Bq1VVafn#r?D;tPc|5qPp3Y1qbwv@u{lz4)#r*0gS8emIt_^N*2Uh!P6~Q|zCOvz23|q~N8^x<9AA$y?vr6({x+?~bjr)rCVr$FceiZed7&PJft^ zeLr%)i}t$JV)lDV?Bvw2oVY>K;IMg&WIg&0G?0%QS{(AO*p6;U+Nf+tOK5F7+D-3a z%hpXe3M(kphaj%jK#zO{;e??2i=W1h?^O^iC#C}IV3~2xd5Ch)qhpzT8h*ba1&N8Q z%Ld)2D(#o@Bk(Fr*jh;?^Vl+TxvhBfP^ag|+FZ22ZZFNfnPk7C()ZS``E|l#{_?qV z#v50X>!FFeD<)rvlf~>PsjLZ*%^YnGC2TZZJK)?}(jtuJf73IJD?l$F=;gF!961Pj zSxjSOGhgvmAm#!Dm13MWs%AhsYmNE!JH$8?RFI);r)!F;i8v3gT6vT5p<xXvSF7kKfi8ReeX!vhiAvJvIv>UKPoFgcJ*9 zqp*5owyZ?tcBa{zy5_q)GyrgQnw>J9a*_99;?Ly0sG4Ymf!mRnB-wOTFGv>oCq37g zN|EfuQ6kw{<+~VrdB1rNohQ^_b&-Da6QUS?A-r-XTHzWjmO&CqmqBukWsrne21$rz zkc7bViq)GT<>8U%?}7IMrj~P!bKs@<0io?eIy53NVDB7cqMY>*hkTl=A-b_9qd2g zNfQ#1UI}<24pgnPo9U4LUvf%pNzw4StLczFQ(0PC zN&nF~L@xAyQ~VLR&^03K9`-Hr_mB(ClL^6Nkqga`nIPmsGX#1g7n-5;TxibXg9b>t zAaOTn>c|C4&}a4~%BMhCu0bUW2hsgC@}ntkPsK=Rx7T#x9O*63FFf}Bvww5;LP^q# zKRI>k6QB45p+n%~sK}*2F5NT4vrq#9os_yOB)tW|K!$=cXoqq3oL#Ni=?76NGgT%_ zGTmtLU9-kFllbP`>S~gWz&GN4@Ghg4t48^1%nC9SuGl|gCQL}5m`7bl=Awh}% zbcf7l@vA%h^ahu}wwLbn(tR$vFG!!!FWg3-8T0&EMxqdz(JjY zagygLh@DJG7b$k>*d_+TR=b*tlQLk^ld-D~HSK-lZQmz!$JgbrOv~^t|ka|KOBt+P5-?3({~CdCSlX8M_DBIcC~XZ35@K$0a29IO~;|gb1xy zUX@y}oZrEFRN@xNujBF+fLE5sUMYf3i3%1hg zX8IoKJ8{rw89_+x`#SP|2==kcem`Fg4`+P&n#zc3L`41BRHoPV)Jbsq({sHRUs|3Z zHlLpK_4(^RoY-F3|A2lbmF$%_F*CE(V^yalneVlD^Rfi7y0p|U?VfH=+eu3B_qRL?l*qF>3s)CYjOHoE}NMsH6GFf{+P@7 znDJKgcH^!3H3c1!z6?(=oK54WuS@g=1hzem_m^CY^Q@BwMDso=Mj&;(Cg!$Y(utXIR|{iyK{Y;A4_^pdutp zSWM^5{JrVCnKTOsFoBE!wYBmobz=2YTFIkmHgXJ!r?Uo!_nReo9BQrO_4s6MW_K<$N^S8R!dxnwB{6v3h|qoJnZL zW|BB%iVI{Z2;K?aHQ9u_Y`Qx=ThOcS14oU}8Rk6CVzpjO&vTqoTDb{z4H`kUf)Ink z4A45lG3f-1Bblu%Jf4boYDrv%QnQbq4X&&Bil}HY{xI_4qu!9!>210Ce*#{n4%M^PHGRa2x!~7nny6&XwJYkl#19~U@ z{-AhEMBNpkX9^XBx;t5QCcg)Jt&qM!Vi>vW?DfHUfad_-&9p2BwHE_i(Y-Xga%nOa z_0Rd~r1tMd;jef{{?aIPYCj&X>U)1Ox9+8_A2~p^EM8CJ$!VI^CTdyWlsPyuJw5WH zxKn>JQJT+LbGr)~P{tB5XBU)Li>x_;+dZ@=zel`fP_qzjQNIBjuaq?UT(Kk3FBWGQ zyHu{3aTon&3t<(pG&B85;2Pddc@MCitsv}OR9&$a;GySmzJuyIZ2y>oz)dsh{rPks z^5~#J)?yfwI;}-hsG59X%_pnRazIJUM;zx50Zud%qA| z0?m9@RHBe2DVjMDFDYA-YG;hM{^_=d z_vQPFKwF2moa>6-TtCr2t!Zlzcd_B|_fhGQkRe=q1ex1ndL$`zkvr}nxyW7ipog33 zmqP=wsa5IeAvr?V;EnUBYf{$o^GjtdudOC)`AWL1g;pcyoH^+e>*c67QcO?G7F?@3 z!z?m^7ABJ%?-z|16v0!X+UUjIGc&u5r>Wv-O*yxdbM6p zoQ(7L8i{J$(MLXm94&Y+I|ScKc`q-d;V1zvFsEBbww*g zjytAieJ+h7%QSc`6WUf84M8&Z&wuW7^NRyx_f-B$J54S4?RACs`fW~EdElKLx32R? z>{*%-q8dn_FL7<}{J)xiJpRa?@0iiAG9F3H3{uFxc%*1uW?eYqwjZzRqmXf4Y|Mg?`8Dc zScidsT;2hnS&M>X$0vBk?j1x?evhlQp#NpD4V(yJoEae66E%DEcSah^bMLav<(J)+VSb&*<`34mCrc(1C81sZ`o=m= zXv!?#yuR7Dt)j`5tb#&so;ylCujY_uhkmlJhe>#FtnE#Av&x?P^=sc?CIz-q}vI@3BwaYcn^ zCZFbhhhw(NaIQOhLqUVv;)}+NZ$vS6_91I&AYifBY*u~#mMPtm%*!82<_>0(omfGX zgT%5C4zmcyR?@7p1UEz-1kJD^Z5Vz`*1OnF&mcS_cI{C2!aL$u5Htk#X++c-xMZG! z@(3zb5Go`p6@>FxuOL`Am9!t4#9sn0K{I_jWL6V>Zllj_;*M0U3h4`C+%vkxtQnz3 zdWUGvPd8GX1RYfE?SFgIO@FI>?&ihY5<^|pu4lB~XpCBquXQ8dLs5r z?JWT+S@C-Eh7-4Y-e7)k^tM~{6AKT%QU5M_2pb>t*0;1rDbSf1Ev~mwTqVb~v!vZa zY1+}l(c zV0X0z_xdtiIhDQ#T3+4j&$HWflRvK0-fuYEc+UB}`9HQid?(@UP0g=vB5s%1RI)y+ zE*#Er9j_elQnpv@pzibg^DNmp7UO$b{#+LQl7Zx`l?eGxIz>f2;@`0F!vwR14}Bl< zoV{r&FP*$Dy>!^gat%A#qaZ{85GiDjKJY8=1AYq?l>?`;Ln05Q0A}5yPyNx)m^YcJaku%z?Gdo1;i)lrtrd& z&P?Yam-q$FTE2QNHMOWjtwGPKR*;;g4ogISH!P8M1+^26xNA;_T0@;EI279>$fuCc zimtePRJ2TTISQv^KqiniwFp+!qnE0Z#TA4FXVb3`WXZp>N4wMLc4=QW%#+$b8r@yi z7nnvyXW7QS7VporJ7VFSyoReo4wowte4y)GzdzRsK|Zg&S&+zN+%Wclp#_ z5Nembprp(@QyOikid(C4bM4uKMGdYDUo`rAoftpP5%;2G9@ZzOtdIB)dpeLGBF~mw!`b@Fa>Ekp z{fKLvKPL=%mGWCV=`U#)XO(p&X!G(KGHc*l85ERC`Bv7FGn^SFX)4uV&gG*~GmDGl zWf@=m#@Ov^ikoLv^1nIbJQ3Z_>{n$@EK<5{h)S$Wsf54KdZ%d8O)Zm*SinCP! zmD9qOlaM9X&Cx>V3dyyjX=1qI9;cQavAZe)FPoa)HAw=^q2Dz>zX~C>FF=qLL{|v1 z#b4#rbqyu*6D9G>?KOd@*KuFlc5j9+Ph^DMoTBTyAC|HWaWRfT+sP)qhvr=kgY3VMf5;ka}_Jhd4;xe)Wm{1<4@wyNv&%b>Y9+ zS?#&r)*czAzPhTevp++r zTyQ&Ki+8%b1}TAvl#CTR=rc#}A$Mgjyj=AzmiqE(NPTo^OhvI!8(K`?QcQmVy6^B` z01C?PJIRQl?1?7hQPQE6wrSIv4T^Z->0g+)|LbjcUF*_b9J)|o_Kg#dP0q|vDpt2k zf9D!8S@sReI4tr@zeyN{Zx9&ulHJL_AQg%2P;1aB5gjDklYX__aZYu8Wh55&rDK<) zvU%zW<}LC&(WQX92^6b4&{+k22@-^3@E7AiA|pd>gztsP>F?4WpSrl%(9XBN z{lNqOcHsE&1ICvw93DC`?)oMMtfqR_7LZM~mv%d%6_8_yRul>TfoMgBg5c|MDF}QN zu?fC2JvM=z$&ntFX`y7$vYt9V%AV4{oj+Fpt6VM1mGB!s+4A0fD>~CsrxksoW=CQ? zt1cMvWuL1X2_>7-_H7&!O=%bZ>lEts;NRz5%L0RZKY%QI2X>4>lR=xwrBCHJl3bvc~^x|zJUlHN>G2b!?7IaW`};nYYprqQ3R z?E7#sALn;tAKjVkh&RI>q^Rd?&OwnBxw!C{dAok5vNXZ1y(S79WWU+ML{*qOM17nR znY4Rnl6aB1Ipt)FVP+|Eb6}|>H-{~CP#d{93|%-khwodOn^U5mUuvBr6Nm4Y_Mh4t zt8@BP1|#||>E8|v)O?jQaQ?jcG3qHx891HSp4f$+vbIp3J+mR1d2>u)=GMG*`J8@p zSw$~RX^Q1pa%x+*DY(-HK@3Ou5RSw;s7s<%ZE3Tpea?wI#ewwyd8sA3GP|Og0BkeH!5@;Y9^y@6* z>Jk1^!DUFSl$(EiatrE?N zy4INJ7P(mBX0enV{?|EoU~s#485OInF0oMT%pS;wgv<0I7-71dQ0XALAdwP@MobRMc%NK>iF1*+%8E%vs`&)O^&XLg_| z=gn<*Y<0%7>=~}E%l7p;ji2dH&d=+g%#U^7)cYx0AQZHDvi(mEoUXN5vz^8E`fIK~ z-88%K1@mdrDTb4AnLLV)lu{Izy9^c3UuPw_K>T$n|4UGGe##jN|wlC$pTwNg0&XZZ}&ug@AE)Na&spjY;(Iro@@Iz+z* z^XY+Y8^MfinSlo1k6Z&UFQnba*_u^qy^4N?l+x#!X|JjL<1(VowvG$Uvv(UAC_DdR zaDM)mX)~l&PO~@eocPYCU2oLS3OXGZv+U77rph!n#h(OgTsE&TWMFu32cvu>dUIhu}&4z7Kd&*d^4;bsIQPg5iN!(vF5{;T=H;CR z`>v+lh&Q{68nkbbk9z~<(t>xyiC1)!^cgmNnrM&gXvj%qIkVhK?de>#hFr-`(p~dO zcZCIk*c0CkZ%;x&*!#tVJMP(8PItrqQ%p}*&}ZPNO5KZH*Gc!XHC;#7>*#u$x{g|+ zbqZQXcQ?{|IG1F3h3qnHYN82$sdO~?DZrm>=|JgHg7cY0?(2aIAUL>RYg)WD*>``i zIMsLmHS_b=Y;kCN)Q_yU44v|xlew|l&Dv87KX~pR9V9o0lW`!6 z;F(p_w}-hV>(HfXIy8E~vqp`&8?F_Msx_|TlXpN1hb|0D6jAIa2FLc;ca1gGr z^P+)*97a9`IocK z&Q#c7X*dDu!CKPvruM19#650JvWgq0BT5)!oln+)bG}A3@e%AOglBc#)q3|B7`3jG z*fQ?xY-s4}YG~*T*KTg1#I4P>b^Nc^M(JNWF^TKI?$bOE?R6c~C1OZdrEXrVsBLMf zt!-|GOdBRU=Nj5C`Q)wc6+RtwUV*1nCzw5@I#%e{bESin<1$L@Q}>}SRi1+K=yc^0 zX28wmn-a9f+1ssZt(BhYRuJ-pFLv(zdALnp^GI^!{U0{JcXv2ovAX@uCl2i{GCrc) z#mM{m3oxO%mb&D;`xB*Y)St!S$+vpSYZ}D7`wyLuEj8(sBDzvfxQxyq^aR8KHR4cQ zeJAxHWL3yD3t@+20EmP$M~05TPb}3DcundE3_(W_I?@t7DLpN5m2J47uQvv@PZ}Ft z+Gh;c)H~Ce(&`$*Z;v$|DRUm5(%!s=uqxBOLbzagG)ns`ha?7Oy}@gUt|OU*4GN2x zGL?;?i}RF8zZ@PaI$3n?kY|D(SG@BOZBDPJkx$Fa1?)7rhImG`f`mk%XZifn4nx@z zRnAh;V}c4^TFO*5!RmWT#4iR9yRKcl^VQCo*IZ!x7@f7}UPoOkI0^}#q|-H)(WyLUzgk0xaJT0&!eSZi zi)7dB7LrZYgz)i^%T#?}6OLx^CM`UH4heY7(VK3%&0@C|)Hntr-Np8NTb`{ex1-P= zce!)yC7qRF{j#q|0-7Gn-B{6@G4)ycY>tL*rq0{XpEAO~w%E)$S+PeO4%RuXx+V0U z+Wl3oj7(d;x8wR(UDY@j_V?W0fA7AJj^fizec#tRh%W`n_Im^2qnUCM`o*s4r@eqk zw~64675e=G2VDJ$IuYav$)}Jf#NBVY)mk^Lad*UCwT6yg zTBFGFgltdZklOp#N;Fz)b#8e_ctiI>N*Hb{Zduw&TlYqMnidTm_GIP7YMphl-k7U^ z`tWNOb8lWxVNQM^!?|uCld$Ozc()c+W=?4x)UA0d_tVz@CG4+1-tZcKjn8k6O;-*E z?H0SHQ4YiDioviwGm!5Ze9LyiV$Fe?6RlUZ&MjUyOM$e1n)?qu3w$X=_9t+P+`&Q9 zU9`_S31?jbr=7{EmGD|4Cx~ZJqVoW7$~6Tggh%)XfYVa?TuPsVbQLq%Q3WEOO7-YR zULwBb<(4V!v*?W+G_qjoeqR4pnCj$P9|%_Exb^64 z&4!T6Zr#o-%p8NYbTP; zAENG=S7~O#>?Zn!>jh>vC8zuVvk|&yz1X{#vRly+fuBOBBFGzrwTPOHN_H@hL7!&>%o6MWlpbiZ8?55;`?TYP5LZpHZD`%8Fey$>LHE*7fc# z?TK~n@x6QZYs1(Nh9@i35UaFixZOErRW<&)CVk2Vuw&3#7u_TsbunUz7UX9Lt9G&{>?&a9}>ycK(lKl%#`{r&=7r=bgGQ<(e= zIHx&uN;eB{J}8F$V<9-*&mf_-{S0pP6tcW46@-|$n`p_lbt_S>RjkN8#@X`B35V5F z!^9m&1ocPN+9*+cg?A#!21W7^N0rF6M*K1vVOot_;$(|<$|Z(#QhU-E)_aU$cyWFi z@yEgkec?d8w>R1qb;KMN3zdhGILgn-_nTc!8wJx0`gat9X^I2>(8S->&MXwT%#N_X z;ZV(9PkqRr6&Ww?^w~6<*-HO=u(;iyZ41U-jkgH4xwm3h&B4~Wd*;5ReVcF{CR+-0 zXd%wE-*m(@qj~6LA0Zs!gqUb$uaZN#3W8??JQKa}QnCj;Q+h8@<6S2(IINx;rl%wY z_R_uWL=EJg;WK9fkf(w^bBB5GQu*zD^tbdY2vTyG-jAF-^plbk3-{8eO=4{;y?HA= zvr9d*i=YVwO%Q#j#9wz%tsSJd_R$-Ti8r7=W`^D}!{=NGyJb{n&0=--tu=Wvi|7zj z;}XjXhl(hopd&61Kf6`H-(#UELI0j;ca%o&f_{qp;p&oHvyhs;ZG}~|0fx@}u(smN z(Bf|&eN@YTm!oVn6bkBQkEh{4V|{}@kMn+J$R!T+RP`R-8T*Pmd|A3JgOafh7SYDY z4CcFXJJt`CLZa?2AFG~hnlnm`Ijy`#TR&IPF#X$V2eo|;=J+EN{LIK`sMX&x_i62m z3(p@J^Fa3vl5Yb0$3ncipU%u1X!n3V?2GA7^Tk-{I_r5>qD6s%kTGT@ytAz-Em35L z$cnN8y2@P_p}+7umg+CO2CEJpoFPF$cyMrr>C|%f#aE!&sI$u6ooe##yllEuF3cyD zojwc3d(Br|B8Pq3+)wqag%{7h3bPS&llaae?G5}2k$9Xd_5}^E;tLv~``AM?Lc5-Q zLD^~z8Mh@0g64zFb&dhm)BZ<13K{GT^cg)=F&`AUvN)acy{S%b18NPkJ&-rMSx_M5 zK{Ed(9FwD?_a>c7H?GMqbyw5qN`47v(+`ZhC$z}8zT*;E=HJeJS^Lk0=XVan2Nfir z0``3~^+MVsvM%?~FWyMlG!eW}@yv*VE=3z^QBNTYwp&5ykhonz+lih#1TA)|HB4@J zB|1Fy|6kT05t=DYa!Bf-t12IMeGRStL!DEDrT2I>oqb)uXnNa}@O9k;#;(H@_rb8m6OHR<=Zs(ILxLvbNtzrsofJ7uCy6FI1x-$x zcBaupLYG35A$ljjV~E}=>nofk-_62L*C-b*eJ0sav{cyp~T30N~u7B#4QS0k@y@SJrC8hOE$Lfza z(Z4M>xaxg=tM`WTp@_|5vu4~-Ihs)0SkGKc)HXKO*49&MGJH6JWG!sJ2|m9Jq7M95$ROv;a`>XRpgRO*F+Arrz$QIM}ZtYYx#HbHIM$W z`WtSje|2U!R%@?v<+*~HK6^O3BiInh&Ud+8+4+@uPJPEG;o=GV2lDeWdj5_+XB6e0 zw9tf%pJ;_NA>-#p-0(PES@D}`smty4S*-5gZk!1Fu>79f(R00i%UEP+P3(h_X30=HTf^&Ceja~~y0(s6j zd#K9g%8U(lS7&QBi}Tvz-iRZ^7tbl(wslhxA-8^_X13#W^PKO=rxt(y z^PlVP#i?22V}$D>^8XwqTsM#ovq9LEu=h|eVj>?{kK!Of1xZ}9N0xK(+5aPbLGb?| z7RddgW&f3C^#=4PZBr0vi+h>FhbuO1Bwtii8c4kJ-=}i=a1=4r#83WQAk2PN2dwc6#;G6%tc#XE1d_*@d z+&b~~$6SQ>YO?2#5#DpC;&6+Y9}TUP?fKy)_Pm5HWY5d{V9!?&p4caV$RzA}qmEgM*?OPS0 zGHc{S`c=GBxRPgglVVI8fqWsj2}-++_Qqo5voAN-{21x0%l&DfUX zx-Qsqpir7Ex9q%-+vQ?86x(v+Q~EyRnpeW6K1RX&KO65iUvUS@^pj#Jya@(~? zYE981i!}TZvLi6(em!A>ZMpTU*m4^QOKi(QXOXs?T!SrFpzeTO4O@=SLM@#GWMaXV z!Q zEr~YSF+XV$z5>~9JluY8sO+8`&CJH&FPk1d7>JU2ap}_j2`z?0^i;5Cc(f>5R9Yf) zBD$wS$cYg28aLk}^sR%YIn%r7RKcS^Cg^q4G?qp$30*wBAj9QTkl{RcjJ|=+!y!5k zhv-|5s5_1jbWB0V=>8*gR%XPRJ4R2Oq$f_k0y-&c{UYqcH0A7))UsPI#ys>1)$J0= zxbV!yTZiUdq~VG4NQX`E%uPam`ACNEG#wQ33y}lPb=jQEZhUqR|M^2(hJ&>J1y|4X|jWrMQvq-%f9P(ln;-8N=U1>wCqw zKz>cqrg&Via>?ql*%*;#74Y*eS)jMaOo;5!IGs~sq27FaV=OM(g?-e|( zhjfFt6Rw~qfy0|f3iYP(FbQ1>4{KKMNX4-`)S9%!p|i=iLuVUQ&>;R6+SAa^URi8g zkmN6lZ{JA&lNRA71LhJU+#@INIQc~t;wHWV-xKiNOxWHd(PchRq8-_x!oz9$J? zn(s+I#l9yAN#E0x6seYL+i1V@R1{>KI4wN)0Jf-0LFkCc z8Tui$7NTbm)kNi1Dw2t)X2o-yhuy92Mf?dCzMuhB?W)WUE4)%D;}!P%`TSCpC`wKg zswJsM9#K4Ut1~A~>}6d+rJn7#bM{f);Q5k|w11kPo}SmA4Ey`$2Y*N`nNp7)?&&pC z_dAh&^uCGlWb)CgufLj;j|T4>|M=+K!e_Og%xR^>UnV`T#V<|jD4=i71=vKKb7u1x};Q*H-CuyN3$d&E6H~R zp7FmE>j%GJkCWsV3`u^${-OW5SU)!~ZAo_3(xxcZZ@hTP>_lvRj`b&fM39PKF|4@m#<5FV%7v~fDAB*=VcYU&B*5{J( z{s-6G^DE;0wCAUfQn;VpK>PIFml*DU*QX8F*Jl^s0xuBcCHsJyNl)7=;{AK+v~QyG zZ$eg~(#InTx)klOMLoswe)&d@_e*FyecNtz=WddlJ72NflpX{t)krUK?@;Hf^NZ3o z1O5+n92`pAW6##I*va$TMvC~u$#c*A)RYM9EIkSr(EJv@73kl*wKy0JR0ZF_A^#6| z9|@t|<4aoM>=y~~f-d9c8-yP7zZdgAqT>7T@0?K338Dxx0A86UBPpWB%C8agUrXIt zlSa>6j8o@RuZ&)o;MLJ~K0o^u(GN0ZQ&JD*m_PcL{k3BLl%GR-JaTlls@VTlq8Z2j z|61|>(j>9cYoS)vQ`aP1RL1#b++X`6l&n;Nl*sd2k~n{X^F{Ig&2a5dN!2ElR&6qV zIQ!IMIn_+n);3X-Ec89P-aJWXYd!h=Zy>rL0sx;UeE%HnCzw8KgjJ2OY9Wcu(P#MI z+zNuG)uf}-srZm3|tgB@)f2jVlrh`%`72rqWWs?Uz z==8@=+k<3ZmADJsF00oY%x?76ggNk^TOM(ZJc_t~(A(z>x@?_qfK3+hU#V@~s^wp= z|7798|Mp~)iS?$64Y4Ri{Xf!rsFb7rO*h|ieGP@$I?oN=P_bv{)!JHF zEr2Wv63wE31Oex@JPgTd65*C0%me#P=E2)`G?SNMeW<5?XsLstxU(`>RX1(&7w5Wl zu5XG*dJZ2xeA}Jc-3Q3Ykl+4}gZr2I7uv3W^|eX=!u?ef3vcAXrS}i-*Z}Bw0%A4WwRC}+i@7AUl zMFYL>PH)&<-0HTta`Q4vk2jx;g@y(FDsmj8g#xG}$=lIO? ze9Q09-dHDk6+p%#N6JKCa0yjRw4f;nF5k7c^5Ld>^?5hs- zF4X=b-->zUGW?_$2A>x{7)vJldkP$lmrpeb9F=uf#j+SnwxYEHZxWak1Kx=1bgiuwyv2;h`AW$_pGHNdmhFv*_8cJr31L#yQ zafQBmKcIcIUi7BLK0?=U?4!n2_7Sh4?~GI3;iPBQ+EwVdEZ4TI2JIX_m;qBHe8D{fHC07QXRRvVxm;=Kk`jMt3;d;_5$?+?kn$;Zrqz za%(ou`K&pvD*siDZH#ja!%Vj6(=5}~+lyLqEIG7E3ns8h3)aVn;v*H83e zwWB=Ry!fYyduk5-R~*Pk|1->e`ySO|x6;L@`U5NMd>ghx+zO{m5BLj(Kr<-O6)a zwBlHg8ifa*H@-Y`e4p5_={SS_^V%fN;E^`b?`&GJW98bV;jB@;3ta`cP7HZ3@@?3i zj7dxb8A^}3{%v~w#o%+xea0syem(eigKbDH5^@wh z_^<~zi%B-vfzZ@}&5>2G$!nK}%?9-@o*yCK+)m%qrLMut3Jmi%h#nQIpKV$8T}Vb3 zeNGcKN(ZvUmp1x-1shdwKeVCZK9A;AJ@|g#^5_wC;QN>9jTeLJJ;v3Z_JIvF;jXCk zM%je#9Uc4p8NOKhj62|dkYcZAl6$!?iT%D+u+M9khW%E;DL>arwC$t)IwJT6cmT3S z){^Px;{nS|thQt+0gp_71<0OQb8Py>?rr1gHD;y@e!EY|x@PiW9x(la@D0rXF%)P9 zLo4tt*I3#~2-0pXJpmon+`e5Vk->Iu=u>9p;McFOQ13OK*VXaM#9GL>Zd1n z6@_wiv)$i$#Zej^{bs$(L)FH&8;@z*HTQJo=7KtVhC4zt%!?~(NI4D_^v3!kL**n} zO4Yw)v3tzP!D(hp*lB4Z zJzbBZ)OVlP9FA6c+QN;&oC4d~H# zOzfSUs(Q-&pXX|J>z@w$>kd>M@mKkSk)83n9J|?mUG0d^ZVlzT8txh)JG^AH_WhThY-0HTszAA=gG} z4L&OLb&zYDah8D4Oc(IkrKK4|E1GDKjV@eQsR#!lpDR>+$&43$b0}9g7e{v=Ia>8; z^V4k|`RgOzxLbF5%8J7JAtFSMV^?mWe&FvT{;+>TAj21~@V7W3j>M)Jqf$S>T}!k9 zv(HmvC)8SwAMP*faAw&;F-J~SQ&++9us_}z+Z-QA(5H$`MXl}{s-+IEbA{~(bc^xR zS>vDeC+7aFxAEENp*jlCqnCd1UemXT9*8rsOxl~2BPODNg|4zxVR}d?MGv34!$onw1P!rQu_+^ zpV?xxxwNl)QADTBrKma5RorN|Wd)-SSE8;ZCa4)1iu9Jyr^IkUg{vaBt)`iXx!%0^ z^2D8Glm8xd>8Gh14UQM_x*nRh!{_S?(`hkT`ZUq=DB;sY@X@sMB_XD#gi`dZQTJb% zf-J`%rQ~~d(zh}n<6Pw^|4UqzI=Mp5oMx_;gHDA!E&N$hkN zM@?uftDZZl918VOSlsj}tyxzw6IrwyQbn!HPG@_pC+f}jxO^2wL7YvOV@Igag0q=R zXVdBrRRmfcxpX#-eX*AE@LjgdxuPoi|M$|=(Lk-|Sn=L+n=R-*kT_W8%Cp%t{ZT>h zkrcfr`bye!va>>Qhr6b^1N6@Cif)Px^64c{NCiz;4s|<2_C0iZ4+omM`U(pQ{iVLc z#rvA*Lz(YNSH0h#>A9+^-$N5>udN?+Su(TjMf&{Q&-HS#C)$#66+3C)+f5JA8Gj{p zl<0)X84>7h34dp*V*+?AS9~CES>7je4Q2ITIvFqfG}%YIx=H^~+nFQ_z>9=E$)euk7>KGXil}=S@Q-3d^=7wpZ+}nOpp~%P! zx@p_XJIvP;&)sUe(ew;aqnpmfX~Kh@?4i@*gxU$iPJv;Ld!f^$yoTziY6Z!u4RT@u z^;INVNIBR|pQSb1sh&Yb=sE?V8Vebouxc^CPks+P=jc$leP)z8$Qq5spZ=1`?K;q|u| z-_2_(3*VJ#y}T%KSEl9lJTLf2@&2kp|9*dMT`kWG*1GkGHz#7TWLeF}_jeW6JE)UY z%#}FSN%Su2&+jiBDxgn^4TU`!)(kE3m2WJ5?WI5cTZYvfv_{&){v*0^c}`vTP)Tlt z&g{|R@wVJZpv-qY4-dY&ZoSJHxhA)&Fl5QF((qt$Zg9zKN&Cf48CG|o zCaa&`#4$iR!Sd897y6pV7EMgkbyl2PD6PX0KXrBUhawgJ!Q7^hw>UdvB)UG|UEtT9 zt?M$Ow7N-YEhVM(sdML^Nz+-MGk+&`u4W&U*4l~6NpE!^oRPb)pdrVZ?Xu3)3?Ih@s!jl~m*ef4t-pMlDn0hQHC!B@-N*;}Mc-9venyM>N~eq^v85S8Xk?SZsR zZJJP+gjl9ZC?!)%)E$^h;}&?VQfsLh8Bsb>sC%p;tnwrh)?-thisZYYsg0^PjN|`_R=f>8;i|?Gy`HL2#2OlOMeMV>^;!Mhl%4s3w}W?@O?yaRMSkXb())IsK1#IM zjol~C#O}1XwuP>8l$&WGp%g7@)EyVE-)vCNAlAJ}L7Rx0qvDKhAnbE4J!0GNx3D(4 zlPD^BrTj&<#0q_sXtaVh@!l}$EP9SFQ5eoRCbX8lxrxk^pQq|xe}5>`7pw?%I3teg zU7C5BHhS)ycA44hDYa)gZ5c;~JBpheS@v+;?kuZq$|K^$JM%W=^&;z_Y^0#vRh=8n z47E9f*?qc|T-|q9PQDm-X$_hIT4fNeIDZqJd(iy?RVAopVry^X5^GOFOf3neQ%kO0 zm|7`&LOz2IDyT%|+A7YPWh$Ys7kkB4JuT2S&o8_(lXgOnCcNaif|Ci~?sB5^C`Ga` zsIexwGg2U|ypVTez~ZkfZ?lK()w_&8P@V9(bMwZ>T-q?Ji6F(E4N6U{Y;2Dc0Z2{U z9P7i0NsJb>yQ@MiHC>LNeNwj?r4!E^U($~2#S1SU+bjI&DO#+jUAv9;E$Xmgc{3N= zwuFmGh-o3AbXv%@3)4bc1_Si1+zSP~lPv?-ZgLg28@LwJiFFR<8ha^Ek&rU zicqfV<_?@0L8yUZab^m;-PK@i!(_ni)~)v&AD;OA=qcU5@O*y@&r7YK+#UGm>xids zGffL=gSaGmjrnM=dIXL#h?_u%_tBo_p1$ZUPFb~ninJZ- z8%%Ov{HM|M`KHDmy``Bw%u^zKY@_h8ttj^@5kJnP__4d`bTWQicCgj%%QRn>3^&g& zcQ2C&dF<)izIfZyi!XQ!s&jLz3%v4Q?PDBfE*dHvNyeiF29sgt;&z|KnrS|q3`iS$ zYlmur!J47ky209Duy#<(nx3HlF`f>_y*8US9t_6tZ%o8lFeCLjinDf*Rm`zvM2^>{ zVS=c@H7g0CQ>%hniB8=6khS^r8M8~U4Is_N&6GxNt=6o0gd4*%F*xl?rY^+8m)8$x za^gZpBK|73p5v);Ur{hz;tiPtj@h!w`kXwE)@!`gyxn-Kc5Tzm{gkXwvaxic`d|%x zs@PG!(@`DF&2}A+HTiRN-TkV{p|H&niY+c`jkB}HH%Ja3uMfEk-y@5r+jJ}80x@TF z?zU5;m%D7k-qFNFun z0nlX|PQ)-UAMiV39}S2eV*&d0o%COT&Y(}=#7a0p=1YJukV&7>2fUR0*F5{9l%N^~ z)ezLGpym4t{gLEz=nLJeAn+epiO~I5>V-p{_U&ur3 zNzQ`^5$D4caa3uupR+2h%Ev=|)FgPShjw75z_y35Y$Ggllt^B8(sjGIoc|Lf)EW3@HsIx`d z0ZIRyc37leOPm!-4qBK@qW2ezlb6P3^cqUHc<{iB8>go?8c*w+FP7OD#dDK59CFt0 z_h=$yJ9&kMMMsPO&)j>!$8}Zt<9hE+(P*R@P45~>BWcuowdEqovgF>oti+b9WIOeb zLkIzaot}`8MiN580{_s%!U9ma-clO9>F`<$u2S%)M_^ZSVg6 z|IdHRyMO824&U00sxcKBD9(!nX zvXpiPea7x+R8OGiUZej_KNR-V7(q$2^}lpBVe&s5W%LjQ`QGiHT!RK?4Ndh4sHMMML%o zga)F>=v!Jua>6fU5!S0*(@u4D?iq>7R9P_t+&3Mys%REy2GEP9Pdy1qKcFc1{rvPK zN5Xcf>xiX9I=g#vqP&bshfL*$Q3aTA#YcC$Ss>`97-dA@7bW ziwx4d4&ra3IUb_VL-5E-Pn>Y8LY&X2$1}$f#5swUJ5F<==3AEPM#38x4eqF~54HsR zliiVEMWL>*p%}8SoJ^*MK|9=W-jW^hDssm?efA4qIQvW_O!0_7&DAT;K5zVN&->65 zpkYhZx~i72GrFd{rNmw2(QTL1^;7sGoG#8@K1e1~X0UvB`MQp&bMJfjn0~c6XoLcx zxV^}4H~&d%n{s0=Yy}&rhWHtpi*Cw(I$3aoKz5v@U%rPpQ$Sbth+Try{CY)QPxqxK z4QDZUJb%vph{X-h2&RIYQrZEq%T=Z%*?Lk8CCVkMjR9!2+f` z$7iv4vX|2#>;&?sqXMr;pTHUrmW1IXzdV+}a$R3bg|U3A5cjGM_oN3?B}F#fZYy># zPY;nh&};JsYp8HM+#4nC&GD>r>Vtslr?)Dnr7Hb zN69f&=#He^-s*U!SXPxtCQ}Dequq&Qb>@I1#N)ha3)1EU6iZ{o41<2OZU+klkKbNWp=t$EouNa%eW>^27qP+qY8A-5UzN zPJ12*ey;qpbw=eMNd;*xCuls^0h*xEvW_(>0I`R#pXLz}pCHXC`*XRv&w9GPo}S;J zp5H+0W|LSg+tjsfG-9`+cGG(%=*%CE>LVRRepwyY~)MSM$GB(-*srv@b5OK;GaltBXYH%KY+Q zchkz+K%jPIQ`5@&K%jmlY8PJA3Yz|hnpunDrW>#*%qv52kKOKxhjRZy7Qr7a&xKBs z!|13xe~c!qq9qq|E-W0AVb2TdSg^#G`q3)&J@D)pz;5O2)0TfQ@NH5 zcd)-W+rv%5-8WseEb4zyVIHvrh^SJS*UlYLabj>`# zaBX;k_Nwg7j(HfQb7ZSn%a{q&l{)`SaGhy66HH+yI*Fr9!LDAdDD)fRZZ@b1&2bmx zG;t)%^5kC-&u3{9V0C`p?M1SEUf+FwbM_18yE#6qkGtlXF#o~o(_T$yH~J_-dJNOb zhegMz;NCn`aDeVIMi^%eY=;i9E2?N$REaCHbDOZYL?E49@D%E}fUH?W4E1*8e?^(Ujj71s~^G}7etI#chv zWWUIjeea%KT#Kvsn%9Y1Tq|x^b!Wrg-P@|B&V2#-;YPudyjon#MIS({GVDiGFSGgp zqIwxq7Oo_&u3b#M5lCl#la!+HU&?Ds*{Tugt$D$V3+)347Iq_PH5Hi(7_nrtcX?`{ z%u~K-ma8@*`^@W9FN!KnUgmEKN3_I5luB6UwIHQ*2@EoYeh0YS_y#>j^`qpx#Zvm|+DF^W~sHh-u zo6-B_>Kc6Z7ut^tGJ~}`bZxW|-??rs^f1g1@tnJ-TYXa`r_V1*-HK557@z3m4dVas=sPg3Su2*w{e}& z-F8r%SakD3{$Bl>Xa($otS&`Q+W>$LDo1iD64iWoYWM=S6nny-s%D1nf zowr3j1%wlO^LDChJO8Je4+6G%4&Yg-dH^|H{4{DGj`UZ5Bu61HvCUuXDYKWy{gcO8_O3y7%8os3!C ztSI!vLmm=i)wq9GFRhKev>Nv2^e{B8&eLn@@R!bdKJ@2=VT@eUUMt2XkcDs;W-Q#{&Fwo|^ec2tup0Yxh;psfIW6*E@TK_vrf&2&ar&>xMO{dyUbl>G|3kHgU z?_6;t>2SF{8CS*j@grSRkDFgQVYVBmFXLLJ)LY#sC`iy>TSs`CTj*Cd(XS|{Uuh6s zE`BAW5F`ZziAUXod}7@wt*)i%8uK8du4U+2wctyQx(2T%zLmcP5#uJ}9&#edCRI@( zi9%4qBO4)h_%bp#5&kIc_5F8kER7Z0yr&*W{Ykqf6)$wxCGQPtp3=tP4OZWD^Y6`< zHLtd(Yiq<_nn*f3Zy7#b9j_X#+~97GL<8O@Ce1JCpPc%>9@|O|4%FR4pLCP>gJ04n zDqFSD--%T~8M?Vu0RDIsWpN~>uBGVLr^T-?SJ$9HBI;R5>j6HHI&}w}s3J}@(i0fN z`40>6MC{Qla>2-Ln^%okcr^a6zB@K~<0UrlHMga~mzcAtsp1hT%o1qvX+ETN$>!(g zdjxA%bnZ$yN)u&;gKt}Zyed(@qxXs&ceS$fUDM)N%t{e@{=Vm8 zcJoDR1ML{?&CBlFMD<}D-qyYA`nPGY%TZAu$CpYn6(VO-ojEw>5Xh*qkm$V zqF^~E#SFEmYb|uGP0T%e$ACkWPs6HiR}^Xv;cw+PW8L)8jC0&!j@_*0dA0=8E5&xD z4cj4{>9bp$@9cm3s5k0%mhQf_>9^X|skp1CB635}QS1nWsiBBVw6GMC?9s7@TPA)_ zUGJZ484lQdiKHWQbns|-D%BfrFKmvM1d5!RbLt80g^dSjzuHNjQ6FlO_jV!gTgWE} z-#H>tYz=oPYnZr6>lHScheomW>LDtqC|JdQ!O4uemM`VyQ!M2r1=$7*m}MI*U`Cpt zLJj5swlF0xQ<9EE1+OgEyp{Tkknn|3B-!U8er?TYaZ*ihgJ*Qov3sOgc&MQ z$!oy;1r&w+^Ms-jG(INAH>hjKv}&Sjmb9x-_fQS7Sy9bIwJ8cG7W!JUHVK;-aiDyg zw;J4*>iCRcgiW}PYWX`Cr# zYGfHv)rx`?=vNf?6O+%uqcB7~g-<8{jGimqWpe23V$w2?TWB&@ixa!p?&%m?-q7GVWkJ$h!p=$v{p*0QP0;Z39plgm~PL0Z=gSB$t?B9ty{ zem2~O%fN#IC!3ZEJBX48VhI}6g{ zL@%W)5=+@e6;b&rPTJ*)l65&zokEUSPqV<*2P3|a+ad44L$OIwn~2(~DBxIj5~pFW z5UNi`&15Obnf8i;jM0ZqOPa`8p}~CQ<}?2aQ8zMtih4b}i|&=po;Nm$X3v+FZx_v; zwNT%ko4xUwGZgK;m(N(uuonDyV)@WeIrSNBKiqPtHJ*sHMsxk0ud7`>tG~1Mwbo7P z8I!hlV3_8NPFSsG>T7xt&5WJ;hf?onnwJ3W?mppT{s`>^_?Q{rvnCJU6Cr(!5j|Mh zNksugS*0jsbXF2Sf##FrC7Ms#D#*)`_mG#1S;&7+^Jsf4);`+YvZgH_Z(E~X*SjYsG@SUr>QU^O%y7jj-ZNU|)IaGZ)9L1h zhUVtFI{kp$BP^5B^n2m$|3PjhAk}rE8EdT*Pmqt!r>U%fTcqy8&lyk@p8@h&c?LXL zkf1kY=sbo_3m-qfo8$hHYNeTEkH88w0#%yW*W67{W43zKJw$s36*Wi{eg(f7nTL6^ zCN~Rv|K&MB$3Z()SQ2N4!tWu@J$DWv+4R4(4u6pSG=JXs!OiTaX+C;rZ-x1U?hZ#C zZu9c~x2+RaT-(?NrM|+B6S6OVYmK$mH?ebOqN=L|&Y6^hP<1VlvTlTh#+X@W zf^#F9Y28E5p;KXIbqExMgW0CfMn6)0-46X7%dWqE*&DBqCv4u;_mp@;?npG`Jlt?> zd4NExC2c!~T8f_6`d)pN3OsyGTS)~TzG*Hqjy#e~PEJ1TY4$qZy3>76+rFA&S2SHz zz2}lko2GgMw#HV_Nio!Iq;tDThk^F@0R3ucf6x~Sh;CM14P8;tZfuIO5oK2tx|&0u zVC=k|_#(B&CN&2B1c{$ds;fy_nT)fSHb4C(^d{B;sTZBBuHZv~FUOqq#a1uY6=g#y zu3i7#rps3N5+1`_zj2_&{fxFEnXo&nQzrsNfnZ0e)-Jkdo6o-TivH_wKRf-)fBjcI zU{2JpOBI&H%UtngLu;y!r&8ICHM=}*fuJk!{z>ymV=3?VR`LZLBH0VxbY|N8qg|od<*^t;vDx9Mr0N7 zSXy(;LxJX6jE7eIRPgcs71v+C;`(nlUojx~*s^7yu_(vKZ2EORcQDl9)xMHzh;1$d zCx7$%>62O)c?ZszBdy!Y1TV|hZrluB*6(UM>TL-Gok8>c!gKJ|30h5kWcwX9Z1g)5 zWOer!JV(4lT$pXY{u#EPq!zRNp!dmfh?M#jg&c&SqJVS_DJn$Y2$V`xoKna`i;3bY?^pE<1wl}`;TVDCqAM5 zt9eVqfZsu)u&}hgYgvZoW99O8vfHCxk9IwlHSOh2vTGm{?3AV3LTjf_)HlOf&NgA6 zvI!9(l@ubRg^GeVr$|va)7*-3)0+y3C-Co(yd=)DG+;RzA})t$e5D#+Ns@u98^ccI zRSjK&Q3iSTwy+Zy=P6F2oPSKjNCU)L4Lz-&f{Z=CwD`Cu@X9L>js3y=m~rMprQ#}Zxd%NzPf0|bitR;I!DV}~NL>S8ixq`jRF9%y zn|l@IrEfuo7wmKBWR_nfrpCnRi5f-K(Dzk|(U9j{HFg<&nr$gwJink0421)_ZR##A6Q7otBJ(kmwnk}d0b(YhTVmU1-OHS9T@4z|HrYP9tsJekTbe^mx zpU`5mS|voxYDa{1&3eOm*7Ub}$5++d;nQ?BAAgf;KJ>HPf%pYY|BCk7qP+fmWcliK z)uBX9?cHoZez^Zqw3JTjCME#6nMK{NuEI`VqbRE$-(KST?tH#?&FJJU?a3M8uNmg#{ALRan!Kqn zZ?5RhhHr^nM)qX*J~k&O(;FLwIeD;RdxIzCa({YJjm4gum{-2>4c&I`$@q#@BNb)o zmX0H>M>@*Vs`@*^)uJYjueZD+*rusGG95AMF!7mvttmAoMNhy-&u@c0)2b+G!9Ze3 zy9JUTwxi{NpKC>4sJ0l%3q#_No!bmr8@T`(wN&;}>3-!EPt!<8BGEC@)HI5JM-7)a zCeE{oe$>?1*woa}pdS)4i(`%G_gp4y5p+sO6aQe}A=X%{v~t86nex&7nXyK`E@O?5 z?Q*Oo+Yx`{ig(H~$=PdS@y@pIszv|di-|#^1@r|)A-^^G^rZP45r!20CiHPeoGmN- zmhei$vkDFvbn^3WgMTljC>c|ulaAIKGNx1X>q_V|EbvM-PU;iT$?dkGb$4r*=0K@pJ>9NdzVli*+>jbNz>t*u#6R=iDSJ~tDGq~+G3##x=I zEFY?TBgf?=H8UN@hw5SP1zR?H>9Jj`onE*zK3O*kbKQ=(~)OgnVcbou7Q z=CbHKe-W{{Tt8@^E7F##ci2ixz1fDQU`xlG=v*XbPsA@YI``eNcK_6dstJJUVHH|yWFh9@nBqR+%7k*7aY0UdVI_A!5Oi;I}MKA z!MoBU>@;{F*iP$FcABLjd1#asyUQp_#_7oZrPYs&jSO*F&P}ZvS4&*35&NcIU4tIi zq$tQs*l8>;aawbf$?`*7U_39!*o%wlF-I>rs&~WjeaE-Yj_bjv4!**t&U(;4(n_CS z4*~)q-={7q_|!YpJish^PlGBBJfy*XCt+dqxMuXlJHo)^&en7)*Z`kpM}Tz%GrDGJ!^hQAhOn{ zQ|%{v?q)>RBP)(dMAnW=k9JK>H)`*j(vF_W^U*FLx%>YXCaaQmZ@J)BCGjq+s4VSu zMri#nFj*oCze~Uxw6`u2j(;qd$MUwfoi!g8kdyI+V(}j)AFOuy-%U<$miFb8u~~nO z_`{g2H_>i|H4X3F`7v2Z+U1Ph!=9~B6!d0BXl2wjXe$3ZR2F&>V!;Gd1u3B$ylF91 zR?AspN_hG;w1xkMc~&rIXdzVA9<6v%3*@T0& zy)({jNiBA6BR(a^AwCsV6eDZoJquZrQ6s>?Dn((2niSPURJ)>N*Fv1}@{PzzM~BUB zI)UbTQ!RZ>YUH^v6~SxldF#+vKdUQzTmK!aXTobj9XBgPyBbK zNBeZs5S4*Y=$hrdT{&=#_q~(fT@PqY&fkZ9`+pW&Q%UCvpWxW7Rf>WPxv5uO#ThDbHF6~5Y9z%mRY}R1D)zp-2JB3wqQK_{Md2K7 zQWPqO09g4alnL#52YYd&?xjFZQ--~8N?n^w(% z*AzFT?pOGlI<9uZD<&6i<{S$djg}-i> zv5)wlq+f)r9mKVevjeP~K{WT$gXM@`#Y|b)nvl8%FMe22@C>CC1+Nb>clc?@fgVL6 z4vk7^d=Iq^5Iq5gL|#L-)*$gU*Gq4XohHN6Sp~4k&oZFUA%#^*4CjueYx-{4FdM!R zTmEnkU-RL<1EaNfl)l3L(Vutx&84C_`%RWq(DpU2r(km)yk_I@+8ny(A4B~^BNgQ} z71g(~bM$?E`@`tP{@Q=!onL#5D~R7sgeTobxN=~bP?LwTHM{1;*2t@jt&x<4tyx9y zVGU>%aT6U$m>MQ(y`oU31${^Oo|V~wzk;uAqrYPpaT*xbi$mBfreWr<@Ov%*i=}P!4R8tIYVsH<%>dWzS_DmLAZcqVXS{ppjc~0D}f6jj7{;! zCx0jO3wuE~*#nSA0kUa&37Ir1>UE>b5&K0)bJ{zst_a=Dw+AG}7#m4ReG}S*yjDj~ z*DI=?-VV<;*YkiaA;(Eu0$vh%4W~KufA)*O=0e33suNA0a&_g-i?dOCMo!Kgn9ZPs z*GRa{Q2*T^H0?nZo%OS-Q{uPwD$3 znz)ujX>hAPIQ8ZtGek`k?vqX|>(Cw{e1>oIK~G7jC=v-3URHm!KM$Xw4_9oh&C+C{E$}!<+-gO^KT@wKnTvwhwj7V@hVU`))3EXLuo-jY zFAg*Igfbq($m?Y;cs1N~V)-0YMmBvpHPiLC`?Oj!qaQq*Ieqe^mOgEM`IT3+we@Rr zkc<_p*8)aBc?fHY+d`2NADIK6F>ajx&reSN$v*v4J+%?B48~^Q467lJCeCJLJVJ-S z$x}*nY8Jn6-t)CejG{Hbwog`F&(f2%io%M69>CAY3gWmLjSN>&5w>fNU)3w zkJd2*iIEvdCy)Ka%-)$~K*rws7240twDyzruyY+G1Axn*jzc*a0AvPqv-yx2md7tl zqu3e<6Mut(zg6lQ%KFYZmCd0DK@==|<+yi;CA!lPi zngWwC{fFk0{l27^z+0OJS_J4Q=_ssCT}x?PzLwzcPftvceDF|@0RhVRZ}a2Y&zjc8 zoF%c8E4DHxC$`iLxLYGpf2lS-{l||?{=q)|k{&qsB2^C3pP9*5S58&{fAneMEAU5b zarDn)adgrswnN}~mKKM+28$!EM#O0ZFh$_59Kq5=Qdrsb>K-I8P9R7VIfA8$q##XT zS#XAug)p+R*5{%ym4um}cuu*DC*AY;1h6e>@BfvoSLL%DX2``}9-#FddIVmLS$|6FzRlauDrD)xY_@+{mnB zt=7_9+toGLh55d2&ZOhlLg^T&>BC&n#|7zaMr)xZ?mDH@O*;vvlvLpX8Z9X>nXZ!Te^~7{q zhWC$55EfMWt)a&uvX7egsCAEdaVoF1O;I-Dp-w!c6PR{F-X-NhN2Q551h6=JM| zG~1SE=s&uG93j#T`noKg4enh1layF?cDK%1wYQP&Dl%?Q-)d#tp3=&5MTT+?-J8}N z{>=2ruV|cG`_`U)1Xw4J!isl_q}v_!YeuGjCZhabr~PXPOw|>%e`^Jz3Wzo!sz&KI z+X&w@I){Jq8uL$5%s)wie?j#$kg+jE0UKDMC}~k3f-AY%r|v=@X{D8iGb#^RW${uR z{7Oi2wV+%%ye`XQvs{~}+vN<@74!PdZ$5i=eUaVcYYyDLgamzm=i;$zUZ z3eWmu?T4S7{`J9c^9&Kah3%-XhP`-6m~E5LpXNLHEU`YGJgN~dh>IyzFK?vmC@F< zuzp>>!rzmbyP;+Q8~EMlZZS@um^9by99+9*MA>t&e;I4PwBQrOK~zsdl+>Veoe?bT zm6VjFFO;bf$m1(lR5?)Z+hj}Q}6N^vFQW)qfiZq*Ng*n&`L#pEY#EdTjKRb z`XxY46cF95PAOec(3A~DVIJ&?f@iEuQ8F$BEr4Sde6q2v(W=IwZs}4*VXj+g<;z;r zkkahsYNb!3V!dyqPwSb}(rTL}we#%{!D=oe#Od|TI&8byii5uV^yyu}fYTpr@f~bD z-p_suOJ{I3Rvz55=ibVddwMTFbLR5iJu549{qzjQL2vl{^eaaw$1E5s^q;63Npf~c zPHAY|Q@>_!^SAve~Alni~BiriS>-wQzq$+=L`~ z8_f$mh42CCM6-7WGlAF%Q?Sep!5t|xO4L1ADSkyEGa{}i%VtTdYrr5@5|0@d&VDue z3+M_?R9fF84;Vv`Z+*~-h|1hXh`LWx*9E``^yj-beJ5U6=&A{szuEY=mj+_a;y~{e zQqGZhI$&0pVp z;>5k$?Z-*RivCOnx-HcTpAUM&Ar=FFfQzJGlUTJDKXj6z;8l^jhmI7;^pF_0pt^(8 zFsUdD&0V3c<>M^ncL9$891YjTf*mdI$XpTn3yFKc%FN^**RbcJFCwW9T%*2X6;RE5 z8KIy(m+pB-$nS7egw0nP$M^5a`hten*K_sp9WnF&)}8)Xk>efU;*HwGv>DM)opqY; z)yDL?Y}%_=CgU;t3UAC`tZSh}%y1>jD}CeMXqkD>#GXCotCQw;je&z$bKooWZZbHE z36v4C7G$22L9``#ixh<}dp7!2$or5ZkoSS^g{8!I_5;Z~><5yRGv0yk0H65BBo~WI#dO$_2Uziz$&r)Q@B~`+BSYF61pNtPGnkH;(PyUgZnfN_?$X zp4b;>KD+Fa&xdnOogNjOu8cGWV@7Qv9&v2;CBmgPJ(P&siYl`WfpHJ9`q%{Z7CSZe z-kUu7w-m3bpOfJt-y43-QjrG*$;ZC8r89hQl3LvN7N@tc?+ZH`{vQk1l~DH*^c`{H zrR6J^PgT>M1g+6}!Tl!n1a?)cqM&`Set|j&{Czn4+UcE~X_|iy&i1<@!(oAW3Co2K zWl!~N(kD!EpZ#=waaH84A)nn&Q}bH$fqmP`gJD~#zwhM1ZRO_s^^)r1hjJUh{BO+2 zqhmMMT>4_nqn|8Iloab#$#}%x?+N>gbUmDi8?In9>EF|CzGq_HI&B-xh@I9x^=2ZO zVyAV-xlo^@)jyxd4PIsG7lYmbJI(UK`P4mNkV=Uw5-XcfcM`@Ezj&#bW>hq~WrcEug#YJ_3E2o5wt0a>paP)SUZ;#B-A>RZRlvi+W7)f zC~sFN1Jzz8YqRGX&d?0$&(SWqJ5(wT<>}@F`*&r;q_kard^Zl|Vt=I2DR;@V-gjVi z?c3a1adENcuzTu)rkPl?eSd2pR#>8!h$E!dm-c%2v|jFwi_Yoz^%)?wr`S z&wNX1$I^jxx+b2u*5MCD+zDUt!>P{tbfH1IlA#?Ga*XJz1Zd(_^*3la1a^ zg3jG+{;6T#zFn+VbzE_5XHKnhJ7#Vx^XIZ*m;ASRRZ}R`w2JzxqMYC=eOD>uUv;9# zwagRoVYgutX}7WXdt_qsX6@9$bAO?}t4^msMg3RNx+_H*RA;W{ppz_mSYznkQ$U=8 zMWvH=#*rPJcr3Loc@6u`M*Ni8R#c5f?Od)EU8b&absPCC;^T~ctWhHniEC68;y`VR zYNPRt@~)ND#UURDj9pD3J9V=-Tbj3R?;HqGENqp(V%6QYNY-y*PxOa zeyVI}{`-nE-M)yc&|9~C-SWV1wJTC7cX4a^?Lm*rm5o$Vr+2+LT(x`uB@Lf9zFK!< z{pQu?Z#AF(+g!Or^KeZU74b|Y?OrO$nmAIKs#uMKpzU7jMx)Eze) zPVLo0w1@>zi;OnnAMx90+1L8rh&(VPR;*4Om?8#mQ?n8sStF{BDJc zDkQ2zQ6=;~gSf>wd{|`i9nvCuvOuHzG8?@{-N)&KJZa36e5Mh99qk&%sI{rR~`suPK*%XE)@@D7i*)F}03+%&!R zgIAo=9omCquyck8C;JH5IbMnZQ9MLzpxH${gmv!?GjwlBEv|c`o?(96TT(dj;_4pe zH7VvTt*!z4g?fZilV%JYS>MEeSo=fj-Vi;FoMFq#Y*F{5@1H9j^1Fbc9j2LNISW*s z{1(LcrFSJsBRIc`?Sc{d-Vyp<#EJMls4*mKAkM|&&YWlx&N8x2+m}H#5Y}idfkn`h zpG4CGbB|O^wh7S`?E$A;7rq#gdi&@yb+PWx!SyTjF2h zDcPbso}Ky^y=XP92kiHCv>ptSY$KFWwy)q4EkP>+Sz^$73Mg}owH~YwhoazNcPk1V zp`mrcI*{XG`vw%n2x@r`2q=V9|v7IKL zhGxo9A+AEi8Y*(^j$YmX-nh#}cEPmW4m$5Q5-Rf7EUSVk9(Dl{JB}@>DqM57=vB zy@6$6-=(_4e5PrrDH5UoM+bW((!5GvHT5UGciLZHRaH;_>DP^s4B0^E^)kvyG3fjR zZXI4~gLsEE;-ss*cOd_Z6;(`>Ur~OVy;9;RaP@LLRz*xvh{cpEs+_1AMPYR`C`#4` z#91xhh0F-pCX6iPvxZM;g{!BmRqIsFk8>@4Dlfb7Msw%DZGFCQVUc(5-OYR?yBo`H z4i*;{)rOn+NUqtnf4t!tX?20Dt} zr;M1dv@CZN-=w>=zZ}Be+#=$K8gUsp9|I%-e?^=grr!nxKmpNKJ!ZS2pfwdK3h@)a zqVoAJp9bI4Y6Pkn$HdH(t83tXMo}4}>J$ZhQWfnF-k(d=b$Py8HoM$~-D(U@Wc(`r z6*zr|=}oAf20LY@hMQksD=;(Tm_+N$6Bo9<_WtS(qbnl5pq=_oZrwN-!9kk}m$+-9 z$Acw>g%y$C-FTyq8VJ*2`!D91`YqL#2>y=oy@t0miR1RcKsw?vblNg@cdDvBdY~p5 zYYK*JbyU~RW&TlrA0?sSu&vV_w6VOEeBPeWmSLZuFUl5i)&l#nP7BcN!JfoEv6J-T zeS-ONDQfYvwoHvfe1Yr5u~pl5%45(^hz2%q$t#BPxJ2`p%IonI@?Qzu59NKvQp&|LY8uk zxSZ^knJ23G*7~j0c|w);Vtv=)8ehOxT-vaG{XkS4tKpJR;{n>Zg_+2sRh1{TDcap% zhGG1G4JRWlOm%2YG4pj%u z`w?RWovC)RXX*%dg4utW<{rNsvuz`qZ5n9I4n^^)D(|`JUa7i=^E9fceCtMzXX{2% zmUYvko`OGHdg;e|tX0>`+pZ}YK4 zG6QzueH?)dp1XUwW)b%A+HrlGd8l%9cty+?b{2W-wrwDd8K+^axTu;oG6h#EBY&hx zyKn9W{txrho*OWi4~_kVdaDnVCPJk)!yk{^+;sQ_>F|p*1jF|FSiCZ-N^H5&n^H5T-iGYUzDokDj22{oj>eW@uEON_`Yw~141I={PYQP{hONMtV8hx@oMs0n2km}HvXoTu-pGiHc9eFNry4&UAF3pw51`t9px zPqVM(_w&!P5YwMAKhK@qH)<=(>kAEkls0IpGK)!$){9B*4BW4$%t6et(vo*-nXz+E zukI@mXYD>?7wy?}&U3U|bJ3374So?X3aD~UuZjoT6~$+*yvJv)r1H;Nd5zCnN#&ol z@)~9~tKJWryFpQq%Z-YHcVd~MmJzj5QIN?S6}6Gp2Ruqo77Wmg1IL9c{j@cWkgqpaf$MH^Kb=npnMQ zdtER=F2j2kSqIwVi*0gqIMC5QnDIsYmA;cjjnR0h_|8;YHt94d$?*sJRc7}L39wJA zCkqL9HS{}yJf}{y6t7xGc|-ezJl{uLV$b5fJkMf~?y_f*(M6KNX~w}fSXWg=Q1h(PxHTu@wLPSy)W{|p|7N_JsI zStxdN)8G-n09Pxjnkf7|d=K$4miFk+W_`B0XjD^Jov_iDMTv;; zJ6|~Wu^*N%Px})tccA;KlLs<{S_p?@h0damO;5*NPFHove7W^_&t-R=Ndm$!e&WPk zgvq$JI5TGg$21>ST;Db5WBF^ zIo2tpt&Of2#5Y)%&^8cngy%uthmM3iZ5|z5#%--hwA+EfRj;-8%SbFg(3r2CA z>L|@WI~tdJv`$OJUQ~p#c1zvptvCGW+{gYSyE-*DQfVeAqGrwlf#sy?_|^n87G$ATd~{DkH?|at@(&`p$Z?wjsAT7@{dG(@Uoh} z*!=O`p{U&(=sbC3EMvY$PlY0OH`T3p*w}17eAs+Mo6t*}s#CV=R66R|T;AX|f{BE! zI9**Ane@lYr`KuKglqVr(UQaZN?cBfK;?XZbO)ev;Pr45W}sN`2!1k6tUfobE}d2# zxaL&%opj$W?o0U)QTHNr&nNC#u@3oOtlh|r^(yc1dXlT7!1zzuiiZ|@$Qd}ee`aL!NHzp z3{Hf8+0ue<5SJwa$FHz0&|o>@=2O>vbj>N&p^sJ^qjeG4k$9LAy6+bES^Co1NIR7y zag}NmV%>-a5bB0@0b@es8#1(-E9u?RddWxQ0BJTq2FJpmDvyF%*M!Lnc2q2a2MJ?o zE8NX*d42yzpl?P<-k!;!Z_MUP$F|Ny-}tLbuEi1;pquWAiEaRIE~o65g@8A$yAIAc z|4L{zp-wJ*s5m=d33kyHu1Jp&V_sH}MgtVN{KSkHF6}MfZGk zFQ)Fr=$oR%<1)GfO*EtKz)RGiDEL;ns=LgDg-2Z?eSx!4OcoVf7e*FwUMv)}Z6U4{0V4 zT^peFhQ1I3;)I+JTO;ow)(@>ro_`_r6k}`TI15`-qejdp(dBqZ^m;XtaW(QD<7y;@ zsNw+q1#C;n+T1e33pE>IbDa-kBPYZzJGpQ^ox*g8gpUh>*q9&TxiL?6Ub43F&O)s? zM*gt6i1}Xxuo-KPB%EH|g?ZD@2e6sgFfp;=cO}`j-c-6K9Nkmcm`ntV-V|%7j5>^9 zGO52tLJK-O<7>j=%oq{25KayFJ;Eg0i^Lp4$A*>z?NDArKM+}S4{?3gzBxyMpF$K6 zdC^h>=ZpouS3ysg(^Il;X@hz%JR%*6vOLxDG{B0Her{xvB8E(sY(>cG*4fqB-GlQu zD`R(RBJzOAkX|z&^RG7_-hQ}xXn#-d*iiMM9hivso*z3ce7L=R82|ltwR`8f zropCgnEv0oo$l2W&o7FhA@t0jYAY&g=|8cjMkx+ANcmB~%^;um1=>@xpMXv@``azt zj8k1hY_3pIjLnea*%v7(=;l#1GT-kkN3h>nQkLJjMm+^fA-{tFXS4&Y0qsEMQ30zV z-_lL1fh!AHS-+GaB2xRT$k4)3JIzTs4uq$n8l?hDGkEq3UpQ;-%#4lU zm_4$x<47hMZwbZh4e@xSC~JfQp}5`UvztHA%BS4gEh2U|`r2OOP2@9zuDF9TATQH; zXm&26l?ZlrZl-_q({M{$iwG))DB|BbG*e91Qmsg_Pt2r`+uz)KH z4SJ}T$E-CXb744W*VYiSAZo*YBr8wU&Xzi^a&LjKLL9|OqY6o$=Kychp*WhV!(fmkH zR-w8BDdANV{GLHYaps78Z+_;8yvEhWB!xXtr=Dh;O5Q`x8S+%Q-U9xX4q7YFjq`E# zb#z_&HdoMSWVwro1X;0N8Ij_Y=j+Pk0dmOiA{RlPm=HZO-toxmU;l{qg=@{Lx~^y= ztanjq)$r1mlJ98SQ+`jZVOOZ6#9bRH3(@rYeeqQ_Zw)?Rylc%3`Y(TZoj!H$p}X}L zkkV(qtFp;$^AYUWO<54ZLp90Hy2`@3RMhXu>Y<>Ydh-<7%Jgkq(>$eM<;_6Lo(58rNo z=_UQw(>pu&>oNQEi2nBk1-Rj`NBc=C<23w)u?ci!#Mlo;$-0qL4GrCptXLX+-m&!3zk8)b{y@z(Rji5`G&`;#3@a? z?(R&p%fPNnuJ0gpO}aapwAaVuv7(e72nG{`1F@SgQkPAab`PDk3}V?K)V&*mW5pCovaxMRCke-s6~`q%1y{squ&aFuq)7UZmAMARsFh1*ur8s9NGY zydCHa4qw0gjwTw_p(u{j%6rS{yO4PyWg`$D@?IZ3haJSfN$jA!2o6g~r324|*a)B_ zAj&fjP3_)_;Z@5M*es>>TSk|KUej)&Xiaf8IvFl@l(hZ%>{*Gh`5_;PzP6`Id;;T*-Z*?5=N{E-0IJoHA7c5Uvga}_%E$-_r= z!=a7sr9A;W>w3c2Kq^rduZE~CvUo9PX^MgJDn_K0Jz2=mJ0&y0?zxW1b(3^_(7Atsgn6@Q7KOG;2wS2IW=&4oQiuS#KKq zwWrPgwihsO+qYIV*{PE{w3~A6?PkA6`P4#{G=W(~?No!%#i;56bj=@W)`6~x6Bkwx9T)o+eIR+~aSRD3qr4}* zXz*RiYi#*Q3iaU;OOsh42{jIRge7!`^>ak!{Ap_SjZ_r z`3+M_VSo?TS+Z6>l99NW#8j;0MI|WkNt?t1ux>`}#QxdH# z-&{)HC36+iY9vc%IR?@>tL|lqYEhK*-=U_f9FLl=*v~Ro1U8qv$7l^nVP6lZd%$P- zXvWvlvp^hkatKLYga~~iWRNpl;IeSc=@FU3ujY1d&gFMSBlfJXou+p{+jC}mdVJ-x z#;+iSpBlcsgC~0Hnq@&q@Tj+>CUSMiW4EWHzmnVbE9T=R+J3oXo%+F=)#l&t|MhZg zOPsSJ9>B*-#X8pF%}Jqb*ewa!}D>53*i9Em1Wxt_v@dyjM<7XBCAxtXC9dbAzJb zSz4kf-jnhzn7!rd-g2T)iI)F%plUWLY7_l^8^jt|L#uKP-CL{fL1J%L)OKjJv*vTA zJeEisr(HBmRHbDAv{~qYzHjLEUNN~1+t)1h)8u->ZmrN$8@(!2Qs}IVns4qLAF02i zM6<_>JawVhy5GA$7>aF*SCo}cx*Nkuzx$5v4L-pn-8Pb&r$*8-+~IigSFNdigkM zZ5*VvfsDL@f`bJSwKnXEf(*zg%8C+OGC)2D8Bn4|LeiHh3RX?6qH2j+tti-F78X*z z4N`oG8nc9ExmT>h73vzS?bWo486Sz$Vw6_EC_T4UjaiFdM`IY9g}BOI@s>-}2+^TO zNr3K-_A)XcJ$k0HS?}uXkq(UP;_`lWHlT=wUnURnmF2ygyY~)MR}bv%rhltC*8PZ& z`Hxkt9UI)DR9g z3^lE7dffq<^WDBgfX;?MJZf|0Bu2IhXG1(#_+@=?x-^tTYG5*y`&YjYYsA7KaPQ*B zX?>uk6|CSQWM7K)VMP!Mh~L2Fz~5}A&*-RUqt8;)^QdQly$LBQM6>A?^AJ|o!t`v2 zo|PJWnYx3ugX*jN?N*$@s;>+CRQ!*C2!_Ni3+RWG-Q<5lOKA~b|Kyo3p82A&`LV{~ zCnBXlx0=7&{KT#qP=$0b;wU-^h{A2=3t9&MO-^bzx73!~YLe-wb6Z-X6;hdo*rYF( zJ`Iop_{XvJknrDsi}(lcJ-h;l`La(477XgJfg|!-h(<{i4r*aRYepANc^`Niowy^B z==dx>{4q5Oo&?k+;_rdKKQ7*b%0zr^K0iO-k$!%r=KA@`^V3C*$e`4QawjBlI}<{E z?!{x0dc`eQd$boRoPPQxWApRvd37-Uo9bZfn5Pbg2uYSd@Ib$3YV1S96B7^UdVURz zWSBg8GiqR5fsilRA6CqrYtH_ZW&jz%uvPpdPuMQO46v=zudYFtU|Xd>Zv~gA`_fjC zm?w$@wu+s=!FZ|=r2_I3KcJbpgo|NBTXMB9UMpz2bf1jI zpSW~ut`^4C2(kR)kw-WnKRzx3@+ZsUxp@3iPiR&lj6DaZzetV@*cB3!#uy$%R1hx) zjtA$(67tV*R339?SrqcBv?!zo3XTvjh=(|PfaKw)=STAJz4?$ldv-gS4s{^B}eP3YtZ}hZR2)b5g19&0X>G zDWGssO@QBF^GMX? z`>LsMlsweCajMUdUGrx9&kjiTv`0t)cIywf%b;XDlKqsi`E#+0j!K^HYyCmTl})2E zFj>7M{Dz5%H)x+ae{3?7sjbaqZYf^3!Ncdx9|Uf;jC@=*1*d5qg*TBnsuNu<&TE}0 zwaf8+#g8#pS_{6rk90xy4Ts>vke(+SnBh3*;;BHB)&XY8jy_7q117uW*fcx`3 z>%N(*)%9N+pBNXY*CkgSAFm=XvzB)r-_7r{+o=9eSpqDAB#MvF+wLW^Y8 zvsru}tt75O1bh~MtF-dzFQU6R1KDOxfpff`%LT6l{12plDJ4Li}SYruYTDGDo*wG7lCVH6*92ez=|Y8>_( zqDEHEVM5)5Z!AuG*7A+X@0wj>OI~lHzX5+C|3#K=m)A=XDjo5U#Nv68d~&HO<>6wg zXwj0*mC(Aa?$Vzp&sRe0i3x3l>&{s9vl?h!bcycksJjFH+KA>%JH%~D6*XV|EIAUf zIUv*JDV9)AF;-HJlNK*L7xJ2g*#lypEEAe1%qQ3VwR-zrXq7B>7lQv6Q6bCNoL?U6 zKg`dc54C50aKgOhvIDu|Se7n^+F0mq(OUo{Fmy4T7#dw+Ccw|rcaoC!9XbfhYv>@1>}LyA4Qq%sFcFcisO+LL zFcphptL3u2c!VC6>5-BaFv%~Q?;g{PL+1nNeR@LMkwfP}R>-;^e zpIN_tVQFl6(B`RX#pl}vRJNLasQ z=|7qSqhNsI^xTIPx-9yP!)8E)pnx<^?ju$}oJk3O0I|hrMb7>rJ%I|sfB|`B!2wue zj3ISc6-n&6lX9ory$v7Xdh~bo-L%eAR_HQ3eaChz^O(QZzev&XCq!@6(R8Z&s=oWU z5dFLRk7k@jZck-V&4HuG8mFdPjnkLI=VL2aMLm_4P+5$m(822oZ$%M&`pbdGF-W#n zD1FMSC@=jEj*yhAYgUyOWaaQvh>}CIWeU1|URDl#+58Lhga6{^XCri&kXD)d)!ME7 zcMf|9yK46yy}R}m?RBYCAr;iPFJkwUHU=KZ^-Mi$e$f227S{H5ZVB66#h%K--fK4= zuSivmW;PYK1jByMFf9*5(4B` zdDN32Y?-HP|Ar<0bJ{iKR2r|f;(YCRcCR zS~rzRHEplE)ZG}1`%29x$G-YO&t3X0+b44Ke}v-W1*FX}A1=%B0dW+Keodj6e_73o zyrcA6IlBOUQ)zc3)JUt7BzVD3v&@zhd_=(YK=U9ekki@7E!QQwQZ-OT{H!>6!AkWiBBCrMV>hAq0X%lUKkx`M`>YX zR#$Gs!U%YLx=*Z$QGpdeZ+GsNg`5kCwV@7pGjw7}Ev^%z69en5IOpPuLL53DQNw*1 z5Gj`9VFTu)Y!FS9_kark7Kq;rohJ`hGfNk?V!d*k33FEfov6uXt~kc*X0U52*R2~V zD~-5Zz8!aVfVJtOVAGq6-GvTMLr}v~6Rdr7?2+1If1=t_pN=Rm8pMfO7K8h9L56mV+giYljf$`1D=n`u`yQ$sW^U+<8X^L(>_YWMI)2MLa>ikmncUDb3s zPYm9-=%kn*_|&Jgo==uEAIwG~hRq*{EgM*s9@GBwel2>#4RXS?8y1K-B``L@aV ztP)Yfe!kO+B}jEng5>NHYSEjfS{*&+b4zc}akOpsx+VS`PwUI>DK2t3N{Oj4xg!7B z{JQ6P^R6*1IPvqgO)+L`bm`DYh8SBtni+8jF%t9?X@A-}aqgQa$076<^ye+09lk_V zBEh*eNb3VNqtKt1yEE|lEh+2#u23Vut6D`tyIra%*f*$h!tctjaD+VockK`F4Y}II$IMRq+fk>n%8t|A;g_aBsr_NDI3>#^=VQM)fy_L{zq zjyqbLtI2MF?&qcTfu0^K3hpK@A~KDL1Tf!jrTqmIg<5@SMFC9#off!XIlhWUR4WQ6 zS)-yLO;K*4x|G)osHx+)MTE zlEjm%h@&a`mDq(o;uL!du@YV4tl{_%W9r%O0CbP^Y4c~US%9-mK5x~3NULj@i3)lr z=~PgxJA0^dk|X2H_TW%~d$Ao+1X*$R#u93(=G}U2ZCUCA?k|Q~5&_-(zIJ0*$FXucmUmf(QOX#4A`1 z*c%13O4$1jUX>{d_|tO1D@G(hL$UaV&ysJzr%JxzGsi_IEJn8XAamYwo@2GHrCq{HlIEq2>SilN2T*-fbei9P7+We^FP#mx*`qowBF8 zYlc=Xsl~K%-fI?LtJ!5(Q&?SN2gO~tE z!`s!hc3?AS>*;c3dbAmPRGru*ZQWuq&-V# z>Uz@cz-R8Q+9p;hY**Io8uBzd2mN+bqYKcuoTv0~v{V9#{xJf7)x8ppa@JN;%^ z3r=2x<>OT&;M0pL3K^Fn!FT2<=j}5lnLo=43Ki-ZM7p`MdA+)Z$RF3}Y*N=yH3*(+ zc=Pf-)zy;AYON|ZkJGJ(yuWK)zdtt{YQpbgC-IbHA-K4Lf;}LW< zVDJivZWlTXq(!fy;G<;Eq?E0|VlXN&AD4kzJ(g_6XDM6p*^(jhTP)d%j?VnesLNEP zDCkB@6}5D+Gs$Dfo~m;iB7|?nj@(MlX0VWNdE=z{`N+!AwH3{swb{E_Yy5EkC8RYb%k(!+y{7jPM2yey~J_$HuvUvn}c-Us&!VOC<|**_6#aaP>uxgQ|7h;Tg34}#u-)7 z81Su5Jzq!j$C3e&AN~gH9L{U)QrB=!!1v5KFR&QVEsfUlEZ=ihu4pMYSYgT+8~LiG zR#v%UPfyRD6`2hGTlr2_7v`S{KKIPGFKumGy0oozX|#ELXDZdXzPV+6S1Q%D{)Gi5 zLmQa-w)X0DU2|7gb8|-r@m?4CVEai%!(aDS;yWr}N#r6U8iAgm{@7yGBe$FNEj#g4 zRt+jv_Yvi)P!wi``-3h%6SO0Uli)wuLDWl?QYyv&ob8dYM<>X+4&74;hi-Cj=yz|t z{`!q?ob1x{`WVHiUr?C8hq|XeXLcG#nmRXs@X7CmI59-L4fR_$j0CEEO&3rC2=eU5Fwyl6Ea0^n6 zrL0R`2hI_k;Zemj3c9J}1U}0(3H&0T{&CP%6t#v8p^04 zKamb3C!04pq<%i%2-V>l6g{EodR5ir^wpE*6GCq8 zKwhcfV?FI0^g;n2apKSBW5WzSGBuZvd|mR9so8wA_$9U5%30i$oW=EgZo=z>*psb* z-;5Krf#wmmqvB|89SW^!E=Orq=J%D%W9yDLZuXTCTbJ!g6_yqfTRqhwr&Ir#{`*`v zN&VN)et-IP+6YyOeM2Z3-*E4ZSJu1S(UiOPKv#~p(U!>Mx%_ zq(v?%_yO@2F=Wbgx8*)}(PzliBz+4k^|^YivB=7EJ z5Bs%e%_f3PHF>n}eMheGuD#a|i~iuPTgx5A4y^H-u-&2m?9s7zHy->xc1a>7oQcN49Xf23IeVv6NkX$vW)&C(Mw5VxWb!$$Oj(Jo$f9jBgOQGOZ)%~yJr@tHZz@QPbf~Mq@$kt64#|9sVs#%UlUGq*;tb9lU^iiP$aljR6;>2b z_`pyyE}1{q5?^666w`IdV|=cs>#%e2xrshQ*9|L<<9tBJ_I$1P;<&DV=ZxtfSLo)x z^KgFL{Fvtj^Oi9!F{U4X`s=3esVB8xEXeymZXbctYtY)>CFF~n&fx)p-h%Ars@pTq zz-2RJH&b(EH(!^sn<*)~rPYgdD)lv;KFhNapYzW~x%M$*?1ibN)xz(DhqXmfEu{a> zISUt9&4HQqkd#l=lH&8P?eX66d`IeU+DQ*4-gdn!|^s8a~!tgczf)42af4WybFJK;V&ze>@l-C zp5_*-PLe*wnCOMlgcRYVz!V8dnN4gMytma2w-mp*fXNS#J^PagMU9BBC|#XT1LfB)R)otG9{NYU}GzP_%mUf>xP8?Of5 zcoW8f*(t~qaxpfohEvhIBpbB#b?scxC=A+gZ{e{ZNkl>P9zX9?o$aGGqtW(yogzx{ z7`fdtV<3h>$&qlkf&U;+3R1r7`qpqo7*KgpPeoRyW3ckx6A!!9Z@_BTqW zKO$^|)4#Ns7W~Mm)2FU=3!)REw+Q|~8WMk?x7$;gN6Ee2imX=}{oxtwAuIZi#UJ$k zc>F>8eEea={*LBs5FWn_W5L*OWyRAPaja{c$KqKOzt;6Ry4Gb4 zcRLAKL);pMJ<#O(dW4oPC-0K$TEk^IT)-XWnOP2^B5xn+J@Jq`Ja_NCbKNm(*X!3O ztlz(Sv`*{u zIRiUwtCMeoeUv(G93QiEicKD(elmH627JTT+d!Nu%*(KQ|Ru76z2-;fh(6+Um zbSjSd;(a(oLqX%jAV4cx3W_@-1h4OV)2ps<#%7*}ZHp*@%qjTaVNPXX*7O;gQP-yC z>7c!|_npv*^0Z#*N1&($pbIoCJty)`4~`{58TIdQT#o*7{FnAEhOLHpL!iV^)kiGvPWi{ zlUm=z*#5WCseWZEyg`swMGQwWOtNgx&Vp z-Jt9%vIjQB$QzjFw-;Trh&`~ZiuSD)=4p z=zz}j^`fPSS`IZF!B5)b@Ds&OT5+9VC#=#g-gL^F$YarY zq+jiX752HlzZ3n8<+td)N3?|YYC%hgn=EP*jAMsNM*&Lc3l_c1%+uA7ScJ=jE-s#dwehl=g9{Jpx`_AyF`wX5aVC|NJJtpppO-HZH5x~LJ576gbm zvWssz-JD&T!x`ICnWKz#^wb00!$&r>ysgLyiW}Ll`X4-O&<}TR?#|B``L5~kfZ3(o zKvO;W>|M8C?L8A&y?tk6ZF5`KJz@p?+wo&WKC0c@z8d|46OeonhyHLda4qQEiJT?7 zQy#{w-VHkQTl3JaHgwKIkH%kh*k~5E& zqn~*xc)SwFEAgy#_E{SB!)#~z4$O9@Sz?nViJgaX6kf!}c2C1db5SD7ajIsgpd44$ z?&&7V5x&rl2X1_%V%7SM06BUGP9%aHH?_t^3bn{D4eb%ZWRt>WsyAbigS-iI|>!U@sZ&``8 z$Zn%WcH4h0Mr!w;XTBIksq{fH$Of!EmcD+iDQ^eGY5ikH>lCbbsaQjqx5Tz6r!tB} zc?T)t?|>yZ)*X281zNCl)z9DF+gI1$$ zQ72%26Q2&LxJ&6koj`Xs9_!BLXWr4L5(5#8uFXDM^)Xsy^|~%_2gl@!Wk^yoI|}`W ziqZy#=urxPd=Sk2%Uh?K?!Q({DVJBrEV0ccu*5p!<&{MT|I%x4kIl{9iUhE~es2Ad zM^+g-if@N)Zk#DC-?08G(JN-Wj|JWmeaVGMPiQALS!z&&Da>I+eSi_?lsA3a^~E$O z(vDTXM4uwQwK(lKbCh;Go=>|P`yAh^x6}5;YfoI$`kVA-1N}h3Wb`wpJ|&TE2PHH_zWb@wJbI17*?Ix^ER)`ZieR zlVhF`$^o2vLF~R_L8UC4VOvYtVClcBcQNlEr3ZNir3Z<3r(IRGDq3vS+Q(zH_EBn3 z3l)!B&k+FymVm$X&hN9&?Zb1$9!u{e-48hr9`fzMEmsrp-I;3`@4<(mu(v_ zHn!M`O>wr^((E%u@~ z2brwMz7DOif8%qHl?SUc^678@8+WF14-huZqe1rf-iHErM7^*09Au(5=55f_DjXyj z{f(P>{>3-GF3~321j@2*5V29}8k}Lh_-3Dj^v3XZ;lA4XpK@P)j?aBtz{v#JCl~8F zCusMO?H$7SF&2HPg4j9F>#xHSYjtou{1 zJ%t#d4V%H{6d~M7I zDiqh&A4hTSeg2-O&+@6>3{N+)xKbABvMq^`*K>ZJ^klr7xrQw3USNHdh&FP5Q2EM+ z2VZ9xc@ioY9rQkEw2%TPAX>;T%GU1K-);1ecY(8e8UJ|cvB%cP7MVzNY?0^xF|uOQ zb|@pwE$@uEBvy}fH)TQ{sS0e5e$DL{o+38BCd`=?$h5>!Ah)Nt3c060@0Z0gampxY z>rXKX`YeAGI>5^%?$0#nZZ% z0xt#O0o;9?Y>V=WWD_j5ebk=|4L?_zk2X@3TX?MVzQ*38@(RWo6lF$q$RtAz-1?eZ z7BdlW>k}2)ed2+FHAio|G-fG)sjqyVrND*0Joi~=_+h*&-Rhuc7k$}n?FXm`J%9e$0-XN??t#LGHD#+KHRg9Mm8V6 zbt}}awA^)5&4Th4b(UuVji8fvb>K~NbDwf{#}IPozPZuUM|V~jpuGMv?rH$a1EqZ> zz#s|>u8H3I)QRYGl;|kSxxjP;^KHk9qBkA2EJ{n%dc+@)T943k(Du=)uINLy?WJ!~ zk!>+2T)vraib7IaQ;PFg5HtGF>2LYb3eC2Ue74oLh<{3cs9xL0eVBD#MUr6Ds^rNa z7l`e2GG|Ho;W!7{SPVl^NS*71@K8qpT$+?e?%78o+oo>WWbm{bcVreA7kdo{fkEfY z+}y{VEnfOz=SftuU+1j}J5M>!92+`($@2VEmgMc(Cbk{Mg;Yo2cXx%?w*5r(-7x`A zZ56~9=yf|}Y}bwWq8@yAJ?3?fnbou$$S8E%K6>T`&xw3jXnPqkBDHq&aV{U%6oS?| z2J~eS{e;o3`g9-tZL)nt(^_n+1y7auU}i8AO84MMWH!$1q)MI`F5uguGdp17Nm>jr z?4EsJ>lf}@98hqO4*63b26#+h*g1Q8=99~l;Rk6sp;OWGCr(5^W}-=E87zYTh*t{E z-ii4jIVH(ANmp`8p{vg+(`_HEMC6-t#nOC}^i;lCZSV29MXT*2ziziJKQ5%(_HjH1 zF=m6fa@6)x3nG9KlPh_!fx~{k=t-CT}J~f!XL}EW!x^WhkU2 zHcCVGPiw^SGe|-(6B;^k`HpHseBW5v)QSlWuijH$?%osMGZNgPPwv@BKRWUi!HU}v z$H0uY3hSszANe%-iL{iTNQ?YraeOD9w{T42d5hei$XldOd5g4s z-qK;;fxNKawv0~h^Ad1w#eNi5j-$MF0Fy$4zGL0l_ZMwCcJmf90vl$VOG?DNmqrm{8h2S{x0QxSru0HSbPWd z8I7g>h28Jmvmc0TI(E}$Ga#!^=^oo%k)Guy49Pn#0-bg~dDYPI%Xd`9d^~z$mi?lZ z0$nY^LnorYF!*#+v*6SCt4??e@oA1(AmuP)%FP}@DV(tx+#^_9hI_==ygh<-S)`A; zKlcV{y|TSQ?(z4A9{U`|mkaJ9dxTu+?-BHf6iJ*sD<+9w{2nn+8Xt+5#LvFJ{i%C| zc}-adi+RlJv-45wHz^?P{N3!SzgxB#Ba5D&I^kV853}yEs5IBkCGf{#oKPEdKYC&i zeWeaU+(UFBv~ld5!#~hI1fDN)R0#Y_@=Md2D}CfR5-(F_`i9ZJT}vI~^#_Ln5bP-6y~kZWR$812?px)C(%p`IP2NAG zIvblW>vG=j+&V94Cf@@$K~gN3%mbtz-6vP6YF$Mq+fAZl$NsmPh&`$6ch zXsonS0dZr7469J&qCtpY@b)2OMwBG8kGRXnQqwX*sdeRLb#7|=<-Ok5Ql0fp6Rp1j z6;_{d?u?q$vhJ&=hpRVk-c(nV?>Oa=t?B8geAw^3cKY;b@24}~=Y>z1T=(v`&6szm z+!Gsh?*551X)+v3X(BD9iL@5dgySyfxJJZBtKRm}Vpap1G@N7JA<9~MHP>hpW{Jez z%j`%(7fcRXB7`!ke;MkeXQc^sLT#7#2z3s%0;u|^v*wKR<`c23vF(9XSk>Wd0U zphJd0`StnUj_K>K_cl&^`k|OyYVy&$--9&M4at;Io{Vl0{JbCmKiAe$_&M&zx5;X$ zgkGCsD9e05^|nP{x+dG=?#?Jfa4OJ>5>Agj=f~9#+CFM~M8}74^-vN#+%fA-DH`(| zl({z8?9;RebaH;+)x|QyM(@PL3#MnLlC-rhIEu-vwonXSsUbp86PwZ)!O zDS{q``Yc*8=*cN4x9}3dRGO@MbMch4h1f9{lk>h9IXMAIPD$>%$4ya!8V=|a^p?q! zC%qdtFOS8|o4l@=hurs88(EF}0ujnY9yp%B1Er-rP+G}(pqx`0a-E~OH({E%YL=*0@Z7#?W_?4Zr+DiFY88%i8eqweU@O>J+_cM5DS*WV2N z<*`B}V4SzjtTwYYT$S&gj6Ddu8l zZZxxzQSu_^W!paP_!YKA*@j3g(OJEVnq`UUW6X&>$&Wc1vVF8~F_uuRzTENk`gZ&Z zGKR+P?nP^vZ7o|czh%dg(zGMkv6_%J8g}=52m1YRvDAU%*`a|~IggA5(sMF`b)}^h z2%dM!*VR6g^#A!>4;$z$?4B`Le@DI-U%C_Kdr0cBpIi>e-G+vFp|r zR&8j=%(^-dtXp3CsQ1iiuQPC6^lle*xk~f%s)8Be%+TzIFpt;4C;nm3m-%DcVR`u( z<}u}%IzwU2y%bMj?Gu?wTf$GYRfs1j&RvN4C^Dz|E99Z4%uxQ1$pXb}c=|h(DSB;- z^dGVxX%=u1UkC-Fc_#(i=flWuF=X^HuYXfOCq2RG=uW{3a->idgzKj#|PpwJ$ z3C4+P6@_}Tv{Y=&HGAeF#~*DUN-piw&L9W=XEI%pd*v@NiG)D22)s}!wr+hU}L zdcv?`EPdmAPr_34NVd63P`DNpri^i+TwIjZ^nEC+_1RV*TEn(AjCYlaQ=BKu@O0Yd z>HVZOacUld#L>fMJ>HG}`zsve^h%I5xCe$VVo)I&GRs%z5%-elsRU;0y3X*jgf+Zi zIA8017S1>S<^4k-n80!K>hkkk!*X-Vvo_EE+->x(@Q3sCtefV&`Rb$4o;jx548Ilm zZX4=&{uX1JJWEos%~#}ON42(3WWCXtL`a^k-edFu(UsT;s!9BV>T+E;+YU-o##opo z33ChQhjE@6Q^)MD5vg5iTjE=-zr7Bl$QWd-U)(FJ5UUc$TkxDMcr(h5JIxgw#eHTJ z=SMa!lpPcKaq=}92dz34jZ%x!)}(w_!T<+LI?DeuD_YcCvenHHT=iK|0N|% z{J(((05-VyC5-oqv@|m9KpWoot-Dj`inq6*N^eBwa?i5_G4q-}Vap{qvfDu3qlo=Co+z*W3aKrfZ-YVztSSm%4 zy3&dQ5YjDOR`H&!v#nz*JNLIm%JT9{)^6X`cwgYATao|ioHGgsif?*DfvNi;i(dVj zS9Ow)HWW5r(vq3soXVK>x}DTix1u1oJQ&JIPo4P?=pIDAy={i>jPG9wum2-X7S`G; zi}08Apk9N1eE$v`(a%f@g4|M*Esd>5MX|{VwU3;z-?o^CZpgOik0h&3{D4F=(71VATybth&M5?Q9(jWn`xXt4m7@5nJL^tggHx>*38{ZPR z_4eCzDTcZ>u=d7=uC9$eWo11Z1NkOD#|v)ZZL>qAn|EGP9f`PZU145hL3&J-3YTSj z-{7Pw=Y$AmgaT8iy(8^yZSDAn^|%A;aRt_66(r7~l=opy)Nu?!H5WY+pAs+eY9A%u za(e}bCkkHgdfne>5%4jPTybq+78SO4NGdTN+kGmP7J6sCin@eNz=-QNx zMmpJucNckdV*(PatqaMcdR@Fcs(m7lYD?r%ZT&IwXb);Fiabh9V#v0J&{}3&tkO)} z;|au!>GjNoJ&qAtjS*UnV|o&<$MO1CEPa+FD(FxFOE{pH&J#ViI*%oao~0vIKgjw& zCEXRyn@UPtH(Y4+!E=FgXNFJx?#vkop3TR848ik56g<~i!LtnIyUo^>ifo&I2o&TO zl!l;grXHI-=B8ca{00L{yVuLc?!{aj^wuN##}$%@{z>L$t_j+Dq~+rwrM6Gw^6?C; z6VVd{g%<5V_axdoc+7jk+L=U+ z81Y|;F_4@Sl^jpJ4`()W)&zg%YK>}QN~`UgI4M0 zd-OcLR3(l(3+K2#sC8uHm>eO`KAZSm#I}fyiVttRPXI@t-24{3bj8YPV^%IOS1@1T zWooN7{t_$XpbIcFkzRpNdhizSpQb*x^{mg!6})oy60sEEc&(>d2g_1L7#re2VevY9YV#y-c(0byu zE(HBJTgyNP@&?q4MsFi}Ie#e2GY6p7WKLW}V2AUTk$5SdKTM*;uOt{UWGSU(hTh;k z^z%E6#qC$8CL_J&BuThB4-0Dhr8{aSPkEo5zVWoR`wCsSuDXrgm+wlfjw?%e_u?x{ z&g;sO)+=3Eau-)tt^Gy%5~wdvyX~bXmh3g$br?r-p;b3xEpg&#=)8Fm24txAu50gz z{swvcj(YD6-}BDNNN1U4MBBGjPrh@lclU%-c>J;TBjQikh8joY#kG(nSdo$u_@nra zYOIb?!;P8kSb0)4-dW~X$es`3>TKIePPqu~ll8@UQ;B&)nW@&^Ma-biwm5RFwne$L z!?uWkciL7b`8KDQ@jkY`C<*f|m>3Dt(i96YbFgu_`%>MuL%!=l94CLsyK3m@mX5nJ zoSd>yR#tnl_uKN#d#~s#sYuKH;A~+kAm}^_fcRr$K#diIQgoAfLFRg6Imohj!ashHyJ6ha3-hJ#}kMCQInzESp zp3p+xb803_zhok3VzQ;z5E9Aov9`BedP&VBdN1kONDJD=p3c@*wT-!`$8~*RE#!Ju zRiJ+*b<=KqbphIv1=;v}V0LjI3EAEduA?u9R50lV^)hiyCVCnFsF@N9a4gaiXTLs? zatC!NN|V~>d+s&bKJGglCE927Iz^L#OT?sUCk=uWF$fe&q%7sDOPsQR@zYj1g(k^I z{(yT`NogQZSlIOHRdde;Ug+4}>ZUp+!)4EAy;Rg)=6IiV-n9&=dO{hYjQsD%uBihTal`9!7Ap0z6YiUV&L}e49t6WXG%1k6rVFqB| z|BjNKA{#sw6qr(r{+3T|W~GrQ(#xAM3WDD+xBbk$FpPfY%iu_e-7zf!GV4GnKnpvV zWgY%N_&Jr_+0LL_SeQRBzOHWW>A?4!_q9V199;f|tRK)8=KZ5{H?*Oww5-Sv=05R> zxqNWqGhyeO&O1ZRMa59~VU2wF-IK1H-xi7CviVgx(?ezJw{ELNdX^{G9z#)vnNLlM}!E2VoZ?XajafE&Grt;C!My%tb7vfAV{x7*bA~J$35pHl3>W*L%SxqlSm@t zI6sbOuCnJ>;XIM}B=N+_#@d?GU}CX@T@qV!flIx>VI&e8cQI%B~81EJ9 z&3L!$?;tv~ydr+UQ`0j-zvpm2I&nwik?$j;d??f$DZy|fA@?meTp4h~m0?0a$6@+J zpv&}7WNhV%vLBTnbsprtkcx5MW@@o^;Hx$v%msdcxIPmVf~J;SzGPx?ONAa zT->=1MR~i5i@Vl;xAmCwcr>rQzP=s*6mLI_{i_q!;Zc*_+n}qUPp;)w%p9%b8_#K} z!D^mS(R#?$G!HM&s(w44%lf;Q@X5s8OZs#KS-D>M=>SGbEHp!Sb}vSf9G<_~hvPm- zUe0i}LvLViYDD;!#c~_Qb~PXbbcW`x)}LmoE(|p={MPwlVQDD0sC<3%8;jl%xW92j zof~k=hROlC7WI@nzjfBe_O;OZ`>wzKKId~cID6gFnwnr*W~%p)b9mM*9U+fuG@(y*#F$5vH3P-$5?v`PwE>Qi0M zaewQxS8`RU+(0x%S6IB<5V2QFbtZihce}(@wfG*V_xNM7-ad6bp0nDlnay~Ebr^?r zc*l+QJW)=1ly1eDt^C&5%3|;1DTn+u#!fE<4FJT{AE@cKa54y?m+)a zcWAKNZKy{bou2{l4%Aoe?093=+XDAAZfydTUb(F5hOBp%^jAB-cGisLhl80PXIVOOrQ_}HTGLTf)Ul?kYi&m)(y`W=cFsnht8j~=f9GzEW<@IUL!tbNNbD~# z7-H;{Az2CZG0X_gX~vk-?kU-9sXOXi2-#lBkVIBQhU@~3buLhb6uB``)~T`gGTN82 z4)sy}6+ddK$@bBISaxOd(N2sZ^&91hc9|_MJhB3{`&x_(xZc3Y!83v913zrq)*OJ` z*k1~{v9P1m2q|1&Kx(`*XPixLVG(4;tlXgYaa1yc%(%Q3Q0&!#)QVonjFtP39c%GM zm?ww1kR_ieGrchOjQ-0+s8i6Em_8r5%d~xzAf-Zp>MxWIRe#B`*X7_z5!)gnBT;Fx zV@b4zL|$^g(qB|=CNgI|XhvU6#ctc|b&>}z-p5d%Ku%_`zXWlRB6_?ys19pbHUL8n zq0f31>%SCup=oCuCi?KQc$ok~U}&hM)NyhPdv9FfybrrKm z3KUAibwmoo_PQ`yCAP&}X^FAUzewO!`j7tbTaqp3c-_@J15zpl&}XT{@a`H>Mb9PQL>#;W3%O)7?Cs3hVB zo0W-qe*-_GpIuKr)>f>$ac(7L;5D1b$;!g585oG0y~mvsZsYkEUvnac(QW~D%{a>e zto9WtzsGpcciY7`Ip|p!4H34z^eUkx+Lv|1pp)#r%yFf6Gsjh#ZE?K_ZXpyWcI{{7 z;IZ1nYwSIKRu29`^EsmH>b*oQR)47zztn46oKs`AMFdX}h(X&&K1UlRvj}3ZA)bpY z6#j4}gCEQi5-BZGH^S9ph6|}kqtPSFF=CC_b^;5xowO0GA2VR%&Oy{(zQg-q&OdsO z9rlh-0e5IMn-3UWUL|pdHJi6!%t~a;-qLl_Ejj zxrNKTBmGA+Ir2HJ~ zaV^GZ87RPNQ+^acD}0TLR^dL;ozdj2};b{h^+BwX2vnhcZ4;#97u~7PhQ!gHuzpqh|=ep$!sghM@uN$>RMj z_AK&rJ;z8mkpgfRcr|Uz+~@Ut80S0imHPE<_Uoy&=v9=U%WaD&t7!eiNvqD`AD%+H zA7gB3xq^c?&BT$|hG1xu%=w@p;&$El+OYE??CRJ3d{N8$Kes;f%z9*`|ECkvr9+i8 z{Owb-`!mM>K<(}Q27Ow};@*pq7rB;J46(TP;wxm95R2FI#3}yt7I*$u3n<2@Z?(SD z(yUd95~a~42uIHikeK_ewZ>0=XHjGPb5|H!ym!sR4;y>@j_LfSBDKe_-LRp0dI#+B zPR9=LNwvqfV7KWr7Ag9yw_pzRU=~PpIx{+`bXjkExf&bIYErRDVmY{zS($km(EVyx-{wY9;tzNNR$>4fvG(p@kz!A1294;ABr< z5kG``ch`8|p7H)x#!mQbIp#2HV$teaVZN~-rDEPUhJa8=9}$Tx+oCifSQ@n+#m_Y2 zp7TJl2Kou;Gw4%M0Xh&RGpG$+(vmRDfX(w}K6NoqCCxDK;&j~NuWa_} zCcgSnXfE`*5uRBNP3(dHpTCt{R=-@)V9CoN{FaoUHBCl*2})o-Kzk66Bo6%n=z7UK zkw_2CBmjpbr(?RHHA1?K!5L}8)@?P>uT4BMa_qOpA<5@|oa-$qx5s8Xy*D`9#V00l zwo9MRc4@tm*&gp*qa0MdH*zn^hO_s71UUO@bQ@z+lLe(BTim)0x!{wn)iN)n24w%A_AQp>(V zt2$+!C8+|dOe_VhxE3u*ncw-2MNaYLYct|o&Av0qpn$}H>jvS^%VF#uP9Y8nBMkG9MgN&zv>c~0=d3{YXA zW-VH_a8_bedOtNX+61K@S@WRr+iyrSfxzG)ppkKTMMbHB59FXMMBc6&+p4Nihzwr( ztR(oH^XEf@(+|7dXU=qoQnSMKS;Md25MmX<)T(6_s3Q2`hu`uO7z_d_$6+rRGT+h= z;}4YP=pRphQEzq%exITTVcSd0CkyZBe-{xM-3fUtng=x$eG)Yk<{j`QZ1PV%yL6?o zqOhx_#_|UqG+D4Vzp4e{kjNlcGEj?@p#SOITvj!H^?RJNu_|M8Pn%SrP5XNQ!(8RK z!Fr~O+xXVoW*(gJ{>Hh<&BJ(-27=>P;Y~VH-h>floTTuG4$C8`X=v+}e7oMG-_AUM z+Q%wG{CvFWOooHCYcfuBoZs!(J3)epP7 zV(C$f=jJ{Xt05Mv&XU^2G=>}R`SVwMk4${yZ1^GfR?=e{`{^dk3D&~uGrpQcGR3E* zFTtlpTTA)0P*+o(jCz>fBi2`K(fTR~t6=1$i?5IISbV@4siya6z9%9K+V@A)y#j8x zDKUv@bPsZ#rss}Kwxs8#b9(jH=7d1d+p3B;y!HWiBhl^;ploW10Ml8tw~`m!wNS^A9}2d2vP#W-B*AaB9!;tC@VO+}AH(S9T6gX;n9xiet3P;; zIY$;-d#)Qg|Kgi&;Qs8>Cj)QWfl>TGZ1oB1+>r!z?!t9~MKk_MEH|09PxKJIf_jKV zR|%2~YYb+RT4#8yJ5#NFLM`s079#6Weu+7asP*(2y7_r`nl6rZ?#E&oMWa8t5dB!0 z>IY_@KDm7{0#-ObKmYu;m2eIw?>Z3JZ}|5JJXSfo=u0Pcsg}ppr3&M$REl~fyi4!# zc~`Z44*6q~ZP5-gYFnch;$Mpvpt9U-5#GMsRNl^W9Lf6rv%dEni&SK0xkv=PD6{vT zE?&7|YeUySL+d*v+xv%?9Vuh3cc;i5<(|%YxXr9n);Su2uiD!|NqYV;7Kc7Qxn?Ki zsx7iDV&V0+MZAERkw&^xs!^^b$G*KtpVy9iTFpH{Tsv@%BPU)&%-ziR(Z^xk<64~` z@!WEunU{coj?PaC`N)Olp?9aIjjZV2FlT0(*{8d}6CjvwgJd<=7Uz5lU=}G7~en zNG3edy@4b|5MBzANkiq3ynQI2dRAQofygG+&CfDIyWY2}7>+S{d2L6IPY<+>IFETR zI6FX#?uL(GUREFyE+`LXNAhz5f$na%YUZv}&bz&@pY|G!9CZ!ksC)3O<uIPyw?{n^xvoE;~`1(M~HIT1_ zHuXSrnU#uPE%9Xa3*yO`^+#gNh{`}j%yG%BlB(ucHMO;zXU~BfTFTH zuCTkKMlz=2D%m4b@m(Q9uVUL5Kg;wwnPuAIEUUEFGkRu?ZLPr*$;s6>m$_)v7h8}| zi60rjOk_qy&B8(1R-aGn87=ejjw5)Y>=Lx>EC=n)&X41DI5t&S7Msh3230n84cK>l z);NT^3zE+Upfe&V=QDxWFbw_O-#H^^bGnbUl#~Qg3ku6ttXW?(;a_uFi=nccaXH4%yc(2;l7Jb)o?N7P1gT~yjW%Ev^exf1kV?&D>)RfZP%v&hbB1rR7RxQO7}f1;A0qp8`i{7(Ja67aS2k-V`keP=xN^MYeLC=}nO#%s7V?m{{uOv^ z+4&b=I|UBn(=7wL2-he%2yJE}OCtlK;UErr)QZuK>!i0EbWvGa`+WL^?RAtMCD&7} z?W4p@KMq;|^j_u^sj{sqv=|X7zeO%XsfTty?GxWW@ymd;V?i&IvKSOyuwNxo)4eMu zVc$BBpb4CV!u3}?l-bQZUKh_nv`;vQw#Y#$>@$eh*V`5)C)RTC{h~$<4aaQX*i!p@ zVPc4#b$sBGhs}3j!D5e1#gS$3|AnhViU{04A9&9ZBXHjm69M*4ZCN-m-*x`E;<451 z8)}+b>fb0L_ameGN`v{8)$Sd$-t+E0()K8F@e6<6jLNMh8>la_$*81kG%zN`P3yZt+PSsq}l~bM> za*v|&1k1m=ACFP}vZ;-Ep|p%dx$FE_D^{*sS6g1u(SM@ncyD<{NpI;*;oiccP{GZu z8_Uy!>7i6x`qh0Hxu#ekl6+%ZY#f-Ad9AU`GdCQ4H&W0e6*c2WLi^%JLi^%JLi=PS zw8fFAwa=yHjoIDgS2P}vHWc66u^l{?_^?=3=v}{rBwIKSCRW17YeaSs=E=8ztF>NL zVRC*=ihJ)|-pi`4y~`o=CZF-q72R8i8E@$Zc3fFGuoY=he&v=#8@hUXySlo&p$}aR z+?cT?S=iy39h|7oE6d~*@1aFbp&6X$VJ%#_(DsqarM5+WTx(n8*dlKboo~QAZ{R%7 zH=zT@2gFgmDHc8=Y7@-O5%-Zbx8Azu7Vlruf+MdQD<}zu3pTt1sq>tZKm0NhEG#A=aaZPn&^l zMwEM**GfG8xra5{77;DA$`hC2&V?R)i~1a9+iMx^9L9Od!}>Iphnaam5hCAOt5;D^ z=(P7x)+K_*nHQ_*1I~#E4bX%hB0g_mg)mj9+;^?I_10CluKm$hznWjMeED#3egp)o z*|L3GZCAg0+^cp^&bdGR)MukV{PnNh;=-AUsU3L%$VYCZsxp|7my;Pt?d)?Ni(YB6 z%#&_X%QXu-sO<2h8+XrCe0@CK+RScGx&`qK(&B7WdeQe!`{{#2ipf<p_yw-(NJ^IFHOh)8>{K+{`A|= zM<<;iP)l zVso`AZbr|q+Ui}KeC~FdiT&urds?S|Qyvb4XI4zLCn5J_{`)`ZRek;I&iBn;GXvS4 z>plpd8RlI745-e?2a)YFt!yu`B8rKp!}CI9Z)Or{x2<;Esa7@SwdXoV4`?7hV8oO3 zPU1k_WFOk9ijDU++T0+rEVnt+Y;kIiC?cL*4Ke?5dSbr`g(@EipZ$UYvBpv zJI;tL@qH35Mfo;S7r2=DD_J_-e~DFL{oPWt_fsg)`p@2bCYZ0}l$@0!npS0?aaX(jSt?rGA`JuQCsl3wM- zvU^FNa+k$+FS&}`x6MAi4Xs|=B1&U9@RGaOVrs*Z{P@K1;SH^EIz#`%qBH#T$)}^A zaH@ao78K4Ln7T9xu^&7C&Ek=j8=K-4hmn22>MN_jJ`C*-23{YN8}_HLVgvWT%}Hp# z+0vdgme$3|4RUQF<)!aJl$WbW`7!&O%mgX0sRV+CUqZg%9{Pc+@qrd#o zf4UikGnY^8OgboEeg%pJ$B8^iYUeV4<~U+s$>;wx*)vDMvBerQ3d-uf$y_YbtFkSn z6z!vwBK}yT;PdpyLaZM6JQ1}4dzIQ=Bzl*)&PL%t^A(DVe|G=n*!NSKNEfam*3@JEwX~5gI#THU0toM7>9TpOslaDk}osg zLj`!XAu*BlF znff>2zd2`bQtM2^%)Lm^{K1*0X1p)LJcId29rrHqjdDmG%+E+{jQOHP$6c00$JM@g z9asC}bzJQe9ameT<7!KETy6D&;u3!}gm)3W*Uz9qy>}FIle3#r33H-|-n-t+#zoQe zqPM(5vVoj$zdZLt{aQrP2~ z4X#BGDq^51_|_`3FZpOnjqPI<5w&+Q-=Ek4R0b}x*HM!YTVS^BW9B^ipUKl1XIE)k zzE24A%E}e>3Ah#wq;ZPA*aGuo1)1HN7^Zs3dp3wA@Z+?_46BnB(Ei;(r`?y(} z<}RbMx}P~0{kNaZ;KL1FW&^u0{-r=7+KnBMxoX5075=I7=u(DxB7MxEr*vUy zHaZR~;5-_g{o)JJtDMa<(Zfa~6>lv)BMx>+(-;1MCI&5#5nd#p;#MNL8`riLVT4 zqt~fj(2roQv*$Rso3X+=!LyhPVF~M>QZfdRn1nt06xV%GChkC7I8Eq%vEaIM&$RE8O}=NZQuZx5snwh1G{ z+7?OXbZjJy=XFyus~|Y!kfQ@NM4Zb`_j$wPym+}Y5WV@sA9mV4lvBQ?L2QGKGh-9( z9UQpV?8tV%v&fj8f7=14*Sr2VJ(E9a%T7fQY(Y_FFta!{G~pb7V&?4m?|tr*+2kRq z7*mN+4jSItX>5aBxq=@wTl|2wL2dcA!A9FhO+X^(M2iwMRImibhv~hH4-nr6AX|`6VzL}(FMRF1A0}nHp8;EmdD;Ecdm?b{ z%ntZq%;PI}MWa8O`RDU5zWTVa3o6YrFz4E#1yc4Qaw7NuawnTr5RVUZ;yURi>Z$mE z_WAe#tGUW`w9n>Xp5@?gE52H!ZAD?24O*_FUy9fYi)|mP-0ScTdi2m>Qo?&Kterf1P>i{PWcQg-1($?^5u< zWyU6`Sq@X+4JKI*{r#QUnxv2Vh4K{I`Newg?_+vh{640AvX5y?;^?(Si*>F270Q~! zwnZE;$-0+WXBEwPRl1$n9%q+&!p^^O@bJdAw^d1Z zDTw)&Os76wH`%^Tadh1Ty6#Be)kXHYc)IHIgs$2mUEA#SM5+W0L}Uc`=r+vnZ5Kt) zi%{GRjS<|JoW^ArrMY*_&AlEJ-!-*iKE>}k|4LML_pM)z{`y}r2IQ|2b52YCAo5tz z;?4L-W_X23CZ%=Wj@f1VXuHwb-GxyYm^TV~Z~Q1|pNxXGI11JFxy)^=s318DQ9~5uC)b{1&RF$| z)a$94XWJ`C%Ocw%wIwGF^-A@8CjKh+8v4Gegc7Hf$0-AK#=^yNBmVpOmcJ{W zf1i_m%kkq*|E6~ zKqDZAEE)kWcr#U62hI78JN5 zqo1B*)GVW!C1ze$to$PFSnc+=C}}j|HyCq33|j9O40=&SU*=n!ngx0;O2=_ha9PX< zn13@C==9WONs!FX6h^OcHqQL}`P(Nx^GG;Q7QNDaRB7qk0-5>oTc9O(by}h6{~hmr zsjUlnU+Q&=8cXIzc@kv-)x0PRh;2zVuU7ku$t;BWT#jNZMxY0?mE%5y<3Su#2gr*% z<|vJze4jTYcP`$mESe_tNL&tGP7!`Kgl>;mFqP;IrGV& zSK<7S^bcAamejANWstfrxq(RbS`m(MnIWu0u?G5*J$ZxlkvFJh@AC$g?5pi{ltd*) zU1HJc1E|j+;^6ZE?l!86`F1Nx`N=JU&Z3+FyuhdFkP-E15%g|YjGTrsWO%d*{@D9$ z;59G>ZcReZhx4O9dw%9?!RUXuRp(#4<`^A{eVR&rYgz`MiE#*#{80sYf#i>jd$Ha@ z&_^YI?eisn?)!2#_kET8x$lc+s*-=by)K!xP@h3mnzK}_g<>CU!;Ixva<9_;pPImY ztKci4wzUd+(IqLK4!hu&5EJKwcDs|1uQn#3`8)Hy)GyC`F&I7Xrk;O(%Q$rd@?^0M zRze16-X6|kVhOC+l>!go{&_rkh3%tfvhw5=_|D~K-|~5~-kXdk>pAXeRrZNQ92;$m z8t*F5QaFJ`LXCmOtj@REUbWiDw~O(FMHPm)dA-P9cVgu5hL*SGJFfT<{%YW%L)03a zpWHk#p_^Yai{SgueCpwU3ByqixaZC%6uyM~Fx)h5wJllwP7>i`fAFWp3`FhaPYa zJd(T62GBNh_o?qc4&S$%rmma9*HNEUyqoeFD|Zkb66vgFfpnG%6iMVK-{Mqc`{K1G zy-u_yZ3!lzEn)&y_HNDAMVvsdV4e=5>CDqXc}@G{<+XV1fRO@mYJp=mvPH4*t@p3b zFG9Y@%}<=5t>CS1ott~B)1qkjw`Qh*hNq{y#g&z*fco67KIc>3OFK^77@c)ePelJ} z;^_}^4--t_T4T4{oU+%{Alixd79ZiANqmI0&!=HAs)vd%aWbq{&yji^_R4tg;2pMi z2j#opLFTYygq)@oVkMPUR~AV6c#+SgPc8ZRtP%`K?idw8<9 zYq;p5kb-_hvdz5-8pa;1Wj8Gd%)Bx+EiVkz2Bg35{4>VDUs@)f!=+_QdJgXxIdM(& z#~(bAsLwV5Ibm#<$;Sw)lw!q6ekJZ$vf6WPpX#xGEJC(DCmO8Yt^8T6463!V=C9)F zwf0Wc;>ZQ`e&qr&?RMTYPS9?xYz7Ut_f%H_$vk>HeOtFZ^OsJ>E!SQ5y4N|qqT{9p z+>)BA)SM#Y*4jLKpQyM;r*ED9bb^j6{+f(H>4!`}35>Eo{c%!&k%*_Hk7}jbK7R(6 z+P-9azdl3uer-{r8UT%I&I#|Wwa*aWHoeZzXI%weKs}m1n|e0hXOkHkwSRC)DZ!Y? z3@zi$WWN4ZI=*78D8DF>TTr=q$M%}8e&^}yt~+(=r1P+9aMxj`PEQ>K#)x`c#W3%L zae$e+;Rs_dUF4b;>Px(+s?&ScWqeScW6O zF2q{P>{vmJBz?!2`7X?vVNeC4eHY(W zZ!!(>+qe&<;MdFM$-VqG>0A8U)?`$;^=AY_2>C2#0VJ^euV;TRwv^?n@VpG&sJ?P$G&k@UN zwJl~BS#f1#OCWuH#@M=&np#*ItQ566^6(pTt~; z>d)M0d$}VDHJF{Ob!lpt{8Nl=s`K+tC0R3ZnWz3~a^+#C>_qFKA}pJgH+xS^{B*~= z$9t$BbM0IP9>KXVY-|gpi0H->>*Qr;JE35>t;qXr#ireddJD_ab3Q(~_OR1> zqW4e*2)5R{H@|QBn!3D_`kJem891vVKl|>Ao|dYNKtW}NtS9E}A`Kb0z?>hXqF87$ z7FcLFuf%GzI2Gmmg{Vl*BUh5s(iS7xd%32Dm!3rzO5K%YMnxxD)=dl#PpoUvzqTsf z7r5%`PP88?2f>EC=epN-Mk1Z-yL;AkMIv46dRiMAT3e-_kG}?6K`o*&q!q`Vyr(wF zjFY~_X(i_`L@UlXxsqAVW03`*llTRQ*D8JAfp1}7rwxd8n-u@zvHH_2ItLkSP{hK& zLj%n#VD>J7=DNuAyW&*ljnONw&p7q-Pk;L9$z_L~Y7nmk#9Mav$#r=-r%q+(uRHn0 zqgbDVuunYzeX9w0JuR@5=2;Pf^0d@CB==C6O8eqvD(zF5inyxw`Ls~!DvYnEUSDLd zVGcUVTq?P?+B3w$B?1dcKxKCV3F4A_pj6Is=%pf(jl|M>{MzaEz7cjt?(NvqB(=+% zFGKC}Cj(z>yp*En51<;k`*uvO3Qt|*rUwHhrdoM8Gc@~JNNrb7Kj?kwwAV#1Qm(yq z(CHrreHdXa(mW%q8K0Aa9*I>Gn}N27UuW8LK7z{lX}O-7xZ6JeH zYB86@M#yLvMV}aBEzeAhv6epS9R2nR`jru{CAJ00mRSH$1}cGss=`v-1)0SqH@>XL zZV)ukV9JMoCh%0ndeYN-(iuYFx-<5^uFHPK;K}^xA6R1V%T8{fD8Df)Bb*sLxecW4 znHo6K5I(-y4ZS?;ebW6fQephXo5GlbTWy@AWFMo4KPBJ!(G`OCbM6tR#x28&(q#Ln9f@sG(LlujYwa~0y$F7};~ZBCC>a+;8I;(- z<;1AXJY~tIc|>+UFn;T;Q z3TWw@-cVrbojWJjho??EDD7NckXs%MWu&LhTn&Q0E|#~K^^;bZHQZ))hc>(+eZCvP zeZ)6Aehq71{2JE2_%*D3{v4DwOsQ4R$x7B%;z~}`o)%lRtQ+Hmol);gShDZzxx6)Q z$({>*yLb<$*ngin^QL`I zTe4QQ6~9)sFLAAEZ~R)-KA%p>*DCY!i1trJu-mp&=kB@Kby)(E#Y*kexv%wC%T(KACeR1-h191;g{Xp}OpV5?!NThk$t^}Gt*mcl*?a0BE zb#KdZg5{yCobE`pV#Ch8?GY5%bMHoZulhi7esfkvPI~IewHSw%sm>$y;p3~_H1F+s zog*vjiz{oZk7sq1mPc~#sO)Jh4WU|b#n;{IF#@TW<5HKh(O5iorTjfch#4waLxUMA z2IEFZTQWl0iXS2EOB^BXjUOTHyU+-=+jk(YoC!X;41AK27lYV))*8OeCS~+T%ztajc@q|;+#uU4&qz*yC$X!Ed0fD!plz4H}sFzozm^tX7^!`{8#LxEkWXnk_URB!kc-t@q1)N#^g zX1w3wb`_j-CH1jeW-zAv?s_j{N z4QM7Uy@Lp~L=n?VP$Er$8RFQELJVDFCTAm571l)v>qB%W(&GM7@HLbT61eS7@1dX1 zc_qK+7dpQr$YxLm@8&h$4<4UhbCTajTt)CUjz@jUZ5R=LAvIinp`d4pUnqUazA$3% zm_H(%yZSU{ksvMPIf;0iGyfZ%7>HD2bJZ^RPVXb$TQG)y{ohDxK8Mm7&WnxaTgOg} zMxVX^?UaTC1v)29B4R3{)6^p{A58r#yG{^CbYD;~MeH;D8N#|2l4Y>kp5?3{ zH3ea!myF_VnDS;Sa9%9@_90S;6!>}c_lJ{y_^Xlf{p)MJZyoyD+Q}!W`X6>`Pjp4! zcyJr>He|0rY=Erya;%3|lS`H>f|ijK%-TXj0cvMl?b1rN7PxxkY#y#Hu&n|-OC#MI zZ7*eM@@38mz0aQ$nzgvzo};eMIuU}qEm$>y7?C1%Kp;Vrx=4wk%!0M^s#vb~mxT?U z_TC$Iev9bFivf^d?2pl>6k6X0WBj5oMxDL{>PTxb z>d0AAhkQd?{;W`|1NnxWEy3XQ9I+TuQ?8_+Ws_~0jFt0OiSm_TETa|D|5Z~c zvl!e0QhARGjl8S-uh`mk7b+{HmxZ#j+KWA}V%veEy~PzM@AkVwL%YHgE#BaP$;kuX z$*k!Ztcg^n=cFCZ?5rry&$^|&y{E# zqR`%3h5X0ngkE%J0ST8XWJ(@qS!&xxMOgJn;aYGfzHT0sg7F8FH^B z&BB%zY6#ghY|z+fnfAxbma$*yI(aeV%7gh9K-Pis{?@WLrv|2LTk-#I%}*~X?#jEO z?qGX*YA9HoyT9#ZbGSS`J>Y(D?h~KD@R~~Yc|BvRYUZ8|{GfU7zTNJPb^G$e6Wu*8 zABlG5Hg^qF)i>mnX78z3)q#VutP|nx!lGcoBy7m34k|)Vc8+BuD`s}X%X!C~UwC)K zYTBoxklMAUQR5|K=EH^KMYG@O&JrG*o4;rS-bOw#WhLNg(lGyhAZ<#)!6`lgP6w94o$EXfd+bs=^LvTwWM* zkg&2?3B7;#zdbJ;_5KATbmxHwZn@| zBhy}*`Nn^a38e^kP8X+J#Vg4bs#*pkS3VAg$exTXJ^iQO-hXS z9PK}ohZ5t>yZ2n`UNv&0!!jHYqbN|Ig~fmEgy4CVhWW+1qEbVg`&x&waMK@(Uy*{g zXimPzN}BCcX@PjRUdP=q*S08WbFcC%!xUmhP(Fi&AogS;*NS^Dg&QiaDYq;5j+6y=AW>1$#Q%$W8DA%S$47R=)zbA232rtf{NN{ZbG7gV z&Pvw`x_iCv1`68_R)(*D@|k<3*XM3B^rMY{b-`I(UNT$_;=36&$|~#yR?Z697VB=Y zUb>v~>!qtCo^8)jp4AFm)PD3HN(?==)dL#V8m?P!`@|zaucxh(mDlAL+i<=3{;+zn z^s(l;LB@z!8(Wj1nJGyJs$$M1rQ|ij28|7KDC~SQ`kN!e&jx->ZsG~_T!cn7 z&ZZbDQ*uf(`w%_&wJu_gJx^^&d}#`7AIGW0wuskc;a<_?DLd%1DLb(0A^j)C({~Va zc@R%z-Udo&dL^q3w%Qi$v|YAE%Tc#&b)z+GTM0SbWG*xRsL3#j5sA&?q{CqAc()kZ z@7>+l6?F3p^ZUlv);aGnHM^q=M&r?mH`E_qeI@803^hkef=KM1=C1!vN!Wd+eQ!nh za?J9S3GY&uHj^!}IBek&eWq3=xddZ*BUp#UhW@mo20#@`9_h9>9W)9V8fDo&R#D8e ztvo|@wa1V*$nz3;gY+qHke2cWX(jRo>7xyRo;9&t2RLFBhg3sJ!Z4DPcZe*+k-FSF z{$__3kagY{eQy37pECuyzp-s9JKZgp!oWMdZv^t24_25No^_?S++A`02lN{8=}K+*F+JEB(~bn-j!o(UF5aAo+?K_U}qK%{4# z+wnYF%Fy^VnprzLR%d(1-+DirPj(j7b`EJN=2O+1y?;3T!{t+%PGif#QbYKRE4{s_ zfBx+iy>v}6w3pad;V(NeNQ+#Ad_!8y-pxD%lKWu3`ui1;^&YNo`hkjf zfgJ04Z?;eIxhm?i#C}a92Jj|$ZVbU2T2KoaYZp+q@f@|-wi|ratECL`>wXs4_44#Q z__Fxkd;77`KeqDNv3s4bSiBc2OzL=kAGk@m7Mdm|PYZA!@r9hxXFq zB>GJ|s1uLHsDAUuqP>C{t8UZ8Kq{3sp{oLZ!4{JQ{iHP}a6_!HaSZ&O{LVt`*SqiG zhkrf#?K0rMw>3_T#^Jx-$7p45f)0d z;unpy4oc}3kc2+M{8{5TaKkq)2S9w~w-yqI`0%A4_`o6%@#ohHeFU@P92~* zV+=iQ32A1nQR)-R8a)T{qJA<&wVHj!g>lHI7BDot(VZxodHx?}4l}tAj!CW7=@& zqfa@n2)UU4cz#WqNG{(bTo|rlL$GUp!|R4!Gx`#3nm3}Hu9!5%oSAP5L6hI8eXtm- z-~`@?+SMOtAuIxBExM=95^Aj4r&Z?hzVo@IRC_K2YghnVzs4(ZubzvZ|7d~{F#7Fj z@4L?B3v7Tzki|~@Km7)gn;Gwz>pPs&m}UVyR3$(&4?^&>@KNrakKW;0MLvg^W+9w!<-}{|?7o zYY@wrOG{BETp9QEdM%}GM%s$>CiW@0kL$YBK9iOPYJo$B-)dAD3G~4mQ#_p1JqA{9(z)ADo_r1=`zTSlN zcy3mHQLQg z7i1#WCS2rD+rPp;TuJZCK4jP+*guTO37&I3dhi6ZbRA0}#uJQ&&yM;VO%37&{wo0R zSNMS6$=BE~+ShFFv%fa{hZ85@NKJ{% zv{=8rJy4jE;mg*%`R#HIqPl%;;aypsLkp_13$rV;JlPf<4P~jmKuM{p7$KNRJT2rF zu3Y=C_79XB{{ScjmR#BybPBoWP_!?AeIwKrm4n^cV*Sc_=RHwSM1G~fy1O?$X@vt{cp#fnb6>iYZ_sv9Q`t!qL{+ zT%D!n*$-0`EW2cXWddPehzOaj-?({$b*c`9B`9@|hJS9|Mv>{aeqPO{c-cA~r@2=p zCTmzptyY}leF+Z{te~;-NnRUqlFP`2$P9XhPxr`^9Favl4=sYb`sA27Sf>MK1kP1t zMu^2^xu)IB!FE_pXAtZO?F47+GO1;Qtbh5gW;&zdS8k261VusBw>oU^pb+DJYmMFS zS5Jsl*@g1sG2p#n_;B^E=L-GSeGOZSv?*@JZhODww?n=>iG)=?_&Sq_9;MzV&L(uV zL);3e1`<*t&2dCOqMQ(+#3RI_u!T9*%)wGOgWeu=EbBnWnR>3k%)ygVVn*=RRhkjx zr8+ZmvjY(2gm`V_AV?28Z^h5)VaOdT$eL{JAoH<9q?ZM|)ni1YvEVzX4az^UkNGm2 z5sgY@S~Y4fum)r%p+R`)qk8k zGjlXf%@y69?{oyY?{N5!R0?#&-p01c=}7bg_H~)J+Yjz|%~+b^hGRX`!<8?TMm)3|y3(gQXf z3eZuGI6h#=gS8104rc?d5@;OV&lpxWo=c=($U86J%t_r1WQxc-L==LL@l)VqkjQu> z(h(}d%Ul&?Xng|W42<8qnBLp!wx3t|_G{Voo42g5$;nTq{*ObFF8&%0E2Emo&lMf8Svf3Dqv9n+X_gx(+fh2LMQ&A2}BL|PU5{xau%f0^U=ml58- z#C!&Lj<<>peJ@cy{Ik=+z|8_7ZZjnu?wOd#mntkzkMBWe;=~l`-&~>l=iVE>K=&o) z5-b`Pa?UlAL~ski0y!#t%C$wDax#)rj`<-xtdY8^taB^l<AysxAvwFShnlsf z5B|m{SFPvdN~ZgKawXH7vL6rf0nfP^8mRQhbKX9-GRJ*vWdyqk_7AT|m3Ev`oXv() ziZdy_r&PS11?XtKi)&KPY;t#(QS^Q_9Q;+CFNf)|1qvZQ=wgSZc}Q zic_bT(n={z53=~Q@G_OB&z%}%Za>-$)(&c-up}PPiqVdC)m-hP1YhFX)5YX19MBpp z`h;}Q8zj&;wjZs`dHJ%;dHIseF<+7q^CcO9FIAgwflS_OM!nPVXH)Yis?M~|o|=MV z5B2Tz){FZ?ms4e$>KK_GoKY;Cy3XbeE?iRKEfv?dRd=0z$J!`+l6}0zgwrmn&<7g; zWDD*C(-o%=jLdl*??d@&!AI`^F zB<~CWD+vD40<*c`IYG0)EaQl+Nj>26}`3kd|)6z225)Y)zP-lfg_T|axNme4s zgwG$ei%FS&QYm#I)7fm2pSZU%cu$*-(FA{E38K-F78pV@VhG8|3n7_{4s~HWI?5C?k_=72UmV$7^2nyTur$EAz7xfYXZ_` zhydAJW337lB+U%eZXVvz@}TcP`bH~rZCYOQX3`N)n3&M*bW;nviubBZtwL%Ho0>_f z_UXAl422%anPDZ`kBr;5SUB*Wf>Zb`M?a%34!F8yWc2t*_fh2*|FXNM`z9-*hm40nk48b`?C=zUK}V zJf~j6{Yo#~zZVKU1i0T7dPz-&M-SRJzeWG7N~Ku)cG~R*m^wbY)}TJolR+UQY00&phI{e}JDkFL=_yo#>H{}F9l^1UC81NP+YuO;)oI%+Sq=GsgB>RZpo zWi1*Nwq`0f4Bytd|Gj#@dee)Fn?s@NfQoBE50kCx0j0j3Kw9c-@;?cW=KeryR2|_V zUWXuLxJzFjrf(T}>09Qeqi>4MBDjc`>HT^Ft<-caXIuq6DL6u04syuwc|!m3`T-rK z+$8y3gM`63nv=~nb8`t(;6xl(z}HKTQBDTUW8W;JYjoIXq3bnty#|urRM-nl;nhNo zB)GLA4hkyO0*6lg?d9{jxfV+|A^5pI;W`_ZBtZ-fwr0{WYqikaeRW zg7EHRkLbQaIAcaNEhLe&#%IjqL(6yW>Ng6HhyXSm#u2T-C z-g&BXr#0^ffdVRlS-ok;$)1zE<#`}rf@-|12GhHGSS8vwTJ2O0vpgxypO!?2IS!RT znw9wF(93Fa@}&#U_N#kwptx`@rt=bh9`*!(Mc2KR4}UD0cJ!2o85fUOaXEG z;Ow1?>n_TXy5(Vx`O2!==EjE0xNi9!Lnjv` z<&>0L7l-WMSPSh5rQT*4Ypa8g6$$GSHful9I(oZ7y(88o40@zn88JR&Hd>^<2LtIX^w!UXy#9i>i8vhoB66DJY$Pjap|()C8V1|~Ms_2%hL2f@TtnR@jN z^(IlTC-SVA3O&8meGPd>GSW|NXrlkUDr-g{zb)%PU~rG=?UsmX~SZ(dfA z;!8`fwZ0U3LA`5VqSULJr>%1E*G9Cwka8AL?4|a484t917envC5%e?4%EEM{#M%R(H)jefpJ*(T= zSNE2c^{%!ylg8)^H?{TlwzYM4tJzBZhWA#aoc%mu2Kp9iOe=y@hTdC>VCK`*o@C~d zXpVD-5NE_buPk#{WNdz3WNaQq%Gf;j{xUYNi?s#SFel|+t45zE=-YL%>(Ic7j zJ!=iwE7YC#2EV%B4(wE?y`PM2@9WzW%pBdR{^muE$k^9~zH4M`U&4@+tC~)h=b+B< zP9*3fVFy+a%F4(sTr~M+%8ZWHI8(ZS!;UEz6%2ZX-NlX%v7h44e8%A)0CA# zTHypqKZyx*$!@fs>}u#h3Hb<|1es=t(3wH@2acW*Zs9^O$=m~9LDzL&8OuYULx}c) z4gqdF4tfLdNP91d>RBctADlCf>I~=H|@3xARdYwS5Vazqz0b}sZCma~VngkfLO(#B#`JTX- zNAC|~UIz&mFy>J#jCmd~ZZ)fLIyVp|IJy9E?mR~SXcpJP-EsP|^f`?j&>jZD`G?ww(BRq&Qn%>q?Oz>cDq3~MCaX}P_+yhre&of>b%YoYoYRm(W zktyqtk%=y4{1hzp(#;SVS~8D}Uf4SNk8!RQu4mKrY?_DNV~DPY==_YfdrZlby}N+v zKc?x{nbYhC`+1<|hT&T~_SMLgmKlj|>vlv=H}{|g7nxD4##=|wkr>($8A9 zX~LHMA6A1G_7GS!>`%V!F5CLe%j%uUS3Yy5U)`hS6BqvQgMt?gCH$7)4?UATp-pi- zpJkT+LOFzgU32y8hO1r4Pw4RUA(RUVqUR7 zF|6uFRgM=k-wlQSQ)6c9Ew|ex$DU9xPQJ8ZS*D_`@jr4-a4#>M6Y~?6Cj7`bCs6$o z=LA>3jDJq>Jvk?M^#11ruak3vN3rJw&*PkEFuwvgYBM9?0_TI|4dHt6F|OT-vw|i4 z<2ftnOct#zT7M3(ooKpK+Wrb^EV^C4-t4+|C%S&k(dWonUUWPg3O%jS@xgCA82-Kr zyr|xre5hdV(p7bp_4SR827TwyF6#V6ak)QI>K*4S-|G9MmY0?#tf#7ku-dJrx1XhP zv^rsymha=?NbWI?WE71fbOn-oZdV}s4uT@zg*qsJ>8J$g^oh8C?yr)lAf4;yv97k^KMLXQD|c9~YBTZ8T0qaCB&t-+37 zM~yzSX-TnGqt9$!UYMFlYP4^|o%h%&FFvQ$PdXVacrt!vK0vjAOs z2E~lCmKzVFa*r`8qgafh7mn+X?i`$Ms73jFq$&J8v~zubvLKzG%JLgFtWRV&`;T-u2b+ zTW|ljdMDfz?CcB%J37={rCy``$8i9k)o}pO?@*Z$7S=k#RRURE>pYe#838-UV&Z#( zN9Zgv7mYFAE#5c)epccD5S1d&ishW2VILM>i?#%nPm=AS+f~6|C97RIDs5T5NAI!W17Om z_rjU~o9R1hhMT$BWQ z&r%P4%7~#XBQKO?EuuXy2~h3aJu@2=)27*c0aqzZd-bfDp&2)I`Lo$Vec>aV3!u;<@+` z5;{a>!{|5_K#k`RLsV- z3)?@2LT>=Jk9ST>1_#F zbZ)V(&o*5du}xP-VrKw%l(|@o0;~WMH_>9&fv2~b5oGfg!U|{N;0e)OaV?rFYzRhk zg|UVLtw{gTw%w`yxDm7+9o779d{QTrFqPjh{6z|#sP(JYycqdXD0DM0a^Y)mCxLPb%d>8!%l1Qucrj_hbcmOA84Ko1wQ*GtHldvaYWsHk8Qm?9=_s& zv;69A_Ad#nU7z_c3D!72*k|4l;WL*Ja}^nRxr)q9&s9o^=dvd}(q}HSuFt&AtgIu9 zHkuLmOdU}=M=bo){pP+n7?^_Ze8lmaD>^JX^@SDqsu^=Na7G!REER>Me!BO4pHZ+VRJf`ipZOZ1r(};AK=(cB8Hu1YHaI ze*$UdtpD@rAS1?!jJ!CJx#@AzVm{Zk2plD^uROh+zI&A!t)gGEoUn0%(GAxgyFXzq z%>py)>3Tg~LlR_P`ZQJ1>Hq4OW8IFWtlyDQhXX`R2z z#nuI0Z2c${dR$|xsAS&arB&569o_p#Xg?VEk)oe{os88HTB#1sznsX(nB@u) z(DVPP{__|;-$7Wcjz1Oh#BDBabagr*>X3x?-=bOEMP7u#M57UQp>dwCg7bWpwdtPl z-(MRKKik&RqrK<-+8P6SOZ>OcpTvWU^A(&vo#b@Z#M4PLL>{f{k3>cj-@}=Y8cIBp z>NsQ}Cdx-mwOWEVXNBUlpfio;ajsRHXQ0y~2cCNR(tXkCaVY-s!UC2K?(_ zbuFrPXV=kR)}_>M;`?r&`S>syjL)#k;lq6*(rJ5$)cQ-{w6#hnuU4;yR6w_T4j&^S z^sVVN8=RUGxdRx(mmriwpR6nMVyJyyb8y z_U;DbdUs{k>)n;Pc-~#P$KG8T#d>$Wd<$HOeaLNuCvY(y!3Nz%c&aDr7mmhvgrof{ zyu4Fj=zYAr4w5p(&HHQnQ^TrepPK2#l5xQAu*<(aet(i(q+XePasARvb-#AOYu+Y) z-ahi>Abt}v=sbc%7r|x*RcP#*(u*kf_$-l8>{(J`K85u-S&4lykKoOm2U?um8KCc; zV@7j`PeGqMN}gz0F`u5rx&4pFaEc$%P;^rQy=r9^4VSZ;cV~HjTipy&^vZn8!tXsl{$Nu05sFUy zgi@1wKe@iaKF2!;~kWHj42t#Vycq#XwePmvkAW99qcf7pz-&bQ7_@9 zTT2Ge9cCSa_WA$9Gw8)qOw{cZvRABUaGQguzeoB8C%hPYIuv?BW9-rx-=LlP^YL#a zg@12lhik<R>%B^_N+Ym`vu9Yov+DMJjv^Kl_l2(;{{ENz>L7u> z-s@v1cH$Kw>5692VWfFP21@*Ll9^>3h{W&3fy~9?Ac3e)aNyNBK*92q)aK+k1EyfW zpLGnc-hmD)!n4RWNozP806qt{Wq{g6(#5q%y0Ae>Y}S-QK70u_5#29?&l^Z_U+qevlHkuRzZ20P6gkep8M?n{ZGSA5q@^~rq=y`tMFSl zoolz8y}f+N9)1Y^HtbM9Uve~2^_nB3;lpG*IBNN@#(_+Xe?lgi58k0{v4#T=u1|u3)Z=?N ze@C7Qa;hJs|HLbyPVw%OH$$OUH4^?d9JX(@{&HFPPoLl3x;=dQ#38@BkhTh%levB% z_$D}h@y~<@@l7-vUjS?jE*`{(z<7|67Y{NwJs#rwC~D2OB1X>ZonY*U2N^a!?wSBE z#qma1!(#OS<)`5cfltG!+%Z)IqnqdF#gJou(h-eQV94XM0Fs{9_PooU7@w}sfr*BDzhBGz0ii9MUKBqJ}DWNvyay}!Mj z@v{0D$L_5msGg|d3%mJA=CuBQ5-;arXU@4Ee*+!2?c7CP-2G+u{V%NNk47Lj+J4UQ za^QnvKkqS?ZN#g)m=$|BV^&69%*x#Km_1%QI(mI`ts7X>dGGw|Bj-G*jJB#z$rtT- zR&_$*CnN3Z@lpAOwiVsQ#oa5~+WD__)@9+>ZU)!S;S@ZMK7c>Kh+F8|CCfht{uOuTFF9`Zo;U z)V%*M6@GG|dn}kg4~2dNb@G4Cx7$9xsczGSb`yQz1xo#ia2aVgLkB%zGsWR*Y&YwS zV>j!gUBs3uWRXi&gv`aWo5?-4o5?8JZUzZL?jbLxlVHm6dx&+AJLt#MY(}s~1kH$h zyva&<0dnax#K(x73HB@^PeQPWYr!INCIpLa&P2mh5=S)tT$?9xy{8V_$y5Y&ZT!3m zgFRzYd)~faSQYL1ofmxw(gOPabeUanKB4a_d!~A8^2HMtWGbky6sd*07T2b>P{(oq zo-l|^W45U+n#QIk_i#D|sH-en-=a?zj4oW#KtHMXErS@jRDrv?EriaUY zl#yGKa5`Z$f!;cu{-F~EYIu`%m|%fjnoR4{^(iJbEzwC){KRRrDvh2?C5UCwbrxMG z({(moXVW!kUOdE@XZ@IFPs9NdQQ&Q>PMLA49d_RK zuOCc1Mg3hjjIrN+@ImXDu>)C|2bS#LzvRG-z=5&wrg8hftn<&KZ^gT#*VxbK-K&VV zUFp0#I%446VbO`iVqpXp`Q3RA^2zbNJ3RaH?q&2V_<2Oe7SeaJcOUQ1{-NpKpS0a> zWVpwNfprBnC7B?PnSC-r;b&v#5EORq-@lWfaL(A|mBU}U(69b>1N{IEhus8+=Limv z!S0HJ18eI-15M^PH#w)v1H|QEj|U|j4>XeK?S#5prho=)3G!)f^fHIb zd_3lvX`rNjVOMeAnwK@Oo*O%XfHg2OGC;sOVQljJ;fvc&eznSPEep|)g6EK8K0jvh zo1B;*>j?or~VgGadVC1ghx#Opt1`n*LZ;gpb6smEd1Nz}8`>Ej*(8iJm zt$1sm5wnZVpmrjMsguY;y^Hp`yJ+v&6X+N@meAsVQe<~U#*h?)5cQ`OXh5Fdt zR6`GOcW%gukWsu;#CN8LjF*bMdkR&n`FV5#=X_4YeaI}lth~#L2~(i$sbQqt>gvR2 zl!jFtZZml}JV~O&Hv63iA5=34V#IXD2wV&H?_WR^G&UA~)&AnJy;hxdIJ|x7EHXpr zJ%|1ypdrY)$QJ?y>1=TNUC6LP~m5?)0(AA7}T@TU=35UtW1ea!y`BdP#Q1wX-(mCI-q%tvQ#{57c`T zeeD3(7J}kn!si{x!V(8MEOeK>vnCNmYA;yxd!2oRE^jL^b8d|i zmU50#pBq`v6-#84L*D@jh;?(8fLH>cT|o0S$2fDO!8|X$Pk60FY+-E&t?ls8D4P8B zqxP+%pAS;GJx5rolft*Oy{!Z5eH(w!zO4~`yEF3ZH}BZl@{sQb`CmWLI>Gt|ir-$d zZ=dzR!N<~4Lg!nl$-biOtWv7;MnzjM2qmRIcCgQW^q?K2Zt@e)(uug}y;Z*J2#z&G zh4Uy1_C(#M8@_aCvk5fUt#>qQ3EgsxAdwI}L) zPJ%Rh3O#`4GP%fgqlC%m#7-v#PI>6u2ZWsDHca`Z@4I#Pt+rOFzpeG1^kDNz_FJ_J zw)ORGTToZWe`}SkYbKq)puK$o{_WenTg|6NHMQx4qNK6qgrW~0JosTk-V!RP`-9-( zU_k->PjGR2K|%XsYf0#Bt1BF6uB&UNf9e}lgvRZ6gv#u#y5EY9BSZtTHdjPd>!tPJDNr(n8Q5@@E@p>~&Z$eatU ze6tSq#0xc@iGGwp^aVI&n>Emmz%#_Q2dPK+2jIaHG^!TLHzD>5J`4CdkclMouteZ# zsThf;Io~-BG-GJn4MuE05j}wQ+>O4?54Ue`atZh;-_HZzTxYGdeiVKOg>rwAP0*dW zd$;xDgXa)UZnRR8Tw>i!#Cp!b$rA zD5F;%Jb0xjqjv6>@aB%4Zv|� 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

r6+8uYukHRamjuz7A~6G$ZKx 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 z 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° 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�A0EfZNY^m$n`l;WDvYrYM4 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 zⅆ@C^xsMgtPb@eY4zqI{Sos;%Hi0&GOxgyLKOS}72Oqe zb7*@f%Oj(sIGCnsSwmi4!!lDJrs|8nt*C;sw6e7W>vjC{WNa_Yev%SI2m`i^+rdQmdf`1S3$rhde)R~|b1*Uxqg zc~fDXiTH~{#^>*M`q!?xDe}hbl){4U@bUhA<@wj|I(zoX$q9p%3GcaM&vl(yR}>lO z8xJkcFG$WkytX+jC+PfW!r;^5nJw?Dt+5b&XI-FxRCQCEY`eWr9jn(u^bz!1h+a?9YTzP0@_G>$=dgBdK!mod6`@7O2P(mQ*Ka9l-R z&Z3>|UG44(mgMt3aQ5tNwZ+9XHO0lXPfzYK)Z63TT$X#_Ktb_ZRNsqyIW;52Ey#_O z1Vg#OU`NN)lAYJ?@m56g@*>4Kd7ugT%ke1PDiMqJn&{dojZ&<17K%w*Vv6MhL((rF zYp2lg7h0}l6%oT?WfKgG4ShCD`a&@pduQ^EMt9Py2|GWW`bF2G-<>`C^T~Y%3H#oC z+2x^Aut2_UAHI?M2YKj|*gtsM)e@807Xo#e7n_USqS<_9F5c8J^i8&H$!K%U+oxbg zq+pDLcNa?t{v7#GaMu3s;BIRH1#I9?v_3f>X?k4ZP|1E>M`e! zw>q`g{q?%*oJY1zPHr3j+(*M+Thru^tFnU0NE0KfWd6~Ht8YksffAHRv4VNc1|jB`;fc#=ZJ&YpK;mPkrR3BM{C|1W>6tov z+igz$2ScTU)pD$O{iP^M7T%ThpQOOhCiLFjF+}VbYQfqj-^dPC?eX2%1YEk3V|KU zzqPm)%Q`I*I+7L%W_SrbaRJ zuECqEnVn7x30)w^acCg#3HVpbsh57gqvfSrrv3zimEW4xv{BE29zjj8=RvJZL@PY9 zd2({ISu>yVZeWN)^U>D!!#`_?RsbuBRscgkFLY=Ns({7wDSA5}j;@~nT|N~7_JrfH zo;7*%3*|`>U|jhSdHE2qOn(bk#xSmjXT|uOJV}pyo>mH=sl%DEPNr`9*MD`|@5yZ1 z%n*a*{G9FyROQ-I-clC2A@{77<=R}bl2Hj+!GSp5)zLZeltF)PZefYk;L0x_ShuaS zvujQNt27SbSp8DQA!JrNKVV*UjHk7NpRG#z_5UX{>9aIp4o<(B?YfHkfK}B#^05{~ zPvO2%W%?<1i{Cd&FiNc*Rk&7rI`@1;dlb5mt8hkK3T zaf9{whew>2Bi&Bbc5LlF`ZOErtaGwKA8PaxAJF%L;{$Yr#0MypI6gpoEi^uW8ob0E zFfW{$5*H9Nq;2hJTVyD!G;0MtlxEb%lum3HI*Iq+uWg8>*KdDG==}%nrilU`yj$S%@9JM&HGwm*d;T@6b2nW6y{TOa5nub=DIEd`>;WT zsM1phIk(5;684#0TEYn8RoE-mcVAy5F$G11soNtfO*Njs9De2Tm%DqSzpsle}-A_w{7wfh}Icj6y-Qzh&%5*{b#Ht4qrY z78PF6d916nEYel{D)H^Vx_M)1S}-jo`L(T^ODWUTJ0FX;mr)yLtOaK-qnU_1iGxkT z9HQnc)>LUrj62#Cr5|N~dR{~_(KD(m?0rVlHd=_$Gi?@%MdkafH z&n%?jEJZ1WZtzU<#JGw1zQ{n$okih{w1z_O`Qbaq3rdoMxj8R>Y`^yww>DDl{WDhn zv4dt_9{fXOQ9(fiT1GsBiro`&2J@|4MU; z0Wr$mgcz-zWj0FN{1}yfs!h$rsN5$;o9!=AU+A(>tPXFVZDS5Mk0}v&AFxd znXa3ckyVkLQBzx!F_xbnE`IUIOw;jl;UaTjXXCWMYF$lJjXg)xFjYTu@EXSJyvG90y84k8uh_lf z{L^R8{$g^knWcNZt5egDn{zVnbAG;8@Nr4h20(ng8Tk0$kfvzy5?My=dbGo8TkL!! zN;6{B;=ED}P_Ix7%%WHDybS)M|D>i?%zb|GW$HcdB`D(Xb+3&@9G)5fZJc)Z(6QDd zmElXrocp%Pnp7F27QCi4=_An@@&9Vs&H}SE|HaAkS>~Kz>5zt{fuIr6pc`cpJ)y6J!-K(cAd2!&f zXC8d8#K*$kbL>m<0XB*ne*ps{ z>cvf{XL7D{Z@n(3dfD#o?%m6(o%eXJb6(*+-PPLK#lKQcu>Q%({_)S<9iI9^ZOP%o zWz|h9nhOh?SNwR?`(<@mS#?cGiF2kOD8+86JSZQlpE57?K}JGkLT8t1Cz+Tt;*WGL zLjK47Onj4zYZv`eZNF6X3mROgtvScuV}+$Gj1ub`w(nS%;@ zaol6_ic4EJdD_zupt%tKX%Ri`mwvj$Cz4J*d0DrzNs}-l77AO@A~bR zZ9jSP%r}<5c1dYj`;vd4m(k6=vTk)GHIU{iGKdTDHLidch*c=o;q4iJl>-^N)!-rr zZ<>NPB|Wu`ksMhTiq$&`<2zZgjGDag2v%{?QRECcxYL1N%%*L{3K6+pRs>~!?Ms<| z(BKE=w52$kQpw+4WW*!N?=c~C4o{+QiacJ`*H)GOu8lHHK5HC_k<;Qx9I4&iDTk4@ zO?MO-5KITaLy-YarCh;X^!a7-x z=!f-5p97|IfdNWXncz+$^>8)GtP9vSRvJsT5VN>aEHvGJlV$IaB63PpnQdcCfYeq| zJ)i<~prqAc`_Mx}`?Q>6q@Lj}d!P1c+O-+QPtIVfxO7-)vKMH&%j5R+)$)0!e3o14224dvQSkQbP&H;Bc#cDK>=2bW&O1R@acLp z*U52`%v=xIHp;ZQXu}Ezz5*B%!W>S#6ObN?ZV>^;p#1}7&6y_=l;*=2iMh6ydK|~wX^jSgWA`R{NWQw{qsAw1hZ2geBe$Vvt#f}o$E>9vJV!v zUjV-*Ck_~Oz$07C>?D4J7GlI4>e_w9b$uODOO>@(iiU8@Dx zvI|Q#p2QAOBG%{AhErl8$^$K+f#?R3MMh0nds7o`w@^ENQ>s%`;CEKwomN0|h^K)u zz@*kvD4a=%#@^W6o=%C?Lob65t8=>Z3Ie1^0;h+VN)z#c(?6rDlnp^%>*+BTgY+%@$cDH662 zcTH*;(HtINhcS(1_I??l8Vl6`m%^h-Kd~xI!{sap^x@A}FgMN;1}D`U@44rBncgEG z&urS{b46Iw2_@$alxc6#~f2`szL6n%U5jJ z*;!pvzoz1qbWo)`X&IL`42XjY>mbIXJE6}%0j$%~#|W27%pHmCXXb_SXl;wx9cJe> z+HX2NBr{Uyedb2w-(GYnUc`2wpjm*@-pBk)ZLfHHxDFRHLyCuE`d zFs-9zVw&d_h$m2a4EaFeMVaZv_7`||LA8Zg`9vyT_M^AP?eV$|Be@4r*OV1NzlHuj zEvHK?#0(pbQ5!MGtit$J%7Ik7AVms{W-9I_AO0OZ07X|;1lz~;_uc1Y%4%^6T2uRC zjwSbcT`d1nmeHNkT6RxX=gubHbIh|4 z-DZx&C;iRvBV z2{~GcNLG46`UNq+i(+M>?-l(8g|#&&_U|hw%x^5XTKpg{Yg{LOkTcDL;s^QL@yW^K zPO4EjV>*2kVtN^2-Hz`M;fq{+Z^+C%mo1n-VvSKbGQ-}_K<|7DF&ePULK<7ny5su1 zn1xuhevz}q0>as;{Wv?j%-m`K>SnDKZZ#abI%3Fkzt_I{j;N2r+kVf4_&5em9~)of zz5Q2$wvR{3bEBBs+>R2{#>+8U-4XS2WLMU zEqH1zepU88`jxaF{Ypy&lj^?+Gy$nm_l0#9!Fypby3|fZ_t&LM%HLHQ4!W7SMIrCm z+aHM(xNdgtsn2ZoZgtld6u;Md?64qp^j%Su*5+1)^OBp2LxtgB^5$i^ZeDgyNuZ#= zZoDA3^vL+)$;riEFoFg6ALpR>FCvgyZv;jw@FnDaNzfLAQ!(E#U?E!E#6p+^?4=vN zRA}$gKOv_!)0V3GOs>68tFG7~Rc9%-_lj|^TKJjYCtEE?a-{|OJ+BCB z65r2nrFNjb!uWyI@bsi5OwN~jr&sV;^@+-Q6+jBliLkj&G?&DTx0p|duD-eYY7+1Yqn zpLiD3Qb^B&%7YoWmMSGY{R*B3V2jdViG30?lWGhe*jMBW*rB2yZG<1QD zn}wWCiuEkG*F-C_|_)q61yQ>kr>Wn!pzh4WkOa#gk;`K!c?^89!4D$w5C4GeWdPKv~2AnPlz zQz5qO{oaG$hhFR6dTrS6D>x(gIdevla+P`xDl3YQ9*tBs4KS~1;CtgelaoFFZls=1 zSLfwb*W~9DM?=v()l~4sI@s3ffk_39sOcs_?h&5>=f7(q7hlG66=(<59<+lB2MF6X z;u$r(qtD>VskO-+kxKd1daYb32gH=jP|gj-jCf4f&9F}NHCa|mg2tsO_OdgrJ=jy-uIicv{2Q<;;sVos{=FaOHu4e4t=UG zho0CIT{wolG~1SjZzSHN2k};7A+8_s^D3VtPNgStT4^C#I*2#9$C*y+1m_@kA#IOE zH*{ep(mLFRS*cMD)R=qFj`|Gr;0SgT;x!+(HV|P29*BV57 z56yw&sh?l&{rF$;XV&u2^LtG`d=sR>L7ZGhYbLAKajrC=P5hzMgj4YLw6d4tOGFBX zh8*Q#lxwsvBNSRK)Cw%i84O*vjrv-jg&41})Xk-_;@aa(P{xs0^)smZ}`MtX5^Bz0fe z+M3EDRI<759;e%J_HzLwB+ili&ZR4Ba&ik>3no(wi;B|HG6JcYhpKyWbMgZzf$V!v z{v_a}aed55Hp5d+2UssF6*l;CNI#U$$Wu7W$y3q{-&LL>P;6C%Y!Aw3X~0#EnZbFs zopBJw7NW14=MP8(M1^gqZd+?1dTrV*M7yR$PpbEuK34$w9WZNr-kn>X2nwYLfPhU~o|K)Wrp8_1pXsOg08ro7W4e>*fl_Nlf94U2y3*&di9WC{tb52rqaYkP2<>Ega zZ`_M=HL2-AH`#4FEUAdgO)6rtvt!AH^&id%eA)jY2kxF&t2&5~Ac2V7z zxtGXY+Nd)?6>5iES<*_)GGZZm2)J(K9;NB4d6(dWLMAKJAmoY%i%xm)Dh6t8_18AFQ^JiN;un_dR{mz#HgyRx#%$%*ch z$4xDaOh~aUSm6&~1~HeMyw^dSa9al}mVPMVuM#PcW$%iYL;F&X5f04rk7PXOW2uE? z57v7P=r8($OH_|0Ar3z9_7P$svDow|WC%=RZ7m+}%9y z3cl{LW#Q9fKbdD?Qa;w&A`!DLzXN>o1Wc~MAl6V)REMC}s8Gyq%d>c?7s}d{lYw(= zKe5&7s8}o)H7cNdwWA1C_Bj;(>H6N-S|8|K~FVD_v%uEes zq`4_$PDdgNd*u_}`yjszA-;ok&4ZZT4X|ntqIPZ-s7y(|41a2UNygo>sMUh@c!ele z^6YD#PpP(1*}rtx%d&m5_)PRAH&d@6B}si2*I1>6s7=wQCBLe6Khde^Wu(_!?@IMW zg_yZpYpKi;s`XRK(q5FZXbofqMs1^%*MQz@FGg#-<87siI#>8GTA9}voFl(C>U~_u zy3L1Irl7~2m{H{%Udb0BA?}Uy5&jjsvfeWS_slInXdM4$1$~tvklrN7B_{mTD?apI z6F))POC9tKterOKR$G&HJAOCfgQqj&C zK@KXh5@Ic<4_}|f-7VKbjOgOY;Du&Rs1#jk?{gM3Scnm$jPsGVqTN?K`qVFZMQKRy zQX1;EkckYz8)}v?sXTzUWp>s|+e@phQr6bzFuIQ#x@NfYbY4o^JpV)cY)2njp?2em zyD9T5B(r#7{6Qwlzb7t^KHqG)dQ158-mT0)&KhZ|8~b)C<2drN3nH3<+>(e_Oub^y zx?FGw@{0F>R}^DiuApY*6k@he&!LqX@_p1w&Hcc&5TjZfEyR@?v``RZ8-ceV@J3Hl zioL_#ftmcWJA`nbGIPGYPyb4Zg;-~@%tG`VNPG?V7haLZ`gSYPcb$buUHa5TbMkX` zO20ZrH7x2<+O``bxvz}i-QqPV@xaQCAgYqanMGNHrc^~0Et^vXt3&<__13rBf7xGL zote+5x9(m=;(I?D7&w=aKD{V=R&X?dEHKzQ@=X(S63T@Tke!{JI_|V{B0P6*|9N=N zs+X6)T2rDgYgjH3CvMLiB7@8i)?kldjdp@>?r;uZe$Yz9xEu#0 z?4X4>Kez+O=7)~r{3x6;Kl1EIu~BGm+9+uK_FIfqI@TM{AWpYONAT ztyNOHBWAafyR=*N+L4ULA^*_Knr2)}Bo}M{>+{!O&PolhLEAQnk)7x*`;Jt5-j3NE zFLOkdaq8#2)6=g_5HRhtiDuP3$mg}S+oSu>>+j6Fi>2E?acA;;yalu9+a)2h0ZFjT z*z(H!LnBUjwBrMbxC+#zC{NjkInxXuC+&)Rozs{z)I}(rC!tk*C6xCa3o&Y*dyK4d znH_9_K6O!atxVfjvbgm*lqw7DJ?2zVzt(-H#NJ_?9{GY=Fd6xw(!PW1#*6sFvs&y3 z#%V0F5Gyu{r<~D#ykfN|eGAt3?z51d?WmD9j471dD_T5tj9NTt+tjv=c*`#I-io*J zTQ;#`(7Fq)yYNeUZ2vvz&$r)$JA1fKkxBVNcjl-IA5#DmNwRPk1$Hu?=Y6aVzZ|vU z!LIu6&+6P)QkCAB(&`M&HjI>lYb>a=p2ftQ@3h{yL^w2x^ zCsbOduDXkJN^Ci_-xVt#0tP0WOQO7pG6Z>1gOO~=i^y*TQePBzB5fn5p|l{L>ghWY zIgX4a$EmUqD}I&%%aox57_I&(aun&W97UkHIEvg=jv~-}97TG?a};Tti=)uCqwlrT z%ov5lwxiGi+&g4@9>TX(;oA=3I}c$t&D{6IYS`NlbG0#fePMzRRN+)cBZ zsk$Z9Jjm+u$u-@lSY3X1R+sbc?yP;g_v~}}=bK#LVZp3>%8R?ZQwxjNRgZlILQv2x z3^zn;%r}%4jEoeN4s6}(tWCtXytaLREQ++ZyM@BPjz{$;@!u`66aBYE3B? zO2NG}3#qS{J}B)kzB`4;wW{pB*?f1}Q+#&{iSJG!zwb`8HaQoFRuYMe2+{;m5~B~S zymR{V^5GjP=yBFexZ?)(YJQu|rFYW1EBv0ZfAgMlRwuOhOx-rLjIr~SB?PbO&=r~> z$M+}E@hMJR*(o*XNUre?3o(C(HCqJhF0LfL721M0-D_g|_57H3 zAHKoMoVdXmzJcg}LecMYcUbG^W#0YaTfEPYeSh60G<16R&tcu1dVg=Twf!85o~O_b z%g^?teNGMVPwN$Bxgd5lk##uB(=5c99F4{XzQnUkIV~2O$9+k0S7XPqULWt&U8H@9 z`hq^6dn{w2R0`8mWqE>GtHE}Mz1xAlODx3L!B#v|v^>!>WQXNB4En^?c;l7kIU8)- z20Ukrg|^^18}Mt}Os^fbeFu8&w9ro41>$P^TdCeuN}v{*MNy$!C;z{x5^}VdOKwIo+;1u@NRM2MyEPkw5Pi>#J0`9w_m8*9|AoY%LmS_*! z!m}+TnLc`tD=**Pqn6iXAxh-*A4;f+=n0W~J?Od8Le&50<&b;p z@%}48-HjOQ^Hta=PR83AN=CEX%~@!3@ufGD^inlLfMsW zvTya?_wl%(2=Yxmvw?ARtiX96s6;7*cn(5Kme@RMRvJfMWLsHNrP$2#a@$7BYpsQ9 z0kvCbrXQDUUHrJTzUZ%YV^qI|=z;16&LxhSr#LW=d`bHD=KPR-`>8Vy{M>t!xM>jt*^G$*0$o$tP$ph{u)+- zX6SR9O;!>!o4KC{&?YfYjEv-tA~sU>8fM!2qO)jkv4ksB4jPpj8r9hTT!D2K;!Y&F z6)m=n+DWH{Isq-S5Gzn|C(`;F)L!-1SQ~YRl=Otrz zZcTQ1YFk-pQTop6_7pcKD_k8&t*CFzJ(^cmc_JY#MfNyg&IBh7SK{loI+<8Qq+&My z#GWmtN3^Ic$`YM0KQ8|(1h$#_hs9Ai290u`x`^2HW2t9W5a@$WF-B;$_=avBW&ypt`!WByC+dlA9R_)aI7DDFwx)StGf{3(e*GmA>lx6=*)+uk=#dkP7;nbNhacx83J)j|qthmeDiuXHdAi=UXqI8*dn` z2u+MRb%|C5mPAzlI)r^J8*kr^-C;%2PoflH22K)MYoR z@-O+JyqVZz{r0fvNfp+Ymr(AY{x2n(9z0-i(%@Y z53xQX<+_8QM;`Y6PLp}K#he>nifOu>}DjBi1C}Ume zP0{Bui?-TA^!6}*p#ijPz;!;Zn{Z9pe39)%>!P|;J;q{5 zV`I;vNdD+(UUB1+n(XYFUZ*S3O7dC`{2ufnT!HBpVvYpYp2WGNVua-8lE3K)v1cemdxl1A ziq%{#8)XMh%|sbD^IV zo${UvoS%BM=795s;MD!@u=g>yG%vd}n35j&r`H`%?(FWk|9v!Cq$Cl)BH6*YhonU-k<$Vkun>222iTOn8rsTZaSS?wdr+Po!5mNSFyg_c zmr3(6s0*nLBn#JK52htgpTr6}4Hn{hs=||+%?fO{?J+IOA0;k%4CG`gx1%D`f^qMU z8h7tYNP!>5BF5dP=Oe__k1zLr_Hq0HgF8?&=vvT&(FI+`iu6-ZgS#O8#kG`A%zUp! zOY%jo0{VPob~aW`VQdehq?F@`ZAiwcZAh~?Y2%66hqT@?{Vw`T^t&vz&{F)~VvJa3 zeuJJi*$3dO!?i?2vIpviUt|q&p0A@%QX7%{w%&&Cd|FgP^HJ5pum;IsGjL7OJpEjSpt!(aaECbrA4K%bl^1CLbUF3B}wdE zk!|N}DYp=-2QV^#m9MEm>9eRoHCd<$y%<+Q8=-h$+CW1_w$LWnfopPv8eB^(Sp3?F zMV=!IOcGd@JE=37nfvi;Zo0{7zUGZnKbklnc7EZ#S-BROS;4x-a|QnxxPI^rSU1O) z9Ced}Qxon75rF=-mxrDI?C$u+BcYpxnFZ4W?|$p?WX1J?z?*^VC6Kz-7~fSc*3C-1 zFRd?W&`G8C5v{EffzFj8Un+5Q68|K;hx|rI&?`k+iT6@)A@z%C1=A{P^iAprW?l4K zh?bi^{FbbkK8#p>5r62j*7jKoXp@CDVZ>UD*kb6g8Y8x11bvlTaJ?PZ+f9!LlXl{o zzNfu*>|Q{l78*sry?D|%p2RiA3RjF)r`dsCig_zry?`b6e8oUlUHUtnKy^`CYGvfg z{N#dsq-50ZX^+;tIw}$CtMu@k`xCChLphE0HJKBYMfn}YOVc}w3No^Hly_z$UOgu_ zMWWTeaH}nX6&Rd%Nv46f?g?CH)?*Rmr3TPwn~BI_#0B-F0{l@N`?IU z9sN(*PN_t9zL0GVp_O~0&a5(fM{2F;Xxj4`=~r*oXrt{#j@@PnT){Qe37Tz$Dg%CKCS)8r?*>ZJD^<_qHlb!g=DtrILP7u!Cf|LHF=hqf3aB%hVC zf@pri$yFyQMte*r(Xp)Lu-HDA+3Jh%B=LLtqum!SL;c#l+$#w?KcD(BLa-AufE!M( z3ZEJaG|#)Rqj;GMcRs~HU>{T_Iy)Gkr)#c@&Z3Tf0kZIRkWTO_km#M4Q<Rrw)!Kt6S#on*FJ3jc2q1U^S=!!Y}>Lb{lsblOnI$SB_*GBNNrAb?y7Eq@S-^aPi zsQBWjXPUVd3NgNea(&EhNI68LUPhZ}KiaD}!)dR=>bR(Jk9wc)9ga^*(t5_s2@$ zm$tDgJCd3uYoEz;xF1uqjOGPlL^DQ61d{fVY#@dF*+BFMX*<0N%Pq7V&*e!Nj9e67 z!Wukx4O&;>H`d{r@wL6U-hgZR7;maGFUPzf=c8`oV6}s#Bh40xulKnlkt(Val-iMuMJu-u^>&{BSZU}>OYkaCYZdyev3+P` z*=V7S7_kN;Hec@UnDeQF+g|ItStah5%t*|e=vPA3~UhSSOZ01i|&u=HGhe1Lul&L?wr z%_Z%xX+7{nC1**d4bKlOl}Ym4C;QLs%g$N3^cs!NKh+qG&ku~xE5DpHbB7VvOE7zO zJ3BCUC=birS?rrTK}gIpTVj#1CAN(*(kZ~{Tr)(+a)x98|7vBX++K}w^d$swU59JR zPXSzOTy?Yk74jR};9Ag&p6^zBhdUOlJINc0ZAWa;V%ZQ4lDn7ok=;un|L(Tf z74pwQXr*`)jmO`NYuU>eC*0!h{Oo6)!N;T9T5?{#+1EaD zA@5Vq9&|Q6e&GWNcewR+hrU%TDPjdha)?@gW&X&BlXkG(y?Z{kLz|TFoYR;$tQpq_ ziEnSxh{HPYloY8?B*7x+kJML)d)<7I`r22bUKC=~OQC)0%t(Fhr;+-#z&>>m&Zv4^ zv;GQqLXmWYa*NPTJ+RF_mr`(tg=iDxSxBO#v|+Sb9+uiZOEF@lg=m#qiV=)p;%=sI zwGO?8EHs2(>(EQ8G*BMWc|*P=^M*Y%W?#Ny-^B-$_Tf1P>~ju8zv%$(nB4kA@%v0h zjffvJ&h(XVqL~8{j<=@{cyG(d$n9M{ST*sv&pCsi$%=G$G-Xw#cc--9op7@Kp}YH2 zd)}3mv9B&QIU2)%Q_KD@)n+=5>oAJ{U3=VlH7zgjao9O&<9e6jRm{rift0x`X2IiQuqwsWrwS}4Y^QfwRfR0D8a2<*}48LwmI*?#nvRat2ENPfw?P$`;O zAo3REP|N}mi2gCn|KL?DI&q2ZvjiiSS%}pnd3LzOq^`E@5_zT1rCz0xSB#~DH5K1P zFT@b8x8j->R$5!t!b;w{2km>%&J`k((uJgh_7@J~Jq}yw@T`1n_IUn<&o1V-o1p%v z>Fb`m?s6908EW3rg{b~u?ZB0c>OY#b#QFHLtkKo%(oU*+UwR= z9{N%=roSmIoEJ>)Xs<3Q*uTG^WMI>#z|Q&jocF-K-xTHLMj|N8MSgeO=c_F@zQk`} z-q9|~2$N*kR5Y@Grk_^sP}38gE|G^;`l^RkAisx}bqDmf82?jeA?}&15Zq`aA9{Y3 z*HI^I1+`mE57qZY@08Oc7;D*!an!3b(pCG* zeB<<3(|E4vb%C>kZ*UfS??%-Bm%MKUZkT#JbkzBBaO%_UI`8rBj?dp6y3sm5u6^b4 zWN*#BO$huKywiuvxPS38iS>(KR?4pqJg+k&|9fp~FV=OM!ABl&AlPS}G#$k~CS;)y zdP@z&OyEPWV7&zHxc?N{o|KKsEi~N+rBA1x*JOLe`=B!MK4Nzf>7)a{!TqKN?OnJg zM`J7*V`z*96U_;Dp_FmIb;H!JkQZ=rQDW-!dG8ASU*g^aKCY|SAJ@IRtFDz+(rTqu z@4d^amaSqHOSWaX%CaRF*>X)I1p*-<2@d23Bs@Crkq`(b!RarM0!e5ult(kK(n2VY z-XDY#qRVf-XYQPPS6ZzM{QjSRJ|D$9=bn4_?#wxJ=FEI&4kZQ5eXGyBW$8=7BgRv{ zrO%n&*5}%qK6O6rtQOC8*N}KRy6PmxzTfk1l218lIp9#X(k>U70kFP+D)G_Unx*_- z*imHBZwt|HLqr0fInRzY5L<)Lv~mYDEp!v34zLo-O3pdp{9I^#ZtUn#R z?uu)Tcg9?!pwpc&`&Q1r$rNrr_a7(G*SsfiGAxMN0IQ66#l` zDcE}@BqfeB)#!G3w(2zni?3BvZqGmV2J&{us;i;zTu1W6=MMVZO`j3-tf$Yt^tqRw zv_ap2z3V1Txe>IedMtIIS7Z>l-3}{5$}W7&S7M|Q{DB3$3TS3e%nSn0=+eKG>@}YC zE!}Ls+IoOzIz@#(@v%j3lfY?gxgy5cqVRuH6pKY10+BbMO9P~-xDpyXO9{jstatED z3xWurWiI10Ti^5q`pl6&fPy)35t*CWqV)zq4d=@XVB1 zI!br*EafOS+eh#p$-Rg>@6i-|2ixhp_bE**k|fx3gj>L##R>7{@r;DVA&3!v?3lv6 zKipm$zSZYDR$6;&((3|=**T3Fv*j~&iQaf$PWp~uOKVf6Kb)B8F>_;zdS7~VTYp7G zWuPQ|ws5?&qOz>$5`R-xwlDK|ZD+u1P))4kp{l}QJo&m)%P#`%fi-wi**;kmeJWNn zdOGgABzdfQoJCUL$|5Ns?#g-@q&1Q;>OtaYNK?+KfXLa;Q|mJ{z4)z5bWhChDos_< zH)4J>maty8^Ng17a?fb4_R@KQF^19SFsf2NNq8jqtYHTsvx{`}vYe9$QO4dgWfz$! zcDk;k$t*APo5o<}@O)3t!Qslv;e$Or^TU6mMAWw5Lv6ly37%D?fAgZ0_j^@EL# zL-oO6{g9_{>5Cahj8FNN9x3c#7c#x zuqOvrg)P=H8UeB+Z`6G_5+(P;zaUlYSPzR%?xed}C$rz0v0L!t$i3{x5z6hyA^R$J zwn~K26>}bYI-HD^rQMHCamLEJD^4CLwccqKBV*;Zm=m}yP@G=G*(y7V8;MoGU`trCR*;v1oCU18b++FIYcB7M zaU!9dtu1lJLfsGe_d4P|`&+OdktbkPz-fK#2dbogsCj84wCN7Ee&KJCK23B-ho;=P zY~-#;FVyJSsHu(gT&EHjY($AI!G9uF8rB%r|HxmFCvBl8O=$|2nKKTmD_5qoL=1zN zIsiLcPiIzR_>G*@V*RP*==|=oDlcWVw4PqvS7P01HV5+)Q{EEOGBb*;_ZbJhsiBk% zPku=_lsM?mK~hU`AeWO`c4dU}&2O!_mwj}Pn*WS9MqW!8qrym|5dm8qF(Z@o^WT@* zBKJ#X3nPxwFYqb>ls`Wo{z2qgFom5QJc2;^;gb_N0Gf#V2%3l~L@xzR#5f`L64UO0 z?yjNlgO3>4kG=5~}ON6jv&Uy3SDEsAcud%giccYbVUURlM z<_w=oH|HtyrDopxIw6^#%~wd~kC`LZW7_okhc_;IskAka%)rgAhW|k1&!D)E;467P zW7j2Z@J+;P3LY=Xe&NW!6Bm>_1pmR$gs*;e{0H|D{0CF8!6We>+%EVJrv7^T$BLX7 zx7{3bF1}erf8;-5ecG-Gp`NK5q_9-39~ z*kDH!N4$@g8Pm(w28~bbi-9ke$iGRS{nQT6QZ9XVONgH&5@IU0gt(7Lh$**(7<*Gq z-^V*=TDR#lYy#MEvKlw*Ux7@~b(+GysF~(&xB4}B^M1O!A9_@KqS@mdVLip1OzM>D zW0(3~v2^%)@72clV@{>k^XG3nv@<2~$dQE9orlZ=Yb}mT?^-00sQCP(2XQat&mcDd z$l9$2Djfo|0edK(tXqh5B>i&eZk#xgt9X=6 zJaRl8(uZ;XLSdzJaQ}7sxzJ=Snu32w>a*e-oSkYreeR;SLYy5da}RySn%S@KMU(<} zY@{pjByZAJ7{@Me0uORL_2bmdv`PChxF1IV8raZN%qK|f^{25qasClt>B|TE)`RltH95} zqX=(>v?r6_P^yQ}YDZkfz9?H?$GKFfgMmGe+=EO`WL5E#d4&_oy}}U^T~*gc(o89_ z8;8;0FojNEISyLT=P8(1ghHmTs`=&XjrY*03Y)*=`R>*SjGVJ)zb{3Pjk9LRUz?PY z;eEOFuU|ZMd z=(Q2aG0u50jy<%Xc(qmdH})FiKV57)f_#^@GnXw=8C9EqS6ZJj<~8rE;xpD~)OgzO zIZorLll-6~>U3O0Z(wnFsHI7bC&}f4=S$k$oRT)?lu(hJLhMF3h0ko0(>Kv)_EsUQ zMeap>vQJa&)s$<4^nT*iB%K|VYm~Has3SX&%`fRI^e>%~r1DpmG1WNy@QFxvj+ox= zp|gRru5%E=1E^bqlojLaE>5?exXQ)kS5Pey&$_FIa`WozuX5$9aJdpBthi*r^Lel5 z<;4F@6lvY5PQHXs7Md@PT6$dbS*XbQoTPgphYov+G^Mj;1uoIoOK5B}ZUy^_mJ9IK z!>26Ig-^MJuJCGzIIvt9qB}V@Jfho1=-$nmLWcd6rl#mgo9Rt<(3`k50m{Wn-Tk)C zcAfpOvQ|IG=u{=Qm|9~#C7%oK`wYV<>~1PgdYchf5=`*7UdAQ*4^-@IveO+9r9Y4+p<@x;~)1;E=ShE*B zTWD+)k~A9P?xs-z%@1T*7PauHGq8x`h$C3L<8^C1NsxUUNxBXBW`0e<;>O8goPU7a zXGXmPr3UK_)u`n=fUYgm6ueqBn!@fAUafjHX9-t?=0na(VVeYBfsxuCugX3z7eMvB>J7hgiD8Q1LWyOT8;idoWgj+YGhCg zuSUQ~3~OqbIK~56=-iV7~4J zOB;Fj$lP-xd$syHuoJDCVhpLgIc(cjx)=K>U`VAMm`ALGBlOlIG$RzYk4L`3zu5Kb z=p0liP&82{zg?f*v8A#g6*9E~=N*ha1sO1vGa~ugu zFGvu35SE~L0IT);U{8r1NFzyu{kU=`YH;=FeuyEp({t7QQ%$S5eL`^V^hoiDJe zG~JbN8B6XmkCjMKMXmk52OoUJN|81{kQUx*p94)5*Nq2fjXrHTlSr?gPMxejxKf~H z5w+I0%ori-AIy0z(wF}0(R)&rJZIE=gogn3$u^^rW+dzrtQQ8g)T^>4-fi=qh zcwm_1n-C=(&=j%(dg*%+Z$b4a=>;ojLQ~jzLh{?_Teht^kKI+ZtJWC~+B^CHxbMCw z1EBie)aq??Qacdbt%rc%&fy~Kr(6^J+6n(u-GP;(pmccw^&;ynz;=fZ8rxiBVRmzX z)-cTNH;``LLP);-aX+GQu%CYIgc=9?<0kYtFzG5&@H{kW3MdgD@dduUB;D#B7jhqu z3!#>e3+PFE5^l`z7Bh2tERRRwNq0&>E5k$?;a)F8Qnf}krGVMn~f-? z(7Obc9jT{3|HKosE2s0G$5N`NNSahB*z2KM=qbssO;4k$iFu*Kt>FzNwEIX(@+AdO zF`dq|v`-qOX+GJyZ-sQfT?y%?1=8u%!S364=Y>l*7Sid;fy87pG1&%MC*}}#Ta`>V z16ttrIy^zLZXn$@MrUc@#FR$YNQK3Fg@eGj~ZbJn_tZq(*SU1Vb(dE+5 zEq7^SxeK*i?syLCgXr2@?t}J*7o8C_JRc<^7h1jJ0{u~+IQr~FC`fR-X-{Lweu?k|9$%)4ZDu{KsoA| z7aV9eu6IOi%NRAwRc*Mq?Zz0%7ow|1?Q5!VH_!s$B zH~t0tTWQ}+Z-Y3^R(cw=$CSQ;y)Je$Q*=e+=3}k)Hkw(TS?j7=zD^fuXfIXEK0V_D zPdstMN-fdhsz$yqqExx@sB3II*xVdVFMPAkE<}Fco;~+PR4F$z^Z0YI_*#9fmUIHgPm_s9@DWw&Yw#MUP%HeGX}T2|`jA}# zT|sP~_cnsh$kYAu=&n*tVNV4V9r6Pak(IZ>Y!`1wyKcpp_*+InIlULJ?~K%Axg!T( zzHb*jc~(;@@4izipxGw8%jiR44wM?Q&zhBuZV??GhunNB;vr|xs!@RmEeeWD+Wlq9 zz7MpnA1ZCXJFRB3U0M7LVUW+AJNfUt2^dZ9Fy7gjn7C`l&Ye44LnO=ki(x!e5DMkz zhe8F$2gK%2Fb{u&mJfGf@%Pjon8UunT3?vEXHRN4y=Q95q;s~g3HUeTw@dGsvHp@% zK#$4K$6f$_+5MhdY3y{-UT&1u-e1wU=_5(NU*V%Rsk}@r#8J`g_{_S1?YLqZ0q|** z>N|i=Ez=b5VdZJ4SH~IL^|}WvRqQ9_R13BraXuV>gZLi1bsyvh8{H>squv*-S}T|BwGqPgSB^rnmiE}qd*Q zncnP~U$!MXtGXTpVO$e1fmYP{qBR zdasobfu6Bc2W;LcHNiOG${&sLOt#;{)@#Io|kG^VYLxzrZuHW8+BK z+0XO*OO-jdht9JbsjjHcEX}woo(_dh&d*4DOV`$HUm!V9{5A7R>rS46NeKz&KfM$4 zjpFGDbiju+tNe?DwENf|_etXZ2yq`-t#Q;+b*1fXnKGwvXcg;Is{>*DD ze`X5`dm?!v_C)Z@@V7Zt$A@&=5cL?<)F@F~GzIHol=L&7TI_iJ=rq>VVTn}^ERpK) z_M=?h>JH)7S8b^9`HqxS-+^QlQiI|*T+p(dd==F=q|6X6L?tblzq~wd%;JzPE+u`_h||%rqm{&SQpI` zAh8XCd8t@dm0g^gtp~@d2-?-EBiE9G)-C_cRjIAtO}&4ZL4Hjq7WbE0_f(1FJ}oqh zUu&jkHQF+gyCI`K-Gk$iat;1XiAO^FN&6^S0c#-h^c<{PGYb3xPZ{udoBX+%s>pPn zCn=m?n0g=(E;L@_OuWhY_LtdhX@Ov>rEBdTChOOeuQm}4Br zKqipm2QX>mBa$I|M)C^K)kNYxszem(`yolrX)L7cvNy=k*E8rkpLCL?+b~meH3bwC z;vhU8N_2Y(^}_k8{GQlBqOuKBK$uq0J&=1Orf%ib3Y4=Yt_^eZBknrVlgnn(d(P5- z+9^AfZXPiVU-OYg*Q_~ZJslAh2Cs(+KZlqRDy+6ER0DK2tlu1>xncxRIubMT=~l=8 znylNP+0r$I$UMBByrbgE2plWQ*L~pKVSR@RgxG~+-zMK&Nzbd-6g&agd7*+TtZnJl zV*5$hfN~FZiX}PGq{uDKkNZ|`d5yPQEylA}pWpcE(u?!PWnxd!u>Q9hj8s>+Vs5@} ze_7hWIWt~wXL&!e=-EU3EU`KI6Qy+}XQvD>zxKdNhY55j6r!mUK zzd@RY4I>9S;y4(j40PmbKm*&zTQ*i7b=7}%#_YS!oxA&#Yq(x|-wd~ zUrss#F`!A$F5+`0jSpZ-MpcbXU`pTx@==Q*(UwPjIQs@Gu=L@1EfgeGt*_zSRP6QK z$TaDR9b<{^3GS9@3adhcrl9%TG=<0jGUt&~%4igRSH$g5!xw@3EX zEYsUB{Vu<#u%JL~%FVc1!j4^QK1X=2(zv(M_y-Ce`>+7%Uq-lM6mtft;G{4{O&X&n z^-IwG1pVV6K+#Wj6^OtH)(7pPXHw}i&k5*j`OaMWPE^PhEDx}H06wu-L_wf9!;sDs zH#UCwvafo!fA!dn=Qo`nevR?jr9aM}^&9`*e`edl!Zzz;Uq7>r{%>~7{rF2bf{XNM zE%_nvn~Nyc-4=Jwp7rn?d1#JtPM;g!ByB5yAvC7^!aVxS-YN23(C5Mn;3h0_xgYi* zyk78xNn0)P8&476H25UGO0=_|I+71`w4pM@CEv0-SWccog>52s0OdrC3epi~A5n~{ z4Beid5Dd2Yj~0y8rR62vY<$LMk@fW8K+*ZJ{*yZw7AEr>J1$Ra&B`_dmz8e}C3q4| z=GoE*`flimKe!XT!+1GOy!$303X0>dCCyAo~$kg#m%_fU|9$qwJj)irjsSeie3R&{RspFD z15b}!8>8NmCs;urO7W6Y44)XSCG*l8#I_TI$y?U_x52 zJ+A>)*$wqo>Bpz8CYg9iCOef(%INp?5wCGd9wNDnf~#?%;Jh@8856fsMv3|wEXpKJ zCDD@-iHoVkMT|ml)K8zW9;NGEu!)N7ap-8Ne0?3rO`J}|-wtFIkTO_3qz#@amYK|H zi8TS0w^5B{Eir>Z|G>gR-}H3ftKXN99Ph2n$@8TJ ze7>fpU;ZBQS^8=?uy=1(?#98vfna)iFvp((J%Bm0sN|DPGqNo1)g&EYjIi#l@#SS7CVkNg?7)l2Kp+L_Gin9lSz<%t%*6u58RiOXM0q;fh(h7q3i!7j9FeT3w5DRvMFb(7__VD~ z-|^UEXTDC#^wdpvb>6Z0BWX?hs4j_z$~CpWa^nH>a+{SqYYt5;EKFFp8d*mtCjLiN z91LV;=liH;Njz06ocr7ZqHi6(_QpN$;w-A(FlQM*B9x37j4o+g$v>=}(fEhtiYU|b+HLe?!H9laVssZd=;M5G#UbSj$vjl{4OF-IUOQ4o`z&e$Y^)i~l zb+H5?4H?a74_#o7Xr6uxRKY@}A=Uu0Gpf?p;q7kJ6i$>7OI_X)KL7Q)$9n3~qvi~J z2?O+f11n{eP*%07kldQZgNehEy8G_MuXwh9_TY0(wL2f{xGS}KR3JDrfZ&L%&Ww(Z z`gb(UDQUeC$eNOgiSL#Gmk~_Q&hz;LUTA_sF?%00MWG_`lbnBua@}48k0>ssT zlGk|LfJ83gPoXPwJDYNe|ZJH^vwPXdX`>WOxqON>6{It0M<@w-FP zs9C`jP8|lKafR&cb)(M+mPgZS3bF56h~M(aBbX##Jo(TEKbU#%_x6oEGWu{@c+`fp zxK-M=%EQz1^V0_#W{R`s_ZWrK)8D1q#-^E($q<%VGg-+2b|TB6nD$f~;)V>IXb1!W zc3uXphlP4>q-km`Dac(brGTnb94D6b1X_gGX4nOCC;Sp6nnIQZ*T{wp*t^V<7d$DQ zLvFumGrfB|_3FI9l^*a}Dg&g`=YDEO+!7MpK%apuMW2oI8MtWl8KTcaE3_I6%Vppa z*)2sF08(0y7O9&bee`Mw>{Wo2yf-m5&_aj1&YL&eQ|OzItbaJQd3#=da$9`eTU%Q< zSI_TQSlBW5j@0CX&Pn%Xyi#W8ckK9P0pU!Hw4}6m%vpc9A9_vf{O4(3+^I4baUuwI zI~_`X>*G4K{7}=CDYtHuww1ENdcxMgN6Ds?e!#}N_nDB0%q83*h>{$A2fTIg1BcbB zA@)G2z7F49lcs=atRwz&q)on+qtHTi(RhIEPrs6$3!F3dadH)iQ6L&8=qYMX2irm0 z5478LSr6K^7hkpFFnVqOYH&z3ofCHU+_@_u(#hXeJyLsj+VpsK$c!&*J>A>bZ0t;F zHSX+A**i70$7r%;{7gwOSW=kn4VG-LKRCLuuyNrE=(rzNAw+b0wR?n-4_vvHci305#47{f8II3s*`W8q-Vp^Pnm#pecc86 zqkHgdw&_qUUix;^v->oKcpRdo19Uh1G_+{h{uwN3I3LM%P&PbRrPW$AS-GE1(AN^EH+Id*#HnQZjCqtopBd31Pe26))I&goLfTMqu256Z z(uebCpb$K+vCD)cts!$PBgJYleG1lLD)U*B3n|^5AYjbMps*Z)N&9@~Pp1g#l z-^eQHOD6O`wx45t(oI97)P!P^axiPQ4ES%sC z1Tyj!zjzEIYicMC_0OSs@%DaNcX*Y7Zt)Qh5VvpDt;l6y4^KN?Yo}`+`WoWV&BQs` zH+0Zv!JYT$UO3~HBk)e8COemLd7504_6ar_S@xa-taCgFivuIKCSF-lduxL44H?N< zIZYWyO839tb9Q6U}(@>bl{a1W!^*rIB!GVd2oBLob4>nE#G{t(v&9F76@X9jYd9 z9KLalIJ{ivIJ{7Z0<_b7Ic{X_@U=;r_{#yBFZ>Z}83 zM#qS-^PaAa(#Q#vCk|NB&*rxpH-0e3pPX13w5)9p&u8a(eSwUg(?{p(t+&s@6%h^< z1Y|ao3u1F49TeP97!D@RmNfZ2>FI$m)ygSrC_FKJ;>2`rFyH7_j)@OWt2Gm2@p+oN z^~BGfxX%+uQ7a1mD1&&+XCq+$mZB*{%h~3{Nn6s#IcbaMF}z=L4W5U5;sfVCJxO{P z^Egjm$Ih(u0wcciNdHx+>yR;jzeHmYTah*(CV0Pqvk18cT0DJ64?U-cW_u;aycJtR zglACD22VAKfU z1E)T<*}BUd%+B=)&#!vqkx#a@9XxU3;Clnb{!DLmZd%aq^KR}9n3?Grd7kX<^119l z*tkU*FJEfraeP$iOvFkmC%Enaem6ha`Q7jf@@(c6TX>-B z;lnQ&8C`bG)w_;=+q3-}N33$=zpYxo@$IEw%$bYAft%mgdnZV*0PIJ~~b;qOo5~ zv0vz_OnTEAn)}^x_Yjv5W#`y$g)8>!QSZ+q0#zsE8b(x+rodsg{g8PgeH?6pJMPA@ zT8X>ScM_Ky)VFwu8*RiHScVu~@EXy+nOb@MB|NC(YPV~IxReuBvy>s^a=}*RRxZ@a(fig}FzLgo-F`o0(bJW2Ds9 z9-p5-{ySwvKU0#KSyGyn^`}-IYpi>c2os-0az9R71ey~zH2BOmG)}GNnjWaP#BJE^ zLeC(kD{YQ$2@((BR}RoG7mFI!HIFdD{OKQx6NfpMl{zX^5^ss09kNGgw z4;vk?G2W$?s-K;(zIn#_+!yIj*#Ow5KS#T$3K|Ee>Fse!0>@lSmc?9o7BdcrWg>3| z`N-JMC%chjwU9j{{A+X@)^hkoROGZYpi4j4Co0l{5)n1UkE3|0(LFeDD}_trgV}BV z#qQk&Sx&H2{mcy~t-rKfJCqaZ>6}Bb)EhWBSd*IJGnJ)n{qls{-hrJr6n6vtR$v_v zPfR3S0muEEl^5O|Ct@hq5iv}pD>9P>B`97w-~**EYD05f^&#CR^%-a-&@~mXpkCC8 zl956;KCOa!?=rk99+-2AT8`TjC`0O(YKJC+|uDS!W%z&q6&HAeMnsh$lV4IEBdSM$!sf94GT} zpLF6Bp95Z?+oaMXb|ume>pD;$tWnD^P{lubPOZMq8Qszwe!mWV4K_V$lXa^(w?VgW zz^d%%6m`mC#N_hXfxjFUl8XHK++_@K%=c5tbe>{&%7I=JgFaCrs5ESmUt0;c8ME)>GDVA|H@9w*ef)$~P_-iSKaqZBM z-}tC9c7A`%`p>2V->-rrJj01m7}XT$qxePnk;e~BAxPo)V%Z)Vj=P;kj9RUUF9xmP zJQ6srB$QZ!n90(HnH=q8Cb^E?A1oh!o>)GpuPbd;G}^Eqp%F`bV=t@iy;c}F!91*p zbgFegoC|6my5kZQa4;HI3n-{rXdOb>;cVuOh)0BSa}qa)Hpbv@BDzsbfOLMx*zxr4;EMc5-(1+z7G2T1Mg`*L?209FQ#qSfZ z;n#&-A4fh+w(FrufD5H|;vL5)eZ&*!oDAX#+b`II%N_8IWoruh12(zXHi+=BjgQeS z_h6R|Z-hi^@LBdcxSOqea9-}HrT1!8yzbO(4z?ZlcU|BpHSU)vwNvMiSWnJ0vTh^P ziX9bj{77o1P#;fCU1FCL9C-9mqumY)v?tUV>)ax+e$m+YwYm4CrMaR5|5QK!e3=Rh zBxk&5?t4lMzdd1%KBm|H=V`?TG7Ec$O>ti$Spb~{t!|Jl&)S-GicoHyB5fGsu=9Dh zvi!SGjfZ+Q;=I&`{gN!l<_!Ur`wRd(XA=ee!{BZil^Bc z>7so3;Ccdu0JKk^UHV4RGFSd~f2;AXZohKnx4LEUx?lX_o^UW2#@}?q!S9qrc=9`n z!?UyD;!TvunX5$c$Aus6vR(`q6@~MPidYZLDm$Jf(iitmTOP0qa7G5}WLRBUn!@Ut zq_~+wBTi7y(9Arl`4kJj6C;(aE?lp;z>>zf7<@gF>)a+>hrf!mmSFXAu{Uv$mLY2l zXe#B5r|5o=4yT~p$_Ry`4&2OXH-0os$G)W8;7?*N{A6x_1>Ep|Jb3MiYfPim&CjLZ zouD%(#%~$R%qrYabbWd=x#5#jPL=nE*$r=a_w2F$!)yGBZLUS@==LGbpM+m@pWJJ@} z99S%GD^0&OG4bWKHMgcDzl|NlCyTc=riIB=JX*B91^!|4VK)or^EV6+mxS}P>w}jz zA8iTehgx!9#s1;zYDU9}zQlO%4RxEth^$wbreee|kEu0{ZMJgqz``?(u>?FU=KYy@JL_7gP3UMZBL!1dd0Ql&oO?>p&RY@CmRg9Thp0UHO zNRPN8;~k$`h^8k@cJqg!uHrkxY4P#lTMnZ%MN-|GM1zbSOQ?6F`}gnBf3oeZuqwt zX#oEgV|Jo>vhn-~YcHh}@Uf(mD&xi~RxbOV{L(@&U3Z za1B1)_#vb2M(Yvf8eElGXRN2bMt{UFjF)|$*U)$g(_W^QBJKY~;{|UA-A=2fZ3#e^ z8EVvHtc$l07KV7!@^xR{naiEnnZr`xh*g#D1uS8mrhwpR))eZ6cW4S02clQ(T?|I? zE>=}T8Ojh-*@2P6%y{|3M*DE{t-&{EBxVO&{m0t(rsgHT>iaU}esIezUsy5f22NT1 z*LG)RcXyofH)drgW}e*Go?s@JgK7*~pE3)r%OeJ&&Ck86MmSEz9j22ek>M~*JYbLH z@ERUTxqdMoN$JZO%R;#`mQg`X+6RcIn>4kFsLh%}Zo@WBZ6khfSN#4PyqRmr;oHUC zO{JwB}Rx3^m%+$2jYp4RdDWX<`=O0kW(!JRv^^SZ~!%oLXLf0;?vDnD6HSU(xB4NDK}CsQlePi~j>lPOt0nTlLLxee=QnSLrT zt?X9=CL6w`wblv4@#?NyW1U!f+#Itu_>E6n33IEis-HM{oNB~^FIZRi*mi}V-mr?a z1#$_1!WmSY@y89iEDNEQb4J?1nRJ?Kd=J;X7YZJ*JbeuwN4Co-`e^qT%Ywd}#wSN@ zP)k>?V^)>Xm1rJd%p~MV<6idN2>uhub$P;i8t=4Oi?O6|9r#L@0H(~j9*y)=*bRLC}U@Vj2+85YF+>P+J&DLr_yOK zrY95rwS+XP>l+V2#jlW41I_)P*^(NzB{du&DW+CRirYm}Oo^nJ5=k*7lHv-$;-#!4 zp7M2gNP&IEb>2}6J{Ooy=>^{(vKb_Y3s#cU4@BKxMznNMD|^$h#>u_NE?7fq1f4Do zDEMEyTXqqSP-p5y6 z@t+p~VND4;cGd{y7-To&nq#Q@GpSY}%razF#L+M9ijW;sD`m&+B0Hu;c1(%vm=f7R z|Hya1VyV)UiBqn%jd=@-4`V3K@A^Ns4 zefJoRl}+l&^>lrbu1~Hh+htBvC$i_R?aHy4H6&~ux$i!sVztt)6aLkuZ2fl)rY1#i za?-QIc7_R^LUJRbH}yv!n;8qJHD-_J&17q=qp`b*>YgILfXavPM%7RYd!wMmy!6Yx z)LN)pd5zz<_sBZ{VbHey#L^W*^ZM zEQbkAO%OGusVS1zG~KJns0a@^P!*aGrAvp;JYzpyT9hxuL~m8 z>S$Tkkr|_Tq0Kn8x*%DO+ewZhMLyFBa^xsf*Iyllk~^S*vx#5qA&nh{l3o`dg_1i& zuKX=4<;v|MSEfX+Oo?2X61j3TY=TB7@+3?eQ(NitR?@^58Nt%$5Zg6XBX{Llh-gjL zCv;hNQMyZO&p`3~V~-h~kES;7q%@cI`1)fp<-NY4;X8BpMx?*o)o|#4D($?Nd*_~8 zP3G1hoJG9nLw!|e{%(!iXC#m|hV0>?Fi3V>ZI7c~LP^x?3Cds)KPXP6<%m}raS4d) zOnoGM=Fr}h z+d-{+sdX>OSR*<$)`3rj(aA5X)kuw$a%fou?IZWxW0aputC>WpR9{)!rBo`_*pt$1 zyt&1fuw%#0>8Y4f|HhyH{Gq&1C^t70%G+PH@Pl&HNzL`wCR5_Gx2dtUAaDPEDvvt2 zeY+W6P5!^0vHlb)EDYrqVAF^BzZl^&b#{Fi1K9O3FJ;%q)N-p!dSTAPYs$T3*T+=k zu8-TWqF3tvj+G3lAa)XA(?;>18ibC7O^bp~j$sqki)y9Jn>){1kNa2K^1bx(13$4o zcKV71$|i901*eiVkniDrG&kUP!03)6nsWk}FG5A~B~|xA?FYu#B8DWrQD-DejXl&p z#EJ)`sa%CGu|!j_kC1iG-wIAK;sSdF@xQz6|MoyBQY8tFteBIvd|(D#{5t$vD>(mJ zW6=7z|K}@Qf#iU;Ic7a!-Fd)>-*JBP`ZVK?2=~JEW|HFBtmih;DR|EgReATT#4}jK zTzR)cSKb9eQ79l3fw`t$^jjpO6myg_so=AbzT?!lMD@k>@(YZYtJ2poW>GhhYvCe( zkCB9|7*r3HcH}QICYP%pa&Pz&dvzZmDL2x+gX-IGqRm$NBdDx9e)DLWzq|J}l96?3`35@{{O9f4 zt>?TbLPh}tYo#;DIy~7gwRNYdCe1X-jL!$!pitBQU)I*esXturj6D@n%OtXruDj-L zWL;g(s*i|0tJEx~R;#L^>-aC0X^m%E<|mrol#=}CTr)MjDfr96@u?lvp|IDNYQFuJ zTYeyHU#UX&Wb|yBD9i}Y>E4ZE_8r_mljn5S{(t$*&)4dTjXwek(lALXc zF)h!;n8s;Z{0*pSvq4iEh#J<^FwHDfkO61q_&WW;1?DY}mymvw;np{*a545XevcjB zdT?OJt$~H|x?2NhIlO+Vot{HirG4Ueqy3wJT2^w>TEdBc-3%oOKsh3#oqSj zmioF&IM#ojxW=unb$eE-+CCOTqc8owailpnw|S(oakM!vuX(hwuC}(0{*2xT z^?r}3as!|%j?p+Sq2Jp~n(^brNmyx!G<&FpqsiFK0k@Y-V;1LpdKHIK^mX1BNN@OJ z3iLGxBVDT7N~uS+rclWiRUtVd(4gBJs8@@onD6o(tl5R?rFUXfR0Q54qNuH^VY}?G z3{T_|>PZXrm)~#Kw6(V0z0Iy^d;I8Zsr8VVf+Dt`h&jHebLz9JxvuS8SzD?%Gu2-h zpI%v4mwh~|px78+eORltcCY6Q$pWXkwa~tFRGr@lJpilALv6gDfi!>;TrLf{4rv5+ zZ>-aWniA9kJY&)yp0OHDE!W}F3;DgRx)*TkotokZjr8mzX>d-#sO~XJZM?URkPwAZ zRBj#vVv3CT*a8CNz!S)7&cEF*VEba@ftj6A3fO)orj&N!7~ODsfj`4jQ4-Ee98J&7 zq_Q_<0V-gdS5WAm&kPqC?_AB?{@o#^{~4Dc@wHFWyg_7*Ey+S{Nzy)(=8URhOA_=4qA5hyR+a%i9wqmbyul1&zwCJljT&Xc99Czb}mvPpdE4kqM5ZUqNVtHSlKQ( zA-9M|4=i-xz!||)6a~Q}ZP>%EMDWN}%%B{4BF7+6mjRj{nZK~lr5*Npv8GV>vqDo? zt7|m{q%3^Jw6Em+z}4!{E>khTFn34Pp1mX{*Zyar{!n?^v3bKKXB{fb z1zba|**JPHZ{X31tGU5+rU_7;^tJnqX3ZCP@lSwP0=h>RViWt@uQ1HML z1NV*bCij3_<(lGID%Vguu2ElWq|wJapmn+pD`K~%V2dI`k5v&qPI=A{wId47F$$XV zc2*IbA9ku@%xSMQu%s=jsCQ@jar5|*#6(?vwj!n!7OjsPgMUKt*^0up!t%m`(ClnV zUV3#e(inS9!x`uwh=>%vIBUI7n3r3W7xH-M6ja#YHxo9jg=7?@d0b38)HjfP;BADq z%b+&4kb&JZ6&Dh88|Fotrl7O&4DOHhGDlPJd>3j;R!_-VV2@%Mja`fj$Eqg_ki1Mz z1Qmt|?cCLAEH3bqk(6GsYxh)1CLzSqvUYs-Xk+IsCLOnO^EspDX6vyJ8Z|c=@A3N* z6TN1ZKQrH#Q<~suYc=*;d8TLS;2G=uPw5Z5@DMNdsdKmU6&e;OxpnkL$nfxxwHi_* zH9G1kM5BRm)!1iCUu4@eRoJdb7l&RFMPv*d_F?iY?8A_) z0$+r*@p+I!4bXSvUHH3!V!>HqOl>A!5+a>yy~M1{3dfM+*=*}voy9-gxG!+qizQjU zgo5A+&d1zYzN>YWe9Uh}=luSfxi$hS6>cor&S{y4O1rY$HCl~?Z)>EI@rPBVfjIHa zgjIS4$-_^pZH>x%ol+-4!V<;0A5X2(kV?`DU0baCAY(hAxSgZhFpCQ`RX`NJiJys> zV=+lma2K`u3ZjlUrIWM1InNGzKe-bcccZ2@5;deL=vicPj;c4=qT4ajFmBja?dV@B zOM$G;)urYLmk}AHPk=zu$sF~RqG0?qqtAG9LjVY*??#uK6#(=oJI~|I$VjiQZ_I9P zcVUmh`SH1-ypsIAd&8x})6>Quqsgt$`0mnoUm)y}nVl63`+UhsiJpYoMx$c=jP(+w zdgO&m%o3hwi=H7{KUcfGvz_-iL`0IUe>(H_@&)T`>gVm(4U1HZUiY2nCU z%x&_EnUY`3l>B0*WIbZaS&zDDOo?x`RDTzvRmH2ytCeUh?6}$A+)bab1CVS-)W?yx zB`?idYgtsF0&VQpt;W`y-eKh4WCbZW)ETpV7Q;CmpgW?zi@MgWmw$Z;8TvZWHb^CERC9xX+Y~H>TLu zl_xuuf`AX^Jfs%-RG~O4xps~EO;E=OdWS7vibK$6MmzFn$+SZsMx6i~B;N*vB=*=G zW#4oGh>IAKiYg;zmADQHW-!TWQd_!ljg;S2C3j8R!V5SiG6F<0Y+V8n$;L}Rab#N6 zDaHJmQD>6nk!`z~eDl~-ZzV2)>ju$`KH$iuP|+fn(ei(#Kk|R;^s|s#$~iuzx{ZBP z(!ZMeH|uNgj3G+FGK0RCeuztUlROZYlr~*~FG}8U)w--`Hc(cCe-@z#WiXLnmYlJV z6GE%%{Ic?}J67uX|D_bP&`tidU~+D5PQql%m`WlxhR&Wn7DW;iZCqht*1hzF@pnwu zHw+HFF};-z`6Fn`6%%cgm6lRsyw7;b)^)w4+YxItcF~&s-UYZx!4F1 zC-NLke)0^?-xdnmH9Ag&b^^A3gSTAz_mGsZYlmM^+MpjgHPuNJehBg&W0Per{UZeINs>duiyHf-Tx#4`^-v8NWv_Euy>Dwy>iah~|?ss*OaFA`4 znF}+<`i1qzRZ&C;rHQ=(uS<*v!7m$Chych6JNh_k$xxcn@eZt&lPq_z*H@_6Xb|aj zv1ky;jNdC#X51z+V@hPkl*o)J#03j!#txH)9H!6kZH&@qb(&T%vaIQHD3_hLTpewq zs;!&?d_>eYb)_&LkW`zlGM2DNck6LjT>rbcM=534mp{E#EW4KH!SOLsc+FBolA8`eKpJsZWb((_xjQ8hjzzBS)+shKq~C;bOB$&DB}YH6+_A71tVzdz|zt zB3sa_3AFyRUV_Dvt*LC{bh6?TaB{Mjuh7@A!zm%|VTU`UTd`unN(+kaBm3uonc$w_9L}#| z3j2RNl_{Wwhc!hJQi|9z|HyL^VG>Y{PA+IDA=|2ssD=de(;cOq)j7BNQ%_JrcHV6q zusynQk4nd$E19lCI`(zZxi}x*xM{4kwJp3Ze6VG)y|t~q`)Ur=UcIedWo2JeyD7w3 z+40dBNggU%TfoD;RQL_?MO4FpHyWIy8Yga)If23psu++d@?J)*eF_^y-HuOFRPgJ zY7c2ssfA-aCR#{0u!mo=pOf`E#Hk0&dAwDBsjwr6Q z!BTG2R3lM%BmRD9`c6%O>;0O-Tr+~2hAAv-4c>)j8GXN6FCzw63l zQ`vN;WjH%8DS2rXHU4G<1N&=ha=lfE1@0z`t{U=_~}E8kE$ zy-{u4t;92U+c?Ts8zssoZPB89l(%NzQ9@%0xU-K^F1NJ72VSTtMkmTOSWC#^Wlvxg ztczvQyj7L!|C)o=CgTxniqa=6|9mJqKbDTIJJOi8IB#aGGK3JnyP4`-_K}XvB-tSH zzh0qB@}zsohQO&b5;G!0i$g}MF60rWRymcR>!gzk=N7X|dbYQ=Z0{*)jLx-N ztj`-=ziO(gYHqHoYD%dnJaVL6}TZylgq+f;=Pq72Qcqk{D;}+%AA{Hc_Bk)UDfK<#I)k zX5GeCu6zSqxk5qPab5~?nfV=%=jEz7Q-oqO>P!=R?@!exQBMgKX9)Y5-A=&(;8u9! zNyYn7iItXn<3e};*~G*f61+ZtauOkm6DB)gFA<>lru&RW)4J1m!1`KX%e(djLzHQk zvFl%sH@2Ji-gx8LvxnAQJKfop*BrVbA()esn3(KINI5;yoa9OJ#CtRTa>Dwu*R$^Q zR|2L#h16;&voJY{5Z)hjSTo%fE0=}fwj6i%Kx$&bE!37x59r~ zr72|OaULFO$cn^q;yk|x{G}UcL~xaLsfXXAuLB7=tSRJ%j%o^aJ7NM8>Ycai_U+W} z-dkoxonXeY%9}FZ)(Xks%#2e}glQbf>^Ghq$U>OL7{&aH9hIRPoB3h$-&V@gy1s%! zHHBr^VE&)ej~mZNkIQt-SbxkbE6dBRFe~5>Iz@2`=*1vu`3dqJz|V^8c;M{}q8rp~ zb<17a9Jz1N{kD+Ywh>>&y2L1u{ul)zO+oYKYf9`&(#Rwkj@zJaDr3P}2VjkoXTd%| zO?i?0l)f@Wb2hr(Bi*x8^~ly6T<9}?xl(@cnvcd!82PsR*cUtcSNme+4)()@WS$l#wHyFh>R8UEP``i$7gMP}v2 zUVIfqtSg3-*7`qDR5Y7KcdT^O-qU;Ne;c%;*7(lK$^9UNtvt0nUuTuBg+Ff-SsTcn z*@U@7Tu7i6w?9v))%2~*7uUb`1))AM>Z-88W zD5Pj4rJRxTjBJ;mr+wuT`Ye`Barvn|!%-zK?ByHco+W9)BI3P#!{51=m;0T)d(;)ork#iZlgZWR<4Gg5sSWKcg1*?6O^cR3k@r5$2ngZS|L) zTb1$cyxZ?QX}#NX=}O-6_5k~^!-}Wa>o=->7;HJ->o-Q(>q}d-y*{1qWZ!{v2#{$9 zB)hbgQCp5`tJZC@Ym+q!SRv_;{Yjms>WEj%_y3-l%=)^y-r8*3Z|(9MPgq&=m#xaF zzZ~m4(nNj$PtGa|gLTECi%+e}mj_P4+aE`7$+%f3P6re(@6!dv+e9-o8j2TObWlA{8yyG^U$p+osO1ir>LU%KcH#Q#uPw*5R_MKjO{T1F5 zn^t9`_4+&R_`0RUKUE}DNnbemn7MVo(G=*x+Ch-_ZeVj`py|B|s(-bOSrmG&Mx(zc|{7`Zitlt9N z1D?4WO+im{?Suw;Cup1+dcQ{c4Edve45QBo;h{n&IF_rN@Lz1%0%uC86RP$yRc?0y zOwBiqUw{4h_0|Dn=0B5jx_i2FvvTN2<@}-XiL&N4^Vs7?@6FZ+o-lfEGJpD!k1j2J z`u)mL9vHQmh-A6V=7PM&(yX)on;Zws_V93}?SXmNXfv(rqRT<^ z{-wu4ZGFSFed`+=u5mmui=|y5+ZFS|3F~WKPj@sCu^;9%#amuYvT36ge6Kn!5xM{H z{l!zHBQ~~GuCIk{<(QxB!`A8N!qbIH8~iOmpsyoo!MBf?p|r23UIUsEOYx&|yL8(w zk{$9EIme%$#`Rg`8QAgt4Vc(0m$+A%Jii#33B2_$8OHl!O|SipvyJ4f39m2S!S0%)>kZR~YRrdGs(pxL;uXg1EybMzTs6@A7O z^jW>W6K7Kh;;l}%BENN=rhrc$p*MiX&W&)BZy%uE6S_C#zg1IP>E1TF7gZiUO5n0?#MY|D4e7ncll_T_aPNF*twMj$yH?tl zzhL|!advi*X%@3?Ui2JNx;aEE z-UBo`kl&g}+%pITnHb?6pmyRR{CJ#Cm`Wo6R+(S-MEoJ3Da5)F5x@y7$e57l1*un_ zrkvVajk*o_Dw0hgcX57;P&BbxE7{hf|Cg=12+75nd#q-^@uj7uIV0ve_vp#f1km-= z#GYZW7xvipLJj$h$5izrtZY^Ew|s7KtqaVp4K(_gf{$eFxy604qZrY5I>?-Kl0iB> z2gsZZ`V8rzk_6Y3K;;A2w@#H!%xr!laEq90Ovz52y)c4BkgLEV^yt2b7gy2u@g6+V z#&82ioqQIcdUvK0E1^AqpyRD zcNt}5iQMsitLLMS8y{bKr9%6zC=BSSJpK4e6Xhks2V)KNX*v36?4n-aq~W1?fRkon zrHa+(CCp5nnh%gMP=qWy)Ul8&m^VY3QkZ^{NhvW zK5|kTMiG0_aCVQJJc=xTpimtIccp#~B9u*{_i2W2NmYA;>vfzv(m4retHA= zwx!yfPt^+axRyY-Y<0!J)kUke>Fws_vqt}?S-cNE^pMf?U|M*a4Q0%1?(8WzusgbN zFW;K_kAzmV&Ujv{1$=GG@!!{IubD4J)qRXEUaRZEzod$MXY6^3x+@gVF{##|x#RHmsi>I3b{Xnn+rI2KhzpMV&4DtN-fEq>{4eLv>jUQNLc zSx?^xd>pbXHmE18r#lCz6_(Ag?kiO~$ZDaU&=;_DQJN@(ArN)n!Fo2Rm_eNUxi)z_4zgmOHFaSc!ZeNiX+ zp-Z1`ZrL(Gr-}y>2{@j7qDmb`r7IFXsA3<6VHy-lPD$`gh&ITICTRFYAmasP(^L_P zXv)a4XL|*4clm7R^L4N;Z=pMx+Cu$e&-PB;x0Cvc9fUc@PjKd(%=k8vrL51WHOZre zbpUcQWS!0vtU&F<%v3;v(~-By*hmx;1Xv=p&g!yK|g`EK8-;9bed5n02{><0L}Gj+02Qi;I)+ ziomBKU@s(h*ORO!G=*Aq%_MDPlGKxAISap;#)IsqJ9S^2XT-as3F^uF=mC8dT4Y31 zBlJAPQMS>ux6x<#;-=~IH0)|fSsm2NKB5Q}K?}c)b6;CYC^y}~#)Ka0?Ns5gef?1J z{L@bx{U1$jo}~(h>*5>V5=$|d^{uVTaqs854*jax38%aeQx{n61b?^p!H8dDAKXQ? z{ddJ3*8AXg`t8egLc6vAu!Cd@JIL5N0sCO?3tJs^Zkd7y75+ZAU5;Ejw##L{1Ix|* zu@=EDX9{*X>xu@F4x+ZO!}%H_GmtW6J<;>9W?-F=t3Wi2YigXRU7CW&WQV%5o$j1b zpWs0}NZ&zG<%o5ErFK|}pO;Di(bPjk)+s6gh`u;?|NTbI`LvqtHjMsC!06{PI*oH( z8KL@ty1Ide9BXfMmGL#}H%9u$3iI;|^72x0!!8wa{YqH<`jWzf2MbF|d+Ks?>v}v% z(X`0_%vnDOmz9O{N=*}cB={_Er7=@UGj4+X2Hzxog53c2u0E0v*NcO1GDv)5DRQot zWL0j_y?}UFUa=0fx||&18r>H-yD?26!pU-nhgZD!h;+A*q!5K`*L?-yMEf%8$+)I| zeU+1l#~5S>)+u7ctw{k=n>>6b} z{%Oh&yqRPOOyh_;qZK}9_$WLiSH?AZ&_euVZx&aoa%0J*A7jad5-d6Unx)ozxqd2q z6;+yoJqdguV*%@QJM8o(P03yj>$ZFkaxP@oCT+ZH6RIEjnk>4IRKSZ;!^*XVi|)nr zw1qd-JQ_|;N~#VmZTrx4cF5~Z%Wgk;WM74Kj~NW+CMG`;OK_J1k)GI;7tTsLUeT5A z&G4re#Aj4DcNCt?%r7=CiS0-s9gX?6SIMfFR>DoBw|+wN4fYyKOHN*oCM}$LDc4iz z4z{Uaxl5~q9I7Bmm(a|Cf4fXyFC%JDQ`iGlQ6EUnvFqXQsH0ZMtWo!sx+;8{LYvaS zUHWPl^3@)iHE}{Lf$Wu3b023@}_VM8|Q0gYYH}7fMy?`)|IQ< z5g9Mg6lOGg99wi7aLtU6sM2kyE?TdtdYXO9qUCOfN%YxfewiZXpYa+S0FEy*kDnck zHMhDsX5Mg;8C=(#xHwK2WT#BPu8PAaWJ?APu^21N0jFyMLXJ z*EDxot;WAt>;1-sr9aObx5XOuFC1$!(FEu9>fV;x{-+xq87yxRv9eLyQSf7_z(@}+C9@m^v)6>B&fd*A>5j~{y_N9135%&d<&q^(Qe zr2Mm!o?Wz#XVMJqB8zuSp`t?c-dG)cG_#}UI{+!_tOr5e4>nwfraI_3V!t7iHD5`s zgYIM$B61?+8%k_$Qbs@ZtfZc>)#WPI20D}4ew${Z`ZNX9TaS7&A|gQalYfc6V}!Uq z0xjZThHYc|;uOEcnUE|oLdg=xDOsX#M_b!;Ux_ij{>B^E-)QZLZbHwf!dk60wXLnS zHLa=Tg@+FpRMc&(4+iTudP?4ZkG1LiUB&}Zoh)BJY<)vzPN0A|@H$6T&F3KTt~&1B zv~r_DC$dQlqPgy=qjNHKn}aY-(rt_im%E_X^Yk@DisZ~i>EVp|GTjgO6xiFS+9Ulc zh{w@!pa!Lb(P^RpdBy;Gn&m2w>Fjm%AAxkEfvbOT%DUInc5?s8YgCd0u(!gOQhJX@ zRb>zHRIaRFYDZq&oRKy+XQYieBNR9jqSc9`HzE4PT$`{!w~37k{Fn5@-m+3tm2?-f z9|c zFK0-%!CD9M5vUP)22dj|@VEmNxwu>%1unOT<=>dE!+if6Gj>EC%CkG;=?UW{g#)5Hk@w4x^e|WmG#65FX2X6=S(t_l3rRwT=n` z7c*X|JiBs>x0l8mtvQsbcZ=V6%KYl-pDzdH8}%nIJ^8Hp%9pM?@XcrFya4FIy^24` zY1*mQsGamyoYS;(jhrUA4o<|=%;S89=s8W&S9bguZ_?(@X_7Y1X%dQanuKz4nzrd@ z-~`MqY8-FZZK$N+AZY%+Jg103{r@7@iHG>#o9*Np>zwa|a}1F0)IvM8iMTyRkVZVJ zEAxnNi8A7)%{}6!jrF%s(BB30WM}+4`A*Wx`A$MPXx(~!Up+|*UIkc(as~vfKe-3i zIU>LIsc{!@vJ14BT!&X^OjBb-O=t?9XUr(%>cDp>_w1r}#4mTz({`=Csyg-zU@{RR zkI1f}`0?`6bQhHd#WIhb2o=s>I}hrYCwHAZv{oimxS~SM??pAgQ%LJHsydK}Ffdl8 zaaF7g5K?kg5K_=%(uSHSjFk%NHdv_nn!-51x%G_3LFO)7o;A8n@Su#a<$fBSoZYSv zGSLyWZoz!b?6=1K#*o-OoIuG6l|;Xb>oNOi)TO9Vjk?!BO<;E~{TxJcg>FNoD8_N;={D?*nly!T6~!}K zt6OX7K91JnY(>sgY0+0(p!2X!kcCKDVX9*Dip&Hxe%)O3R9IjYw3w?nrfpb+PaDE;r!eleHAz(Ak>FQ(+sVu zX`<%r0hJOV6lI=9Tk89wmK8KFVd<#SgHcoRJ{PUBp!sVO*B;|js`wzu%ttl>%gm?z zG01rOGf52h>^|K>SHk<3CroT=gt`wA4m&tl45Dc zP%MpQdG%%i6kWD5slxhf1hgnQ#~Xh@r1{dfzW9k$CCeFm{*_RyeKc;1QB1M~HVCV# zK`mV?W}vjWXP~rU1`g`G;CGf8SfyLxg%7jcrU1V&WLECh$eS23>dgohd4Hh8+_ z8&^ZEL_5h;?g931y?(-adMfLHL6SFDCO~!`|8ivK0Z+SyJ~B12l9 z6)Qt}K);7%R4}?8s{{4~@(f^w{>rhi95u9-Yi+F@Y90zvB_1n_+8kxklXz);mAQ*N z>WR2*M!PLv#s^LO)%YN}gYiK^AtC@@x@hb;`W&Jeg?XGu-^(bZi^B)OmX|vOosCsq z+MGP


`{k30Szj63$~!-|vpR+Bg11J4?8L5u?CU&9z7cVr+YE-3o)9-+^XzV|oe zSo28uo3gBxAx)MUCtADr_f2H4pnCAE+TU-c-w%I@L2Z32R&!}{&v|LXoZqDH+CmagAqrKKA|aPxH5xQh)4efX9(Gc+wcR4L_E|K1|{x(3Pa;^uehYp~@65&D&mU z71QylT}$7JvMCXMzSjD@|2x(#2aKXcb0(_yM7g3~dT#4L8uOFSQbjF@ajH1=1LEg6 z@sn#oj7QXh5Nfqr5ON)3hxdE%^-1dlaYSlCNE>`g@TLQCC~fXq5YooAAcW#t5JE{U z2;dT>4fu7|Lp{WO-WhUzh$+SWi>U;=wp{+68WFbb`FB)_AV(OBQrCu+*g%l@ygu%| zBuT_hc;8qWW#1@m?v+N`u+kuQ!h5deu@i1xEq20J5j!ckz}0 z{Y;wQDSjGFr^^IbdVA;L@%lGq|2br&r8j5)blrOo;MmoasFA=Rsh78#%`ZKbvtev= zX;Vj4&70C1a>D8U5A__(ji(b=Nms+qxKHiLQIl+&ib(;@jNca^nlm?$hbS7SNw+$9 zyN$XHYb5WCI&~XH^m-B5>VACQo1N`D+jq8Vo3{79(yp}9N?MgwuPbR+U6v)8V!E&~ zxCk&{2%#hpT4=UongN3?0)&u+kWfSq5CW!z7Sl;EXrF)I?>lquyy?3J@+W`tQ9QT2 zH?#NLd+xdCe9!l~BUfkY$iK-OrQ{vNRd$&YqaVslqdg*AlmTd$A?!2sJM(5UL0@pU zq}KvkKIWp;^n-4x?Lx3cdDGP4v9ZHb&CT-Pru$M1w{z!2|G>n=K>tK#@Al!ky5a4; zecMOs>PEKP|CMBCz1g-GJ93;m3ifm=Bq4pELUM;CtfxD*GMRv_WQ#Xh=(kDn=q5bG#AX~e9KRttErbKRV@dr+t zI(m;*yYC=#yF9fPYr`=4M)b(oT64!|dTnn%I<)nEAyfX%>^%qM8rI=+Cl5x*l+UIR z&kdt}gF>i$ed}0IE@3V1=oLa``*8aCFL7Uy%_jG53ra_@tLsxBjfq{=cAg|DBf&DM zjHDDTBdLp)k<>-YNa`pfN~s(%fT6&ESp` zAy?B&jcl*>&nu@|-W5i!e)qt=(}G;Rc=kXIh?r}LTwP4HrMPU&!)2|drG6KUVMCjPeR*wLd&dA1@!XKChTn-YukcUJfU% zqf|8qRO^UT<=v*TUbwflno@LBSbAtwnD(_k)q_GbuSxyY5p+ZDMpa3lqnI*<^TDqdjafZ|zS zb`0_M1fdHjBsZF zEKhRLQt?80$Jj-qrs0MPTlneOp>)!cAPWCuJWp&La&PmN*NyJ2ZN!iY7IiqRB{@%J z|5eMg4E;re@{A@kvc=R9i>C-a?MIH3KGTC4fK3<`TI-#rRy~8z=$NInh6KeI;ZfAL z5#cuKwiAKMdtL>Bs?pUr1ZsMND2}eXGMcXYT`Bh5RGi)Z+yp8+>-@I!+hb_EiFbdN ze*riHVlrBMufXijz&J54D+9C0hw);3m5g2DJE1S4*_4Q-5U&H-x}*nBSIp&;k{7X| zbwq5?2SHYcNTjvKJX3>jr#FEp4UHMte!4jJp4S$5L+w{@z2%mz&vEtwt6M!e zIaXG|ocN**cg*yT*j-z<+TVZMJFneo9d{n^A6<3Pd4WHWVcX@!<)J`vWmcfK{}q3Q zZ`a%l;V@Mnj2MD`Njb}4ITSaOs?&bS?9DgN-s~Jr401m0CRj|*&e}gZdScOe=F_a-Cg#og z%?0Nz_Vq{IH6A^V{a9;X3D2wLj3l$cWlU(5MP}I_eboVTiLT(~r8c#Bt;$=Q6?*x7*#zIDeV77dwAjTwfwrGx_(V#1rOD zQzD8nGV0QU^Y?$3GfqZ(cid?I9_(?hzL05O_jnoP8ojdleOTn4z$N3#?xLUh_tZVT zh%K|H0@vEXZ ze4(3%Gtr=jT^;n|9XH*y(dYYHT-RC?v@fH)kls>d962JaL#Ee){S=h_txchv^tby>V zT0VQ<72iBYSx{y3;h7*vbIE-E{}Yd&%%Nj(b0|sn+AizOx5)l66a)T;4(-FPUzo#GA3G5#sHYu=_%>&8e5V z^Ro!~->a6eju$^E9Dt=s7HD{Uy}7pIzAs^XIktjwE{j4rYbh1VIX)LuaMGG_Dt85w9DionFB|O&&&BC&ZIPTQFY!mZdW?dhMFO|GVY0 zGS1N0QAsYJn9;u7l`}bPm18r^%?LiPny{p4zr{*g7#b;QvR_GwY$usG2W6smhpF9> zK+?j>l8?UhL>8I8M2VG}5*ZE1AGO7uC(6}W1j|TqU#Yno^>?-4t-a>08jqBW9cBH{ zzQX#UrD(23k-S9Dz1iBOE`uXiBR~qSeq1tZqeuKFj#z6JpRi2k#zL?7uifnOI4(vZ ztW%RWt^(rPt~GNYhQHCb&zcC&0iJDR=Rl9y%Mvj-UIE5Q*$?+5m;>UgkasY)F0(<{ zy2Ljsp9S3|xlqbE@~6w?D05_AoObxVSsgtysaU`qnYUv{I`YVrss!Yb)-D<#;){vlkMx~2 zz8K<*Vl5EiXQUNMds9j~&`+(<)28-xLJNd`PI-#wjsMGBlA>MC#@QY5+9e)8zARQr z*Ci9yH+TQu%#sb2mG!luoQgVslm_}kkV{(svBy2X3ZE1?=XuxAuzPn{F6IcmF65dI zxK=Drw7IYibmow2URs!Uo@Yu#4-J|UeKnFdU1;ivJSX40JY9+&f-`9|b&S!|hd@la z_9OnT$&{Es$Q)9MGZRbK@9Ijj+lz-Lz;x;2^gaU1#Z6Oa*5PCJ+$YjR@!lJBW@leJ z|CsYO{~f6Vc~5!4rJ(gYIKXHJ$Qb9~FYU$e8~1$yIzNcNfh*I(2*o4P`%SIJAn*jn zU%jOHrky9mE>j}Ty$JRjcau?5ORo&0p*%0byMuP}NP;0M{LK-RE^|D{=}#1%w(^FC zR#T#1Lp@qsy#n?VO!m3cG4*8N2MNc0l5_hr`&5mB=sK=&}t`UornYc1M)_ zB(6KgYo$a@M=y<($etuIKcWewju?4edE67FHsWU{k8%WUAgvnllM*9-E#^sjT!?Ux zHetSd2){hmXO=ipP#VU(XJ!Rr*j8QXq(mYd89%nM^{(7(%U@~d2m8u@G5A-{G>f4@V{W`Jle_Lqn=Gm1Et>qnMcjkA8s*8hfo0ty;3JVJB>@M~7AND`PjlYh= zzj452+@LH{`^YE@@sUv$`%H=JBNBg=9`yCsnI2>lP_M^oQ>)pl5{H-P7>AcUao(jS zbsO<6-n}Lz=G;-U$-41+ur$j6d_&=+;w-txz7N;eWwy3~qd0tOMA;f){Ms{`1J6*-T* zf6x9=VOlECmpFIH8Du`6J~M++m;GeK)De@v0(%eZLlam11rE(q@~(@Hk_ep4bY zmRNd0k8%HJ9wGdm_(X4LJgVL+&BUw9i>i0+fjv#@4v&u?S=ZFG?#TG~;dM>cL`vOu z!{or=}yf4BOxU@iRU#ZRz)nRsR0-_zUMga27C<1)gG zRL&u|64w!LT9DG_sC6WDTt|hb2k&mGh6KfPtnqiv z8E!EB8t@dOV)Bj%-w*xAQm6i7(Wz2Lof`2ZOPzX>r9@9M*WT7R9mtiHf>k=jsb3VK z)s&W0da-8-%Wd)bsoACHlB_VUuV_x`?Y>1wlRh9p<|{w+|1PUE^X~MUnRnOjt{`%F zbYgA(q4}kS!;5Tg>G1mLtw%CVxA9<}o^ARaDUata+jQ@a9cc)sQ=ZR%bm|-Q<43T1 zZy_^Sm>q0sHxbf{ZpAWH-<&2K_J9#_wh&zKdGvN1QtiFOMhkgs~Lh&s8F}bS+ zwLse>K5t+Nb_k?G`@;WrHo!s=NPw{lugZF8+$EfK?eJ38d79zM4o}QW$XL#UB z&gPM!ks<5)zqVFx9J;gYMMc?V)&jDcDn5mR<6+EhAZWmjA|!KP8y(=d*MI6v%mQNz3OH__V7M7hBo$4vY!8SXeX;BQsixX!fmESiayl~={OYrtF+ ztEvk%Ji!c`zGO&Y77S55`uGFwW#gB!Z+qgUtfK-X5WetvoA#8xQj#kJMBttdh|FfyX#V`GBLunwZw&J|pExoUK z|3I)ND_gC*U^*d1?xj!u_W5V$0m@37m3b+FEUlZeGRLilCW5>u+M3~tOHO|~GBT3c2U484h3DK=Se-vNS5>=V#}4b_ zLl-`_`00mnO|)HBT3#KwC%S0h@MFHApqOpKqP#=q9rWEzn$jd@3v-cm4lp}eeI4oeM)m!QS@&v4`Ms(kA9OiJ*J4&M z6Fo8W1vi|87%D3)P@%t1B(?oX_(dr`VHf?kiyw~Fj?Om|v5Q(azvt{blv>o4%bfpN zu3Y+X3XnU>$m7@T%4IA8XPwr0<)U>W7cGfgv_!eo;5)iqNozK`R|d?HjpnH8F#S~q z0~q50ylKR=@VrI;gm4ea4X8XH>o@UyOh)}>$;D+8Rlz73p=e}s5r&EP6Uk~z_)6Lt zy^?kgSJK*-+?DpP8wM|jZVMKa=T=r$WX<+(#-(QY0XvcKzJ+UPJ8?;&T~Sz89S9a@ zWDN9L&wTgUcV4@H%d7Wvb+4a(N#Q_I7A`x@yK&oKZbnXCgX??ZI@{>VlN^LIzQ>?f z$;&13oJk;0t@FxL>qMSf5_xKg@+5<)$Wy(xk#)v9YsIISPR9C<4!p6?ypg%8+^dy; zqZ^+`A${JK$~;xxPb#@2ih0^-o+YOWy^70~`A94-1)A5jV-iVv%{}*69d{R0Z&sez z3*?FYo8o)Ed)OL!_um94@?^68Rj0Xu+NFuz*-~;E0LRmlUx0{JU+#t+$u$V(c*7Da zNRydma}DYfjPaJ?jl$H&vs`knLG874u0ef5Gm6PIsC8bhL9HX#;JE3*{a^x8_R3R! zr^-|I%gvYt+*A3>#hUV-)lwoyQd>(dVq~^6Yt(ro?i%eMpQ=ChzV}%}@5%4mjk`t% zGdrEj3HDSmT<`DciN%WCJAUG4y^)JXzZ0*c554p3yU8XfHqp)Db-Tv(8XvSQtX=Xi z3YXxfaKy=L6KS1y?P{H@T`kGl)e_h4R(y-Zu#{~mvUay(WaHOvA`U@)hj0jLi54>R z;36xQIbXsHOKhU{i|}}nH*kmh#2|X^znbb^fcTv>9{1t3l%i71$r+evHIJs_3|!6i zTpGg|m`HVhClzC$_5AzK-naPBu_(GgcOO3De=g)tp0*F9@w(Sa3d);UA4RduL(k zUihVClLFDvg0o~oX1&&jc}^DBc#*UlHNz~{!K0ywtr`5RZZjEo)c zzkV419esANzqBk+a;agWHao)#_{*L#JC>7~m)GcD8!rJl@ypnY-AcZsHEyJuQ7GZE zS`%iuNylZS{e&k;OKO=izNvK@-y}Xt>jp8l66x$Pbz;G24_YwPW@C`c800cx`f)F$ zw*dPV!qPE7fV8YtdbsyD49~t_7^|-Bxo?*+Rt=s%bEL_6yIodMnVGk^BdHv27*W2e z^R45-KxuxkF0-(scewgI`HtpOkNp|nIt)pjG0x2zQZi9cgI=ep@4?&o@X2|FkBZUDZ7S^p-C75Q_BdR*tSln_@S{5inixo1p{O)P(owsG&2 z7+MS7A^lrWr~EluM?X=M=|SDzVM<)>y{1InEw{f6o4SY{M7|ti?SwB!Jq2-o?9`e! z%8(&};JRq8oKGYj*J!33_^nT!id@tfj34W%*T72o)Jf;xnpdo7Zsrw@826`y@8zw6 zW^BQ%7;y2X#BDK+3Z#x-R|$}QRO z3u1OgZp_y2rSGuMJlTgQ1!F4nn5RZy>oBL858RK>o%qZfj^M8`!ARc1GZgSSW*|r3g+kf1B3n6%NPIWCl~GyEdJCkUR=1rdB+d%k2XaH#`v)R zGUj$Q=Jh0I_J^SfxU)%AV9he30@^nc6&S$&Bi7&m#zw3`)r#Gwjh=#0Q=+B8eM_Fx zeG9({<0rlr$zD^x%UaXd=N@2q+DbW7`K|Fb26@XVRjj3C^URu=B~AM(Et<39i!d>iX~pKOT_}F}B4Q4~o+nDk;YjoT z{&2|QxP%-gOvvHssl|D;eW4R^ht-qY^Sdg_3QCSOjFou94v&2~5_MReUc$`9cuJTT zqYAp5e0R9Z!FSa4u#gjjJDvqQuPsiOXGGxc+*r~l2v;h#|QG1M2OUac7pQMhrb$R&MQ%7IH7j3nCBdRF0T>!Hc4 zYz8Xc7uKv7azX=jotYU$MTKo$J!O4E_A$q?><{veK9>U{iN1B7Ut4+LKz?;_?arP4 ztxoWB7d{wpGOgb(e&r_!TLjw6t0Ga0>J0}UEnBgotgIeH{?y0He?hx!!1r$G1IB{n z#=hQ^H}+|(VvT7@XdSIELG?#sk=n+5i8j+ya3k7AMm6$CO2k2#xyaZnpSc5S-#&65 zdQc@xQMtYd$HhxiFUPIT!ieE%xEm3}%!Kt6a_YO~J@0wfo2;hWZoB1-8w#@Q4BKB)QdSelD#*>YGw1#77ymwy zd2-B|y8pu47vFKlx!`}XGiH5~wn?UuVE`kz8dAdTWxhwT9(ZFHPgy?vtv-xP26ii9 zP0v6n%apRvhnYXbiAMNBiLlGXleuUmeyG50U4c)+Bc%xOD)SzmR+>zSD~UHTkT+Vt zmt4ec?t4_n4w^RV_zn2Z34ABB494(TciHu(*Lu8xh;y-YHlZ))Dl>4l<1_CilY8iv z#Eg(YtTZZ1N2pNkC%fbb2pjdjqo8_wIG9k^n{8sLfn@lg_IX1X&SdYG2(asD5o*;JPGjB3R&Qw+tV(vrb zLtY%SN7nIvY63b4&#*k3WOx>QElhmymx)EbGaOdjtzpGe2rF6-V~JxP1hxl%tM|~^ zI}@&H=c@=PcH~C~6#YZ)LYJu!xucG{`YzbOBVbh{XWUmY4_s>iBh>Dj3nOZHiV{ss zw1w7k?^x@sbcM)A9XS05cCQpxJ<{9M?=giT!a^^_BfJ$n!Y2yr? zGjhS&#OJ+u>t4L|py_oGZ`kktioIw*g7za^!{M_@*!qoJGuJvMqJsGw8@10$B5kis z?YfDv%lUb?78aD{R91zuw^glafP1ie0He#fATRD(2^NZ;{>%2HB0M5q6<{SIl0$WYz-Dy7$h6ze`J7(41QOXHpXu z+>&0{*t^C467B-VDt7wzTD-k(7NaB)<=JINl=TUTC~GNoL|J<+Eut*CU3_X&kebAT z84nTNuIHfDrj0BujD(2P8ROKaA~DWcv~Po?8LQzwrJrf#?La-(08v>o8zjms`eZp# z=7dKjkJe91PT)K($-L;g30h&`rs;u!*m(2bjGg#tUnJiAi;JI4Y}}3h^L4KaI0M#a z-HYtxJp6L#f=ZnI!n4D7+~Q63oFD73Vl0f~y6}0J{st{Y{0+MEQ@g4jh}h@laqGXt zyrTr)LHnH=gQpjLH~n|@t`=DdsR(9O+nC`pZhA&o$ycK%=K%LVox*& z*5NlDbiaQTJr?lhg@n2xyrm~QT%|Z3$K7T3(BJ%x)qYPw`_Ayabx&Q@)4w_KG_c+p z9Jc;?JS+Ra{{07DAXDO;^FLP319g>^wbd0l71h_r$D#eh3Fm}!qM`Q0iC|svhJy$F z>m4&c79Tw2e7Cx>vAU|kwj08FIa zYA|l(GS9;2Mto*I`YzLJ7i3HxL1}M6JF{y$OnV2~yWDxf8#m?6ybnx#B!Ud$-D29d z3g5I1-!zRkP2)|oriDI_4W`5s3-!PT^rJtG5mR})Moj6|6pMjYf=#r0X` z&0t4^{WmgHOdM{yH6Mvx_tq6$4&9-#>%CP|Eeu{S9>4hres)~>m!uwNqBH#DuO4u`Ny4$|5J z&8DAY&VM`PT946O4?CDrC1P13s?#YVs#kFG*7jVCWvMAiTvgk=aaFCOrO%T$eOX#Z zOr_Y1io6~$ZRD+-hTLSGQ=uXOIV%gZZq>&$R!Q63-Z=*jM_sxHkr**sX7Q4}n! z%`9qa@2fjsf*9<@Wa9IE6XIL^ogHxZbgzNmo*)L%uM_>aZ}*uN zjnF~ECeJoZVprRriA^|sYZ5Vq)#hqRHS9a@-0gpA`jsWJ(7Z#56Yz#1dXFS3KbRmY zuXT((i)WHKo#L4+#-~zu%v&*55>Mwjicx6YCy6=HHu6^RRMm}fV@!@w0(mNNl%N=W zf++4U`qgv)K@^vkNxooo{8 z-S73|DLLgsr+6%HVF6ph%#TA@Y$~~6pF5MC+c2?raB$B=!xxeWBfJ#KosU}UA024# z7#Qei9|$&ApFCMmU)(v>QC{9L<*!e+KDNC-d?H)?=abIYfVXIFuBw8Jm?J1yD@`ws`%YPvfS&lA^}_M~`(Q z190;4<%jVR|?=dIW)qsOM# zWj^^+9v$5SMX!tgVC+?6cS{*P4-O^O7=DN76XyeOx7u$@F_4aRgY#F9;vc43R6Z(^ zA`d|m3}bEx@?>}!$P?`wL7tE~O%NnRNeS{~gIgcvAubi6TQCsFdJwM34)|0C4xj-BM6du*i_l>u3wLpD+rQuj3ZGF)uxT}q1lw0 z@on`O?>6+K<r{!}6v1YBy!Bas~ z;!3J8CGKxiro`xiWENIpv?}q9j3-p#GgmM<$|SPYgHPg})>u`$c?Uj}N%BS&$-H%7PRGDG)L}$a9+S z%C*qc@sv_#O5{bYH6>y&i8c{-InBGtz^H1Zkse<0KJz{s-n6OsU?PC@xAfwz!=^;s z-H0iX4KD|8RCEwM-sC(kL3OaU2)mZ{)IP9Cv_7N^{m z7A4s=h$3{{TTs2#lb32e=F0WwTf=}6|I^}S`@7-OzvzxmOEr>R{01)55V_8|xgTYi z{ax@A&sw}sj5rMX+bx_4ren?|#iq`?GPR$qOf7L`4w(L&DWcoNOBllV@w76HvDDQ$ zfX}t4mpxD4BYU2fxaT#RxAL6N71)fYs2RBe75CL)dT|fzF(u|=aE?gak!xQv&ZqGy zc3;$Qox(HqXy4+_E1qp-PfW6!0}(ih-?M(>@dt__X>n&kf|YG=x%7?Rj!V<|uE?G5 zzvV4f?VIx3q7%|Hr-KRB_YKZPtG&ls|0L_AF6n0tp822HMD+4gd&nn#2{8k52b8(1 zWxuPVxgxlaSXd=paWg^dyfZ=TWF}}ybhMVJqpQsutDy-h-BFF`W9FvD>SKMH`nbU0@klwSq~)U7f7JT7ZcD6*kfUtFTOVg#Xxv(CdWV-RtS7XRwFb3b5%v| z8xzP~>%4N;I+44UMDALm+*bjgA~T8ksDiT8)xQcdiQk(O%>{i2=R&V}Bhj6-j8ytv z_&jnI|4`qH8AZ$y@B7lH*W&3ZQ{oEe+|lR-HOUN~oFj@ zx?sC`BN2hy+&w^b!FG&qye=RXEqY&QGw26HkbA7>4oKX?`YmaYvHE9#YZ*ry$)f@)y|Q512qXB%(F2Gu;W$ zTQFq3X?5_x-hKP67Q<^$7YeONpe(@Tbov+l`AB7}40hxOO9C0aJ@$l7hsDOK6DO)0 zHXJx`ZNd3*b$xv`{^1-z8{sV-CHHr;dfHQtOiy@Jk>m_W?~LyqPEP`GH+Po zxfPgW%DIt=&vL3H=1AW_bgB5d*)Hb|dSA3%IX8f3!3ag;p+`)w5q$qzQ(B8(#r;MR zP8&=M5im2RBsPeC6ZfJTdrNAs5#>rO2>_YUoN?l@)tF&?dVVq1#>T#8l zdR(QX9#<);$5l!^eKwo7aQ)IhDyRu#875x`p6d%@cp^mGC)P90&qq&g?YyfX@3D|o zP}o=YlabdQ4I#@dFQHF!@l*fI(cD=+y<=A+u88Of{aHbGMRj5D9TO)*nMDOfE1=6c z#&X`P$C-E9_Z5sW{ZxVwTa^MKrujWY7->I27->lnM$|Z37r}-NnL1`_2{ueoC%vYP z`}deBk;85X<2-Q{|IjjNS|(ANG9`Mi*O}5f?9NMKE!nl@EcXrlSZ^U5EDXXiR_$+Y|443!BzoCM2w{ zbY*d=K*DAVtIG=f0EJcgbLyK{7M>)<${Ukf*UpDehu53(tPqh!L?&}?1PRvudm_Q~ zc`p)7>mo=nVh#ie#wCb`d~c@f+`yEB|g>w z{vsm2sLc~2zVzwH2sfKIQaf>k^=!zo)&3mYHdAWDcQoTW1ed``nD!(3uFsUjf2eKr zAM#``XG8DF-k`lwPhvL_WaG)e#l>50%(#AE3M;qv?z{i#?5%?Hy7jDGoOCZ(yz!M7 zQ!h_W8+0?XV~H`K&x@8#0CPmJxSY3)qCpxMYf6M3U1_7eD>HPZsauIU<;l^0w165- z51tly+LL$C=hk6Llsau^8E0k%>gYw#VFRW&xn74&iJk>A>4+CF;(LSch@6ZK*oy<7 ze2Pb9UnC^cNjB%d<$Tf_`)O}$YhPb$Yi|shPEpcz;C%X!^X&+q4l(zF^)1Jq+J^PY zvoSS%HU2SoMk1SJIg%`MWqH(fz&n7njghb_Q{rh^(0M#{%hQa9wPUR7AY+~xEzjo? zd=`%yrKnG+1tz%=Vt28pXm;0jZ7!A}7L=~**e20_akJk8`C_i~Q>-2TlG}5!Unp}% zU$_Z`IrC1led_YtZ@J~IZ+)xv*<0*~FFHTYv9ba}mJ_Vb1Xa#2FF5bCuf1sTcdt3x zee`9EzqE0JlYBNEJLMw!EJjbbh@wYN*?|&`p0;uHyj(@HgM~0sj5l$l^fUi{IrT+z z7CnUhkSmB03E?niykI5Xz_aq>WhIIqT`!a_o|q_ZjI9so=sNd%Xo)b=zm6SgtLg=d zzk9<%>%vPo$`M*3FDFqy?C5pAf5k}CuH<={cBPz`)7?}cvqx|qBlm+E>5snIs z2jx|3+S73qamQ6=qK)P$GV#iI>d9)oX(L|D%V8ueL|gIALDv%b_cpOeXC&EVQV!y?jNyFCoHL)B~v# zBT0{fcefY}-<^<1-)S55T`lY|xn+SfL9O~4Q%fE;+G^5=wkFZ>ZIBu*CF(@|9N7~D zCofNQVWx;rs}<7hccn?x*D&6o>_yTuIeU?`b6%0XNJ_IPk-bPtJMmk1w*qI&6=eHs zJ^2c#6Xx)3bK-MPw3s~@aWV#%#_U>F6jqeX4aMBv41rM_?1lt8TNHWGTBCt)NI_o& z=S)pCcfdHk?7S*MUSxmlg-+f}=iBD*a{Sg}O8TNY8xDBt3gs_qgfs?RR4*;SY>c7> zyGpQRilah3#!_(O1^86xj_L~2kL)?on6nzw#`)sqHxl%&qAUs^3;nzTpA~iJQ--46whXniSmx(^VB$8&V^n6}2qZEraOl4G`VDv3&->CJ-G1a^vS&u&q zuS6o60+@k5*W1VlM~*4wVB{nth_Qt{_pkHe6S+@_I?%HrQKRxaPu$Tb7cz)R8zU&* z)yU|StVViav={SMI!uXnH+8Uh&Ll?Cjj`qFrq}e6Q@Or@QLs`xBT+C|*^RuKdxRDq zjca=GnadJ$`AkcU9Q@qGc7Hrw4n&w1_8D z`%R)>1NsS@DE?x6-iT+IF*#$Nnc?~0!(x(D$aQpLu7HejBB> z+LRc5qLm~*P~Mmedl%1>3v$Zz67RLXfqqb;5vS3Q8Ni%FVr60FD&{c3dQAvY5+G?L zZzqKVHftVpByBmGu`~@0s?!_CZ zd56t2oYR}}t0vLHb)IiN)5g|cxCPIwH6_Ldx1gWugED*;Bmy(#^%=$qH<}W0TS4>_ z{0h7>_`LgSGKQ-dHIZ=QgwbsYXHJCVDo$f0Cb%+lCyL@~A;I+dbpn1X`@yK$BMevE zzm?x=mi$&$9_9`0MMmoWIQ&*3Yv$QddUN629&$|(VWy{1@{eg7cd$9gLJ&hTTjlc= z-(l11Fn;kaQ`&`R4&xbRu9?DTVXnD?Gn&46Kb|>YN(b=FD)c*a75}hP{636WF|#Aq z3|KBHR@@Yc*a*v|#M%}=VPY%^wIzfTs~=tta$-$jW+*4tI-FF66N`FQ_Zu(clrT#~ zw8|vLH3Q?yorr8Q#6YN?!HEksf+Q$FA4YYeIkAXNS8s`avwBOs{t;~>(jph%sGg5X zeAXRj2R`erz*CWY<~d5A-ihzuXiC%yJJC<9349wqZ@xR)64~&R2EoNywt* zPhfsHFYhWnHD|3qJzrIzmhY((|qRMsNYV{&9o`e+SrbMI>&f6*@Wjeq1R^9i?e5oDQ&?s-RQRs z{Wy2(@L4q%|9a6}-iS&%tYiYyCRPV6g?1~2-kC~Ey7j9xn#QHv!by-E)a2YM$Jr}9 zo4~oXDLkLJ<9mHNv%X2!mPzE((Kh;YLKt1?Nwi9hDJi}J^T^D|M7KHV(~Q^*o2NY) z`j8b*C*JvCK~^$XWPZr^>->;X?EIjW>YX3bOXr7_I6wU8C-XyC$E0O1X0M5F(r8-QA~+v*iQ814#xAA zuzS%@LUu=JCRC?&fhPUf^IsIj4NK`Kh zTkpVK!1rVP8DHUe6~f-Fb8V19)TlMfOi0P2S!>$K&nPDy9k~h9M*rosDbXt6DPzM` z@#8UWtDo26v-l)vLF#vJ#=FHE$IQ#^t_)_-Q#}@X%N_Wfqf+W3x2X5w$_d1A+FFNs z3`xIS-m!Vdox%L;aob(hON(+#D|(C0uGrpLP@S7;&o}Pr4A$l3b*5S>$5uUmLrZJ* zNcDX0*`b!!p|Pj(zPrqlr?sxH$_`{_W<0fhLq(Q9CvT;HHqlyP_~G>k%1iK`Vt#NC)w@cP!%kWxzXmEvHUS?oBOOT2; z>BZX9wC?cu_>px@P3w+~j~`yw^vzTPaV7@_CnpC7CWAejhiYnuHuv;w;eWUIeTl}u z0??B;EHp2;(38dbp6>3Ro~|z10`wy(XXc2@naLfAb6OD5$~bAW2BVOJv11fSP(91z z%)~B_5o1(=8Eg9HLA)*2=d5jgkfoPX6Tb|XMaG~-O|h%u3xKJ)2`#9990#oxVYp<&_A1WUp7r2Ls8!>z72 zkWwT@&X2Jc3>&?~LHzx>`1`%6X>I2TemVS^l%l*ju@t3Er6?t?^2AbPmaM*yn0(qE z;yLEdq%D%gs3m4GQuZRz--BZ_=A0FGYq^&#yMPsQ~m^Q)tYESaS4B#7D@okJ_(0inxxrQZ{ z8_l+| zJYBHUiR0RKrF8Lh>80^>DaFRqlW=pUSyA!yoGFB1$T>UX*GEDhxN>s} zwqcb|CBfL(@59X*i*gXecVekX8}V#j?#^VG2SIC!2SE@>@_cFp63@IEWA}O)4Q_i0 zJ6J4HX9_tuF*Kbk6KzjXU=yL~bYq>$(I%f;AmhWii&s&`LT8aE&-v(_;eC*a!5xzOi=TL@r8ORnM{-oQCr ziqFiaTVb9ePD^;IG={*)jKmNG4=S1RnD<2U0Qm+FTe%DALF}c`d)ul1(zW+kXJ6Uh z1-N#5(E8%ft+R{&@P2FfdDi}SS$(&D;q0EC{$E^pQo;E>&TnpT{`ph*=kwY4dk=>H z-ag-5;lGx;kbiA&g1=Vkmh;zEnm5s3DM%^$9M%8GlZT#H__^mQGh&6e%mfrr=v$Nr$n0?H5-g&J5(sV^=)#yUOKxtV< z@$vQT`9%Tz{T!P^;j!83GP-gm(3ixq5#&K+CKQ{xV)W8;cVsRQIYyLT^h~HTPie-U zM3D8&Hf-97GvG>|!05z1{nqVBAZS~_ljXAHkG8)P< zv+61?$ZesAn)d2#q4RQE=(ye%`kgb=;W3_ej+OQH_LQ7jQBl2m#jIQoy3jBhbvfv7 zKW8on#VYDR%th8hJTsZE!qIPxnVB4YsawwI*O;ex^Myw4s!c7?AuCO3 zCHfF)EtnA9#rjP`0mn@veTRa1V}+M$$Ld zSWy61;9C>PZA0#`_0V|U{QmvN-k+V*H&jvS&nPMC+TGLNW1r)doDZ(3tgORLBrAS= zdLk^a3FofLvO|YTtJZJcY=u6P1rJJDF<`F+#eqO?@8ZbrpM^?FLX|}&kOcK5^~cws zFUfrHk6}462Y_W%RBm^PsHb2iB(aFG496-5sk^Hn)ah~ z>FJ2&7twa&q!~RGZz8U1OQ>r-&^!r~yJ4vjxog@T{By51+V`i{>BYJae83ueprH38 z`Q5VGhi;#mw|-5WofSO2x~Kp1=MEHHx7zt`*U9fS=La(E!jks9V0j>O{$I~Hw`24& zFt&5yvE^+aQ@;NRkM3xAbVn16uGB4ObXzb^@)S=o|8DKJGfdX5Ao0^kw;d9hb<5% znrQB|1j2b(sMi*Mn~ZcVETap%3eK;7g>xs_)|yYX_s)N(mG`$56_!;6g2fpb1HHi$ zyNaXM0dr<(i*vVNCN0;2_@g7c1=oSpEk{yZ2l5ox!75W)4&RpWDAq$>v}xMSI~a9j zM5+%hJpDA`vwGLN@L4QF=1r-`B8gm*5#eE>L<2_>NM*4qj7*$XO2o6P=Ixu_UUJX3 z4_p23e!CSsIf;csp-eje*>mEDjl>}ac~fd`MMmcQOk3%~oYip*Uh-(&w8ppI3WR0C z++50}CBf>Ey5-2E+`OqA+K9P)vM$84UX9UYmLOM+`f(e~6O6cam=e#aw87ODq93;# z&kOEbe=ljsE2)y^%x^{trBtSam^|~jJmvgLW#QMw0q652j?RVY<1-Rm`3wCWO3)z`X0~c5K z^x02%MY|jan1~R&PzQ5aXs#mP2 zu37;S650hv!ZzG$_}m#Gq(1z^+69!KSOT=v+DxepvJo^FcM*-8SL5^WRie;E3i9M6 z`i{7(mhIzcC$6dwvRIGWWY$^K3B=q+8qLhpHiAV}G2{v$`dsEbk^GO(3+9#QR#uj0 zZ4XVZaM?!qz z%Ucu1_~H+**B)seY%IJpJNuc4>E-3VQi6Kt>v#6JLA^68cK0)=_wd;bVY_vMGhefI z!-j_HnzF9)C-$A`udWI8SKcIHyqnu+s@*W&b33?=>vI&H=blbu)d^0^mCyY2;2A~)B7X(Jki9^xb;&6OW=Bh_-j7J{aR zNd*LS2`1p{L#rC^s|e<1x0E}N&EB_AR+SMbE?RZ{i6dRktL&yw?RU@2^z=V+;X=Xr znO}#x$~pqwb=BqB3k?H7Tx45Z9Vl#U?W?=Kvb+Xk#d)Vbla;<#{ZYn|yR3{1aZTP) z)hH?Nxe*j@lj%#JC9{5#jGI4bH8-|3f+EOGluG14a9S3cosapg>6LRGPNn_C=YRLi zmY)6}U%0;D{1)d~SvhB|K>u0i{jR>dF1+?yuuHr#JPM4+b2dptK6*Au-Ew9VM?s#7 z*c!}ik=SAlbQe!LjQPqelbwGh>Unmh6(DhlB;(;)0hz8DAimX*?)TB^YyP}#KW*{k zQ~c*2dGNvSoW@M~>A9yATsQNYGZz9mf$Ofz$-Qvq;pe#Lm)Y?7g{%omMfiqw_ojU-ZA40TnG%sI%tn>C3%yZdPbIOBtjOLg(QlsFEf1k%f?am; z*+sY6Z@R6hVKpu!+Pk{Jdad(9>sii^`a3)O`Om63G2GMtnd|lyoE>(a+*Eb^cuhmw zWP5pe`{cLgoS!z-)HF1P?-tsC_4Rt-JsKcsVP>QiD0XbGv15fPL@Ze12jRa9w=oV% zk0j5;T1TWQF>K_J(z?j3V*E<|bNTqJ=R0zX$TyH%gl7ri50SbEPhKvb5!)3bO0Pv$ z(BEaXO#svs?ZRAZ$vs1*Loh*`i-+vJp-S7|TzlZunXV7{Ki;;tzsvfd^XZ_~d1vRI z^G>II^z!9fZ@qlk+V3wbUYVB@%nh8|)zkkU7mgO3-)?6*k6ds*VqdxVuw94w7a2El zoD91NK%R5RyW_*zNA4!@p%gGB898n9j-1wcM^5X~j~p4AL+zVv-l}ej_*%6vbWM(?7ZXMRv$da2?zPJ z9NxtpH#mR$Z}@%r)J#++AL zKG!WCx+re(x#olF7C$a-@d=vwg5fzI#1#lDAYkeG&nL0oe;EAs@_w% zBXrcy&CMOQc5{w6SxHDJMn*zad6gmSSVTADu;^}p)7Su?RaLxiUukG^dfLA8;uq|~ z#Ror^li?4vl~)D=xjEVXtd5@FtvmSR*4B~=%L+j$xH{vy@cikHU_!QPr;<-Y0sIb4-w&l|hrV0b*&0QWg-Wnn~_CrVVU4>c2>5!I56 zsFu7Vs&(EG)w-pOsP-kR_Ez)lTQP#0-4WFD!B(t+7OVkA0m$qjajpq`BGx{FAt3*O z`~{3d;KrbEiLC1MnaD1>0dJxeFoCzu;`40!mF4vuN0T3@w8WB0EwdXx@)2w5!v&$C z!M-xYT{22atEM*1)X&?`p#X1tgVk`G^%Q@3aZ6rKL3YMjgekvtVQ<0tDXg7uuRQ&q zW%-t!Vf#zyQ_d=2Zu>F&MHjzp{bKRfB% z64sJPSW8|BYn@lZT9;13f{Aa$2-7#(V!pctrFK)I)yrtjHdj6pyJU@en~53GZzN`f zceV;bSUqN|P5WxRdA%vEht%n{6sd2*@8C=yz?*mA^N#dVFLenIyzWesgbDz-S*R|J zb?W0m!4Yd>@kT@ty5CVyye(}*cE9AWV2dyW+Rb_|`+<=1p z5{mxXm+yaDzAN{+u-tj0(hlD~YXov<-tn|6_Z{IomE=UBC6T+9ymHq%uiUjRo!q&D zYG0lUWCjTCRCZkXtgD+6X@^8O6POJlCtr=kgJ^5`rL!k=W zUtBzJVz7Te=EkLM!6b9zHO?y-`>Q(Bu=2#iA;$hH3d^d)u|N9-?)3P^uC>LokBVMc zxM$rH zwW~Mo>}zalT2u3!!v5myTsu4WeCw)mIEV|&vf=8?$Xa-P`-$(==3AC+*~P`VIo1~v z?j4`wL}1K5vNx>4Zo9|jzS)COl+*B@sMD~PL_=uFt0A<`t0A;5y@qIlGzF)`Ik?G` zHbHjLd;ccLFn;e(#CxJ|q=ndyrxcIG7_mmO#_)OlRs2IA#*xKxCpVlv%^MeXxU+{E zV;B1FO0O5ZQzvSVh>a{S$(iIFf8YUY^!)|Z+q^r)i|;FW=Z_9s zv#=286T(8Er84xh(N7VCK70=0nGj@Nh3^%%fTghzFv6)%(Ejf=C1L`HOo_bljG9r) zXn$%MVNO|V>X>6DIVr2~t7h=4X7FoA@LA6KGAHC0M&`s2+GS1%=4~&Y+Z+BX58(3w z%#{|Zkn|zzaA-7{^HEicOE)myoi*)F4lhgH7CTp(b_Z>kTdpNWEQaV-gj)8&C zF8oD)t|z$t>Xs8{+JU?R+RnMaD93)hWk1IT-%X#;72k2w=lJ8%CmKT!AMsbx`Xc~MnP!QH!e!q1O_QIok_Z_hYsbc)jFRg+PHHAWr zjiFFe5-Y^{e*LL`Um>?TwY#@E_4IVthUVt-stVU{+h)J+;^%Ne`O71Y6RM~PRaRDF zu5d4sbA7;#8w|S{h>RR?zGPr+2i&=ofl{U^(Jsj|C2E=?Q(~-&tdhie>C?=SA*NSi z3-U(JHqm253#m0)g3n@&O3Xm|Mq&okb={CCbM(nBAmH1LTNqfJ9xvi++RctLmS4Bem9Q2 zSp1AGXkSJb1fNodc8xHQRe+h&(5qw>ASAf4Z8;-t|K%NvzX7elv6*zEeTVbrf{!|P zFI?O4Uy;%Fc(DGFUaMZ$Q!OMu9RB3Gs5l(WTnXJSJ5P zSwDB#1j=qB_9PT4&)PdUOX!K?9KZR7OZMq>!gJ^*C_Kr~hqBtU(`iX| zIxTs3I<52WbXu2wr)xCdM=uKfCi3kPHP#Z*oZY64^Mig6>6yq6lJ=ylcSZ?(!#yp5 z&XM>HJ>I6?VxBa1Vy5G+;IFDO^0P`SLb*Sx-MZ&cXQ(nGP+A8cS#l~bLKzsA%-(BvCq&2bUD($HyNXByW zA|mJ|S%hKmQd^Vq6ZBe36VxqJFy4W^Z7O;zM=$IImdW*SDVklElNE5B6;8tE}wX z)YCK5S5?(FV{f7e7DJsK9i8|WUPl_2U5_1ryBN9lnK$l3xz8gBEr}$w>IkeHisFtO@2|%I#p?rkxsY#FU66WJaU>R>sU3iDLv#>mockl%<^T(#kEA z0=>4v%3RV}{%=ETn%_~Gmz&#M;W#_qva=FtE(K-1=gu5yblz>}Ra9o>wWL~G6bsU4awS4;Jq}E_R9Htr$=LDWuFux@1L;nXE`+D6}L})>1^uHKvDmt!lrBjFaK5 z8qM=$57U!WBcv_Xt7MgRxVxMB?}((3-H}lp{Vw|Tc|MoOyJT^yO)HX?$a{LJMiUdL z7*mSy{E?l`zh+pgS`YNNR|%zra6PHezRt1&eb+e;7+?!+#gpz{R*1OoxbM@D32_1W zn9UZ-lC^K)Z}hu=W5Cq$&a5nVe8>%*>$Vn|R#|iUJh7$Krj2Mq=H?PNs6D79g-5={ z)Oi`(fK&vu;Uey?^;k^U0cmv&XFWCHF;n{RT4DlWsN>M_ZT$#uMHFN6%j*@0H%Z9Q<`T zc*@4-AU+2%x*Yi|S4-;1OG!swO3@=Pb6>We<+q71%Ii@S^lQt~&cF0Z z`@60SJbCfbGculFy)~T>oZH|0=69ZYVqW%{GgEq!j0J`1-BbR@}Iw+HoV; zfyw#BJ0{7vCOglXsGUbkqLZ`~(Mh#o|p7ncwQ3B9ix$(+_$u#=Tfl(!=ub=E^nrfPB6J@@GZ|v_h@$Z_4dN) z?3{*Gy9fGruWGP<&AsH-sH@|WZ7S!AtMljQ^Q(*7R=1XxwyuWl&0XZ4dFK~(HAseW z{cwKYwlJ5C+zw8BBrz70T^`0y#w!owL7vG7V|Au!qff5Zl*m3=jGnv+O`onnU8VbU zF~)EOR@(}ELjgW35}aczF=8@_>2re1(h}p2L`BPfl7}b6reMyk_UXqr(SPLb6L62l z0(;?RAUkyVXlXh96V32DG#3lT*ZN+0RZ(%-y6t;b{+a*It}#G+pZ(v#M{XGYMgJ|g z^xtx~Q)b_I*_yShOA4z4ft*bLb(?$oe{$hs!TF7r_0~^*X7Ou}{19gKz6;KWxh^td z#&z69JO1AvS~EU!zt02wO)G@GivFd&wC%A2{^z;) zbb3d=8J^#~Cxi2QqpR-|&u?kd`7NdB`7L$JpWpJF&TlEDp5M|(=XdnzGsZ2Rg=LMt zi&u)p2$R@|W8ep21eq3ZIR(l3s=3(jL}pN$L62Zx?25aFjb zP1O_>V!cpK7yaZ#&x03h)b-_LV8zo~$-v*|!|Wn*#m34K^d^1U0aIc;l73?GVCR_n z9P}zMr2^=OLRUMLnmXRyP98049(_0OdzHPT0^eJKcWd7M3e$%=j9IXP-X?pEK2481 zIV~B3ghWKu;P%R9T>HhqpsRw&I)f9WS3`|h;yT5ZNcLNMZ@snmR%ffLgpOBqmY0Vz zib`Ge^b-H&u_@&8|7P*wW6uv-KeT`Jqn|FGwl+8)vtL`bv1q)pd?l%m&y)GdE4$aA_Dq?CLujF{g! z0vQPwXeXqg{_9!OPDXvkay34?6B4248n;_OriYiOsUjHdxIDoziOa3HKn~M9WbQ>C>=H>-koyXl#b*5jHVpN8^bZ)rCK5Wn6R#&7$g8m z+~^AZ?s1m}2Ce8h*0U;Xvs@Syn`Ld@sP)jQK-Qtdhv)9k39YK@%*-e%D(vj-E9)Dw zuOq|C2g$EeQJq&^ZteD%Ho%>_rp=UPy%DC(BVYTnoqO%Ss>=55%dIGw1oKMiS7LG7 zmNmKmCuO0kl9Ec>u5xwFb^cS~`8DqQ9QIuz0g2nlL*z=3(uro4w#m%Wl6PilUAmdY z+mp0!JYrj{7C8~~Ze8su^G8e6<;=IHE|>YZL^~(Ti|6)Oo6$1!*qI-YYX(2R_?rdm z9@pkfvgTiP{ygy9{&uxF-LY2QLvmj8CRg5CD@ae!O}KiUC$1d)9a74{>=(}iW7v7_ zU#B+-GFq-Fs%U7*9wUNB zpW|At!4opp!fYhxHO4LFyoLy*xks?vB^`rjV#%xR?Bcf;tnWKj_C=>EX#LoEp4a;C zT^(LY=ZAjgO5%<4FKapZy_%qPPxK=B;)Oi`XIs|oS3c@kU;4cDKd=F|0e{VV6L_AQ z@ol#n|D-I=WIDACasF{>DT)~E^b zpW05&SlX=Huj1eG_ThMx9SkS{u_b>ndTqr?(Rul&KW**&R6*~JeJp{F3*+JzwU-oY4Ve zu&oYR`@-|#Ps7$;iWZ>NB-S{sCYc$+w6D6GcDHH*N>Xs&lAj@Ya56(=R>-?}6X{y> zX7c~gE}wSiNFp1anQ{6%7~7x5_Z-5E;VpB^(D$WFLG3ST;=J$DuYlJ-y!a{1ouLor zw;iY#y#A_l#On_q4yK(wi$8E)Mbv)iSX=AyZvr=G+ogqN70TE(w;6E#@IG=|cpupW ztYtxX2GLTbMv-jUL>82`sYa2W(HceSmakFdxus|n;&b(va37&fE>F|j&HOm-_*%z3 zgPFC_d&WA`PF&_7WWNov-?lv2$L|?}_8&=lOCewrQ4Wy!o#Z*6_=L6bAM@G{tpJuk zqqJz%69^Rb<^FvC}^F!*EKR@KTrOyxP z&-t+*vX;_*%nv!Kt9IEB$$RY#=||-5q)19qv!s^KUkYSUQp1|(OK+nK_x>IYij51d#{xI?W2dS z%^$y#e(s#?ntvE6AaMDBYpyjfeC6%h#?qs6R@FT2;127O3z#dNK=kph(o2{tyD=t= zbNP^oEEsp57c5ia-Bamq9@HlV^RFe|Vq0$BL%v2I#$LF~i2B!liu!MYRGQE$fLLqOxy`&|tUedbsdZ`s-F7t{kx%wQ@D0yg+nT6Sg9Y@$q+ELpL84-`tXZq6@u-%ll z<7w4GhfVEa)DGfFdYXn!EiL7Jc>5bk=I5ah>VMeQi5_#c6jw={($t_i@%8M#~{r zS1p()7Sis1psn#b96UK~l9&{eNWh5(t^l$IdAa$bb=S)N@R9hbwPRm%&&19h_up^z zy}O|O08aAv{xJd#Ni)x7q7rWd&Th~8Vs8=fXz=1cOiN`66K zg8YIU{GF0@z(`EFDMjM=xsU|&42nz}ccoTSq7SLYl|+N7Ye1cF#nMZpt2ua9 z2Z=M%-@s@RV>UYCjM7L9fwh7$BD;t7C$5B1CGI3K*#}G3&aOP{&)l(i4H*bWe&`iR zoX7TV=j{a_aqe08-O)!pB1!0t{pR{%$wAl#oI39`ge?P~^{}rb!A!Gu4{Di%R*hQbSury~;L(xH1V%Mmqf--* zsh>dT?$2Xm2}0AkGj)l)5QcEY2_Z@%%8-H}qTue=eN30rQT$<7&D zb!*{(aAn@uyuMlz6aIVeUgz5x*8S;({`HNc$WCCa^oaieWX@RWtn2S(taJwdVq>LZ zDQm1$O3|@WMm?pTR=ci7#!RI)I%X<$8Z#9{M)F9h^p1^`_Lz5*|7X~g$bC9yO3XGjzdKyUuXd_J|)m)P3Qcrqw7nTrN-IpS9;YXkQ^5Uzk&Y#$w6&IdaaDH!8sC7R= ztykUTg}Ua%$qV>wEU<-;q5P8cyht{ z-BGgH+tcr~#6aQw#h?1z;?-Y$&#qmpjlki%8Up!lHxBQUMpH5Vi^3%v{@;G^) z>BIe*F;DTuspn~>JgaLhUVmz2 z90#8FdzLi8b=YifhXN~%}bpD<^Px1Dg;x7^=Hi*mwcz~Xt0UZ^~1 z<=&*y*EW&9mb}u}x^&WKma_JJyy$s-UeWXLz(cO$Go!y%+c~R8Oo@@`FI|aTXpN+);*`{)LGthYN5!s`)Wbgx1Dky z_g|PdzWp3lE5AbU^#dvJ_1c#TU(eXK;N4Tlw&kA2wxyLA+m^n|k8R6ymloSjM%^Qm z_EP2VpL~biCgbF<(GpnO#pGWqk4#CAeb)qDJ$v*G>92Geygc$OA2HNlcHey;J9e#L z@~=I1r-xA~jrAYij6IGqX*ut&7GJd*ao1hugq~&iGQoB)TL9aw_e9QV%PZ%!Z*e)- zoTg)w5&2%dgu1?tqt#8hB)Jdt(5l@?zpYT8kz^ge9{ZM5d1Gu^PWEoZNb&YBCf8Ov zUg%W}t)IMud8%nA$~y0E_V(~;-*qRla_W{(^!4poUgw-K!tQUG`Q^?Iw6+Zlw6zY* zyNA8JIx;ntTTuYGeqmwLGJmJtvmPL1pJ!J@Vl^@M0kgl(=%-EaU%nr!kd?a{F^AL8 zZZ!LspntR_`4-xW=UY_R@!lLT9T)e~6o8&$KS1u{T2TD-t?Jl#P2(Kg7oUuw{Uy}b zW^HXx5u303zmvNO{zj>-{f^!vFLxV#N6w$WaKYITPoUe{+4H~8oDQDej0C#hp|ZAf z4GPYtr^RW*zpW?jGoTLrzLL$_kdV!)EuoIKywuS?FLktUG3rR>ntGwTKr6{kWqnYo znI>KoXda-L_zlH#C0?vWsTTp=yr(QKNW(u|xZw7fBNunv>$IJlhmtpXi)Ujt`9aTv z{_|$8@wA(VK}}kI)I`(J){_S5YtoibQ(InYYM+;y+P4@rIoEV-e6BTsa_aLN!nNo! zLirUJnTNC}6&I?Nz1YP3R_Z$0|1$qf{Zr~H*=F*_=)K?nGDC01Pgr+?5e7#6)6kX( zx~y$&3B9%DrMLEZ>8*W>)4SFF-h4H(^<9hA$QFKha2pHBggDlkRz@j<^;*xMX+E&^ zVtl&#vTI==D)Ut zyV~+{SNpu&)xO2K+iZW2^?20R+hlv`Tc9KtUpf7B`fl1vowy?wXEJ7E%#LH7$4$1i z39YTRwH2+MwzU(jeYVADDv@atSzUbnCe^&AP)r6-YrSinQ#oiVUe{$L3CpYvcEkCb zzN06C!_KEiL#E>OL8KN!k z4ADOC4AH*DXGop>y;SIF&W)~%w3-*?P(p3%#g?l3fVZyoysPkirmD455Zm+j#q^;S z&;&Q8{Q^{DwI0^AcF>lJ&|aUa_IZ7(+P9ETRmUXzRO{@o)ZsT-c}IRTo=K|6hSi{( z#tT_9Rq)ZNDp~70XpM~GDTyUZ^l?2X&+}Q~Z8g|uXxiznPSIQKX|#bk!Yun$;i)nms@t&SJKxwZIS)~a^UBekl%oYOup z=d^Dj&gqy$&WS~;m|39FV!zmk-*2%ktx(NcFVM9?d!uiICxSzPz6(xD<+4=Osr9Y2 zzUV(+jW@9VDC1X~aJ^}9PCAQJq6Qu^!5uEP=tCO zcFrC-;Iz1J{B83U&sQc^7IpSJKYj6gk3C>;ulsN&tniaHs8LJIDF;6pzguJYxhYnY z*~?Gu^YT;s7UHLlN#y6_$m7sE%r_Cv3T{;PIJwriZ9mc6!WErZW7^pb?msJ#RkL^P^ZyO@t^w@klWE@t?}>k^F>7fut;X1; zTubSo6e~McVwCjqEV2gMqP@ly#k0eRq|i~Vd>i^Z4ZYRVIb`n-fp7HLFy~93(eray zbxZr0`y~-%@g}HjW$Z)8Fdi@l-tEEPO62i2T`#< zTl>5#Tl*GT**Ye9W#d<4ze0(kGMlyT<+tevn!j>1Q3HZXSG-873ex&6>bULTxK?kY zZK+b5D|*XCqAV_J|CMPF!yYGBg&taLBd&e)(G&%tA1wSh3qpVD!Swle;=L^=f3qY} zXm6-vIq2@=eV>Z+mUsfzg5HL@;GHqv3O;n3#fN?x`PbY57sG|>6M_rXRxxPm1MNyd zyHZ>e6&k^H1T&}{zbhzIMTOSjP7Ov?VwCt$J$#v_hwvf14b}@whGt6YxzqQnaA(gg)ywww;-mIDV*XS zzJ&E}+`>ECGl$%}0Ojl*SyerQW7-EF&geck);AhSp19VfFLA9)-@e)TEhFPp&So!~OD z(yZgW*UbJE=skp9p6#{BF7DO8Q-UvT6=&|`Nv9((sL3_mbB|Mhcd%tstbp@1L|^X9 z?RMVY6Uf}Xd(SRs>4giCzx?Ii@(4;UMnziZ{2$K$pEs$`2jNi{`K1 zxzjo2{B-v34+45wSs5u?63ac<2mH}HAuotI+l(2)ia)G1Cz!L%7IXGE>M>|53!Gzp z=J|1GTkY7b7&{k-)@<)L<38)aP(Rc6GYU#fCHH>q)4gA#qFD9d8|TBY9m8ltH#n-+ z6}dZ(QQZHDDU*n}?)Y;tW%Z^Yu_<@E$O@;nhBGEv>eg4iX5f6}oMOqgm#s91EYBW( z-4$nj?v0Bra(Ctm!IK3;!^_^NXD?qy=OtWWwc`rV> zWd)FA;%}JrzsBtAtQzoe57h`b*vVTqB5a?dHBod?~ct9IWO zK3?AzuasK5r!6b1v>;w7^+Rx4tcqL1sGRkG&b%^sdYdoPJ>7Z3+Qz2Vw#kP5{f$lS zZ7++JNo`tD?DrR4-M&i7q&h=B09B}SZHd`aOEF{D8E+8hE3sl}=<(J_)s}EaTVC#H zpO-t@w>Wp2?C;StC_Cq41_4HNEM=wau8VquoFoKTBbS9Iz_u{`Uzh{_dI5orw<`3@ z*%T-I&R7+L?I8RYlAvEd_jP$opc>m{zn?iWH6~j69jpUps7lmmeL~boTS94Vc`2=Z zUP^1<;*@TH?JSWZ6Su4E?-O%7U|R!d@l3bG8mO{TM7k}?n?>rKQcF!@ zPstwZH@&rM@(Y(x>vTSsUgir6Ryutp-RNdb?Dt=1__W6CKHPh#sWGbUphqf}d36)* z^Xewrw~%h4W0G}~2Ky`I4?PIU{Lv@LpFulXs+;OPt!^qFf_0E&L~m`jqc>weW48UG zI>y3aEV7J6=N42Zd^Z<$SKJ=MVg0#t>cE~9WlXCtT)2~=?D-Ul;`}9{0>3F@x*D@H*Ce7226QdD2N_87jQgBd9Q{tdvnLYR};-CibUD>$K#x-rp z5UxX*{{^5#rqQ`*dzaW2HS4Htd25jB`1Y92%ySmCuMvICW_PZ^ZzxTd;94R#)Nqx) z@^=j5?;zGbZqr(9(?S}SK_al$=+@JL>t|nnHvQ$!!wIp3#A!?{!mIAN$5UzaL-B3f zgX;hq;YF=8N?mBPk^9tzmcvs)$*+H@&&TF4n@@t>YQ0$NR<{a=Li2n+5UdJR$ z{$~3ti7`_hPtAzlA@wVa*zxoWFSjjI=N|eJ>rWA}tIu;Ea23(3s zdyAy!*}e;k{*UBe;k)8kR#xrk?%tl=qqV;53m4wve%@LALVr`!(uT^u%KCW({_L|$ zB9oIi&mNKfy}=v{qo1&ibCh$uUu6&%GWzBdyCp zk2F*~E|1w4;#uPS*FHVZ2kQlV;hM<-#q!K-=87poZxP;7W}hg-Y%jIk%>zY=0EH$$`hU<;%z7^`_jGkn`>9{&Uui_^vtst8?eRadJ;* z&u`CM8$7*-Sfg(^-`qnv;Qh85_$BU)eH~9shr9vEp;we^!Mr z6aN`1sp7gEUrg^AsZ)zgi*H7+^ zkz%j=$E)41eHs6pi+f|d-WTIF_w^6Ps3H4$j@{S2yq3NGQmH{+%M)>4m*ER#AAwZE zwdi7UtrCwEk!XQXM7#j=P$a;rq{)V22FhZV)SFc6IRyI3BhK*ZRkuZM&(A0+?hBn7 z-n*pemR;x0efuOV5Ho3Z{^hj$QqS2nrIC@r>0obBaeDah>Xy8Mfb-N&StD10Zck#3 zRADbX7o!_xK4+0+)agllvPPuuQt1}8Z{e<6f^}4B*NJ2S3SGp{8mG%ZIKIVVofuCC zs#EGb`ChJFD_1;oa`xxb=R?kq-RuA6Z|=Qv8s4bfGq=M1;7(3`^4%e4blS**{jvE$ zKQny|lm&t%%duE8@B9$Y{-u6rCB9RhsKjbv)+jTVbhjghMelRBuEd?ui$n=l`^;b(lARY1kTkzbT?NIb=G9R-$_SZ$jr*p zGg26Gf8FjLDGb>$C50h}BeBAey%#P#b9_r|o^5fjDDLX&EId|K8eLYkMan=<*9;bV z%Rv758##eMpqOPKo%e3R49kEV+Y{qUJ+e)R^V?!hh$VM;<`8FLZIUbt+rBVH&6Uw% zP&D7pGL_a9_9@C{_5O2y%KM}EwFcXweMKC$U?e2&PA|WXrXOV3wuaFfwJma$JX92M z7}uJ&R*QEMF-&}tzKb#V)Vxi^7ojjCP(T;tdV_DVDkFShzb*20Evf};w zi^^A{@?zv`nK>E0;xJH0!EhkZ)ipc3^X8TAo=9O~q^zJ2tTOBDRE(ds&<5WeTW5^1 zl9QE5oaCM>eV4kQPUA&lljotX2OHEhkXpVr`Hs7_A?Js) zzvyYlp*KG|jy%ifPM!&#nE2ZhR|ii*(wv*n?>>s}ej0ML0dwX9|5xScrj)I>^IvEnQdZ)Runkk~$41IxIsvsKMGdJ{V=8%M?Ww0JYn>mswL+NZ-0SbS z!wDW;(b@COGdqH(SIquy>Rp}3o(IkDTLHpQPvO2yx^%-|G-4w2T-$;>%(1vbujCah z;^oW;d4f3_{h*Arcou7~p+XsEL77?4s;RKfq>iIBAf}?)jBUW!2E3=u-fuJaHB(hq zw)!AB$42nP2GaQ@yZdgZ;X}db`WoR* z!%39y3+>ALHdvE;bS$X$uJKWIT-pf9Jecu7F2^?mlCJm;fhhBpUd z>!aFmX04MO;|+awT(e$!WI?v@1Bc%HG5w+BYQPyXiN={{73OgfFeEDWy+d1cz$-P;I5sz27!HT4{d#Q1y# z`Nie2qIu4vE8OUj9VndVm352_Zclq6#z~%!NKUq=;H30jDkr)7$rF@y)Lo=SuS}Vd zU!~xI*lO*#5}77DB2k4po=7PAUzUQ;)JMq~#Tsz+2-aY})dSKhvNHi$qNm&^MJk)S zoRn*6wiG9gcm6|e^A@6tP|B`v2BqvaFKMj^o)5o~wd_jEO0zacS4u6rwMlaC7wt!W zS}y>il5(kBSF~hg&9?6Dp4G#zA?zsI$;vs|IBZJS)i~dSG)&|X&WtfNODGBdZ}Div z(tHFw5)_cGv=LBREN9t|gqPfp$UCVrBQ{bZ??evDXv#ra;Nq#|le$weBBT6f9Zm9h z<1oQ-44St~)MDg)i=4@+;(AAMQv647nc0DEbxo zwCrHQH?8^2c}uw|PpI6KmdZ_8f6~YG*J@>_ zc(Y`ullx8htEgp4i~CwPxJKLn{XxCBrdGAwj-bbtvR2pL2;LpH0Oc)26>@zFszBDK zqIFa9)2mk+gK(b8YDu`B)N(lQgCBINJ`mhCUL5gd)b(Dqth3wM8R~W3GaTB#W5+(H z^7-cKzc{#((34e1JUYrJ9hkWm+RuRC#H`& z*BD)t@>lJ{D6EwRYa!D5CaXbK9eb1e;n0zD=brKSLRt>}%>BpXuemzpypnDXBfs>!tBi%H9!eq*`Q4GE z@1~DK`Yy-E!FeuE5#=aaoLGy}OKVY1M2}z=63r&_PHjYbD%3_y>5+i$CBC@YlKH9f zVyxnr(B-+4$VxK4$kl)4est=^4G->I8+2a3TIq5q<}aY{XM;J5ccJ~5bdjC!a_HjK zlw^<8HOrN$HHcQ*cdrJW#7g0PvG9aa%P+#O1KN6hI;=$`XYr<_nPPyFA={`5Ru4m@ z-(-9bnx!cat-1c2Yu5Ci59Zz!%0>aO(vr-r;D{n-LbR2iF47FDjOegjV;&vvqNuWDEs$@XVw=S(~42M)O3PIo@C)*acs&Oot@--dPw zV$ zVieuxUK1W(v$3YS2}dctE~Bs{l3NkZyK~ur;`E}*CC+=cVKOt`bTCFkW`f-m+rx`Z|_dUAHetza;@brXxykh0r zwKdU-;`Wkjx=-{(DsmHMvjSNe={L1)in7dfgL5yuYTPTf#OT=q|M_s* zTVfQYe}*!%Aq7RH?@}pBxgbw4I>DN(k{!?eLi9e)Kh@AkUD43yqizzuY{=u3O}&3i zHLjf+9-3a;*tm9jXn1OEDNY|wo#rh;&hj7g^{8CEL%*480%}s+th?`zEpgbRkQI5yqozTH<>63NJQKYH%m50AqEZszCC-*mLM z1Uf3CC0Wz;eK~=ea7B8krlq&$cu{5Tk9V56sD2tE09Kirum7|5M;WLjmH~a0v@^u^ zlPY^6CFMS)WV;%oryBDdi_64agxk&Tag8rnETTLGNvougM z7}1={W_V|0sQT}s!HkS(nfuGWCn|#wUOl%`_ zHO5cB`$uB)o@cso-q)v?_tJN%^Pc;bJi&d7Jdzfpz)_<=$vPmCNbfOcSv>Kiv+7o) z^Mbk+=v-ghT#KW(=!2gJ7vMHd*Sk;noiz;yTHP|=H5Yz)?%el}kH_|@ardUo>=RC) z>ja=z&yE}Vc;gbR*TPvlUu2DYl0?HUl|IxsZ$I2|s5W$D%DHzv=Zx0| zX@u3@X)245D*tm)D$W{-YsGyDj8ZYH5ZI85f)8Pihpch2;2Y4-xFfB9tt>)nY1S`i zka$+-lasXaGmM!p*r^DXKv{-kW=kqcD zLM(9Itw}lcr;u_IZ=XlTIq^uVz?rZQ)q0`fx_u{3yw?=m?7Qpcf|_N!`}%e-t8w1v z-s-&C{bf&ETMz#gU?SGe40iVX%gG(V6NB#6b>)W-SJX5wZz(BhS^mRG_xYNNikjN; za_9O%*0Xx&!v_F-J69Y@qzz)(bx zenf8QI|}$#JXMINh%#feQ0tBB7}ndObi+J@t2Y)BG^Z91;4o2(eypu)8gRxw>G<9E z`**tUf8pGH^>4f@24R~0Lr?pPtG66KzQz5_cUQW<@ZUg1rnARe|wef+9N^y7C44kxpuq%U-0$;P%|dG;+I^wQ$=_T$IT{>SJ|OQRK? zOJ7bXjxT&|{a7T^pXIZ}!CK=y5M7Q)Lq?M6v26o=3Q)tk&FpBD&KWWKXde-vd3Hn| zM&w|G;yWd-qTZ}#JC10=0#Ha%nQfquXui6RR-#AHg6r*5TK9|y=( zSR|a8M*mzr*ioJRHcTT{v3AfQyNaiZz40S*UzoB^+=4O-O z12fBn4~V|R`luO%%(w#EM?`Jdw!&!PEP&YfBD^~U4wPb!(mRPd|FJvt)~q)?R9jCn zQ|W8gG4wSPK_ptWcr}PN()*0=aMtroc@L_SB*)&`Us5Z)Q~9S!feJMdKoLrq18L$h zW(p?iLPfnbk44&!i@t4>sXTC}B5v+dn&-f-r=4jtK zn1N!MI%oxLD~NBwOv2ym$G7+~I#>{|YLIQm#ZTGH#kgF)731=8osahw+Hr+w728&^ z8K<#C(NpM=(Z7Wr8CFM-3KiY9U+p?WC-|I|Ry=wdJ}qb^=0w?2olXNbd6ksA<5Qpd zKd~L;=DVsM33eTCu^)QN&}5Mju5%2!9OmPzc0>zvaw?*_3TS@3(VN0%w%PE~_zwqe?QF%pdFtLq0U~`Tc^d4hd ztQ+M3u_1M%Nbi7c>5Amq)e&=P8^BlRVa8Gi8nxp_!7Ev@ystZcE3Q?e;kBavBKA4S z_19k`TA5KEi4Uk;ZL*^&@w;$ePKz6`{R8-QIk%${zanwD-6a1!=q=;xNikE;ZKh?nm~9Qmf)|K)iC>&Ez5vSh_8tn z>=av!oy>ffDo{2A%eBhvW+8lAnvsA3+vnw!j!Whg^$xw4$G3uRv3%=`f(WXx_ZeMd z?J3EmZ?*lc_-)A-Ay=2;xux(1CCv2{#7v^)O25(Bk{#^;Al&}YLodnPKk%{K=8Yb} zL4jxHJIf6CAUFFKJxOnK`HC8IlHRViBM?0&K3kcHIPf>e=zQmriH0GTJjt!`$oXz~kDi5`XN4eo*Q=ldi?^G*y-+`B`zV)0-%l-<^x0&NNQDbs z8&#mFtOr5539>-+4fe!Q2utiQ6a7O}98cIF8cu(y4gJJraSadwtNp|HOBpdq;u#Bo z^;7=yREA5CRPT83!I+G4d=K1h00T{mBbY0xwztfzIeK)>;f@2ZX)l2X+|6k7JJ{jGT9;ixTZ>U&$IYcaZGFLds7#`?D8Z~2 zFOoh{Vk!L=$ z`XcLp#ki!Fohj4iK?fu)D=j0U3owEm=oVmia%Dw1#ci2`acsa6?}Ey$$mz>ytN4e! z?%m(&?cLZqGd?pjK7B_*kr01VYz=+Q31$cHSpB)GTz}33#!o|i{Ap092m8tvQ$?Bx zwiSkFjkZD?cNT4V<(2l$Xn7IMLU_*pGv`}_<4er_I@Sq6DvXq z#w=<5W!4E7U5Te&tT0lRT$fQ~Kt~fBZls{{3ad#qDsSLFL7`G@ zK6bvEHwS_`x7Yc*;ama$US3mDQp11SyQi1W%na;rd88g8 z|3Vw`w>rW1qGkK{mqpi&kFSrGltjx*OJ(m7d%p{7VoloTvGQ0~lD19&oGmp}VU}%? zZSjtT?x!u&8`#^bJ~d12NrFiRu1sa&qO#lgIzy_m7Bi zG5hq&9&=uk#w7Fbjbmx2L3`S>v>FrbS<%ws_AITIaz-#(Z(xkc1X1GSQWBU z7;PLDvZ-Y``{>}Shl@+=Sgx!w#EFw3fp3aIL}IAoJ`+WjXu#n6^}wK zU%gh;P20^AsG1u43wrPbD?P$fl^76;>yo;bNaS9dpvi>pV!nVH1PoT%#tDIMz00?{xa|Gz6NiQ9lfI{A z|8uLu)uF=l=CWW(D3HEsS=d*YUr_EZ9d!720Z;Y8-G!;nO}*%AnjHCV6HESmXMC3B_#R2#rRgSWfH$yek1cTW8OEqg9UQi=P@keth_F=b<`;tNfK#eKq!*_`b?8=UdIW3tS7-Qqr+L z#QT+wzuE^L;CxZ6AD*C*W$$sdi9eVgFVQVS7!|@>n!tC}Q*&?~K|iDXS-2K&1rdxA z$)h(&f3Ftrl$ai$YQub~!lW>9&)D4YMx1^ZyvcXh8$%jf zn($D@`L%oNS)tw8c(kdivh3KgNLBL)bK*z*)iJ5^uIY{=M>^bJ*Ay1k)D{(iZsW*{ zA45HZThfW`H@2H+~ zzCPP}#{IExz+VKgS0Ip;mEpVfmgBxa24R80L+5X&pzw`M<#!+WxYPZ{1Y*1Q&7re<^VRN;{{jE7 zt(iGH;lCPlmS+cyqB7oBFlR^cR|_phV~Af`ha&p~b1l|_*k)p5x8i9*2h-!E8kY8{ zhDBXL`*=3!pluD}sbMphm)pMO7_r8-SZ{ipZEeH&Er#ZT%VV8iee*cxvgXVfg$}Al zNGtlnX@#_ZOzzqQBVr+TIKM9Is4G67lXW38JrK&tM)AeWy%no#t4eXO_011CeUAId zjhgQ@UgiG3rk7t&YmIAZy&&)kk(;qG<@@M$-KXK)Ae*chXt)yU|@a!u8 zPVg)fGq4i+)+fL-MqfCa)6gq>D0LN|ZTUd2bVJ{4+eiDI8VVzz`V=Fe5@jp5ebj>} z+nN7F&zg>Cq2c)+p62>gR4p5YNT{xM3J z*%=R&AD;cy%=rT6`#TtMy1NnI$}h=6k02pbvM|=5`!;2P-e;77JGxY{m578$ z1Bw08kECPi6+(3>zgNJZNy3&#BA-j!8pXF!lRXqJ*mN^OplJa;6nLrSyyXA@Vt{&Q>{bw&7r*Nx`yzH>XMf3QHeb7sqPJ-079tH z=lH^rKt^}x*FP+==U~X+v)Bsa8W~4@gzIB_bsZ!RY9! zvw}W)9jE(^jGzXXhgBoHHg_56r+%q1>2ll4jNW?N;tXuHE!xZlm|-%X_*SibLV2q1 zRojaQMeQ5GlQkH<=^|_P%csj8}Kvu{eh zuw3Y4)mY&~23La`S)h-Do~#62j}k%=4MBTX{osrg>l4M`673>lBDIhDW7M|dmBMOl zALlD@H?d!3CRML(@q~BLo!h}BqFOuby$W+k*e{p@& z2QOs--+X#m=&C7y;i3zZI`q+49kvRrhhY=bA;O5eSpYq0G24R{skY*N=m4n99gT4s z-N(XqT)e7XneEf6L(HAf_c3>(%C;Cksxj|ef_L(Y^-OduF$Jx*#g)qSrYn^`mmW~P z2cwqSQMyv0rEt$v4>Wj?TFxe~7ymBTKka7L`Oueab<_D!Af5quWD&zM?r=0h?Pi8chl!_XD_J+e$!;K!k&)6{)&3OuB8pP1j3V2|*p&FC%WNNazDnC-G?1}#$+T<$H)JO0TR9VY?Pz8T_uCfp zHw1~qD7!?WSj$nqjhP%PZHu_j0es0?`~pv|>c#bXT(8HdO?DLZsg3x)$8qkAzGnwU z*JAV@jNXHp(iktPvG8bm#`G!136r z5*?rc^P?Q}NiLLEf7ZUZ{v5R97#9lJ7QKyqw#Ahjwk_tU_JPh}(3z;uLVJf1W#V8Y zqAc+aMu+rwiHB~qEmk>bwk`S~WBxI`fmh_WKFQM#x7*fs{0{L@!fAR!9!uMczh*B+ z9kip=5=)5NnPiJZX%VYkq}-n`vlYIJqB#@8qaOEqj}v0y51cUMyN=?+{n5zC`JC+J zV~FwslXK;Y?|U*ULTv}0G^axa!_X1(^V2h@olZ`Q7e6t40pY)z(Iv0bQ;1GCjtV5l z*B_TPs!`}%*V{@blZ2Z!h6`Z zI9C{jiq92&igSf1k;J)DWuK&fqrtYALBgoH`ZKuBRio~)qo`ZZlO|t7ECM}V(o&C? zwAAAT?;!q$xbI8u()YF6KDipdJ&fPma8W9wFU9pZuIUBXYDaCw{N0RMyVz_KBx7>L z5d$};$9JI_Rs?v;;3pIJr?=c+_#lrg`sDrT^Xycf8TC|o5LlvM3`;aMT2*xDfD@YR z`e15lW95vTWwaEL@?B|r9io((Z^t-I8u}zoLp{Z@EyhS0laW|(0Muf|S=!NAxTc+! zYscoIRcu?-Kuc_k*&=CpN+LF_!ll1QzZmgH>J1IxTBE2AuA43r;Z9vepHRJ&`;_*n zeMX&B`vh;KEn+8l1{!yz_-SZ*m#CdJ_DR;c9KmmI#BbA=#eGbye|k^#nYj0qfAemP z-Ho?Q*!vTBl3y@^JMSKB#^mo{f}?mCkj$6I3|roQ%mP>JXGo$tMtG*}g>CB;zQXD1W4-abE6H+DFMl ztwInAsU(m*O9|9&pCY!V862Tro{y(naZNNZC5(($2_vofB#hiu2_vn=B#eww2}A#o z{-*ecv^9ah=YYL;0IeC@n!(@Qj=y^bfA=03Xr5Ac0aODl=VwNuviV!Uv` zROz5pA!;ifk|yA>xU}W9xU?^BaTVI91S_v2=vR{1Y}AgBSfP%f52@YWOBE~Bk;HJ* zmJ_50eJ<3eX&1qn5%wy&ac<$mjp!)R_+b$=pyGaK)r@c2YXHU8dkU}K_3neA_f7qi z`xE~)3;U7W730g0*TQ(B&^H^>yb`N>#AKJ#ieOfsgFfUrpaK$iicHK&W_k_SUi#{h zkpvwu*Y+__FlhP;ZC@e!#K&7|`-mDTvn|@Q%z}xUC#!6~=ok7|P`{urRaUj=8meD( z+h;T*gz*&F3yhT!D;{%MwD*1HO>XYYo187PKb|9RQ_%kg_mR*C+^k04j+lO|d>fIg{t&Dox1Ta>7R3@HIMM1#i@ zxQ>EH^qzCiQm;U*eXcfkryir|KX0~oRIg`zN`F)1Q?xO(k2c0q+gghE^?}BNhHJ}g z|1ykPWm~H-Y7l>q*oR`3$llA-XZ6in@J;l5@Pu^j+llw=vMruEczGw1CG4?tmX}{3 zk-q5aL7qyMTa2h>N#@S-PdEjNihHpl^u221Z=O9`{-S+85tx8F7(u z8gY>prJ$@tM);+Vx?F{ARiIU6TU>wDwnfXZ-?pf^Gmau}p?`qU5^1f&?+~-92ykLF z^|2J8Zfg5qp%=>2^D>J{BRRjV+_Zat zTcj*K5OhA7VzFwJgbwq-NSx)9Vm-Mz&W~LVe^Q)ZS zcvkTJAC84b4X?JC{izjFaRuh@zk*l9?9wZfh91GQQ0vaHEuy1X5Dye1X z*?Yn}9Z3tW#@>^?NbhkkVjd>fs`mAvugCBpgw-bqL*`BBedbLpGxy7|hF8Z%ipK`I z>T#M6_V-o!N{S^rePHPz%^(ACNhM3YI3nLw9=b2vF*v!pv2pd}ApYCX-gG7geR20C zFERJ^_F%L3dgy+8q_ksgXXm=k(o+0i@5a)1lMl`+Syu0NJl?+WTVn=xDB$CH9`?s>@kE@;+AJ z&y{@UW6$~($(b8_lS|1|O7co}N92aDUzoSCk4@Au`FmSyJ7UYpFl zRN?8qaBcpQ%#Mm^Y4*;V&J15cUZ}>OS=rDOK2}&!<-22HZN==9`~7dUyyQvD`7v(h zgMZoJ9V1+RLlGZZ)LwExk$l5r=I9rrw;2EBc`C$1>s~4RlyQt|@l+;hC2~^w5;-Y- z%1LP{Cn2x#OL3mcUGj99{e@-tduZc~;csL8Vfu_EOXhK8U+dqo9$&WB%#F>qZ!_Mr z&9=-54T{SKpdDhiA z+2`qRXS|I_AAKj0J`!n;*uFTTkeP+@+uSoNZ7Uv+tG9iER?zWck!nk0of;FRT+n-{ zDBK%JJT5IYFXw1CzQ>bJO`Cmg4%lwYLvCrWac__o=-fIZRZ?T%w0iWnr@t|49-mXs~21*Tq9z~9fEw! zhbC7Kt!zcwf5tc=r?UZrW>!fWX0+h6GeK?H{dHX|!@3Yj%2k715$lC}CAlF_C!zzS zFOeJ4r`(X1aziiy(kD?VeJ`U@1NK+qdCrn?$hfqQWcC*SwiWo>R&bvyL5$E-btrXE zdCuZ66)*ScscrppxRGLE+;Y!7Z$37jn|0zuX5RQQ-?oL8Wk+ox``etLSC+RJWx~P5teWqRGj^vZkfA`T4a2{*DD# zmiwuLe=aW!N2B@qW{qtIc6|?c8GwHy3V!w)>@~B>)A8+oti1G?M)_&TKJGZos>%TM zsPSjo`&^OPw#8f#u0=taa{bC%^1(HU^_JQ`);TLSZ_dP@1uCU^|efl0D5r8I7o?0S%EgzMxvd zMb+-W1Q_&v&CTYVy<=)3N3a6Hy`-tgZg9l^^Sn-AXyGAh2c3t^ zp3f))*FXInin(y$x6%_3$pdY1=V#^@bB{=E?WdNgcwX&OJg@lkBcO%UYtZ{d^i9uLB8YL@XR27eGr^*E`tZ~AX+HA z?_-N`!s+t>;eWX(N8Hz4?f&#*_y^X2nwwubn%RlT4_&&QBACC-NHB=C;X?R5(CV%CsUgYHZGtvt_ zaph0a{o590uJZIM{|UR^>Oj+PV29#rqn|x_wZ(C5Ty4_QEI(Ok(wDf>q)%7cTIlPBltBxI3^NIP-=oElzmJxOcq#AMHW&IhsPZ0 zcJCW*yUpF@m20=p{%Gbx$oYl)S_-)0HBIM>|H^;M`nURiIeTj9F<*N0%w7t&Kh4hg zKJ?=2rrvd9$oYtfxIni5z3((4&a9*T{i9!70ux%05Gzi*KH{|-!Q7f_L zi2b5vs(osiihozIUqpcD{q1=3gl#cmx*cy8-2GPkEe9{+AA0xW`Vg)UnGuhrP2+l+ zme1uMFnC!@@XwVaJ@wh|cKkJ^S(#OlYm3s0i;#HIu%|Ot^6i*F@mK1(gO4n>Di0Mj zHPq(LRFxKWl?`Qgl@{mZ?^x2E?>&j|U+;>SfLp)#62)8q4*&I-D|y%t>)}UQhB(2V zv>E3hW(*@Df(~g&fez8W_$+DwrGua@ZRZfAxF9L0i5A!vGoh)wiRD{i`>E;Z?ijVb zj5g4JrjdNq>x#XVc+)Q1VqGTI@1jS9QeE{*@qoyz6wO3Em814qgMq;lB9|3qs-BV! zcH9R1;!fLQ^k9!|?LljwZS6zrkZp0^QCE{WXritOnvYS3{Bb4LL|IcSME?1K`hx>Y zo9pW`UKbZ9eV9(GvvEG+U^apJ&WU8TX?i}Cenqr1t0L4MmBePHV#@vrn^dR{o+yCa9kEgr8{5aA2P0T9H$M6M_wYQEdO99m$!NZ(H=%1u+Xmvn{dx zC6F#!2~>YWy{miz(j0H*F3@P7q2|zTTa5g(4vHXKX~XC~(1mNwG;GAR=v#@X{>#y~ ze(Af~Ee|YT?u@t>Ui;k5HJx7>FX zdG@Q>NaE^q>XVn;2d3WGaOkP>e1GkkHtyt)&;F)nm-B(Z?9Y8=?$>;g*m^qmx+CeZ z?>7S*PMa_axy;j_M}Q3<0>@~lFb3p6Pt}}esr4c)wV>mE${~EQXw3AB=~MKJF*-xP zSX^?mT8+G?2*0t!wzy(g34xlEj;KeUXj84Wj~rn=8hHm-4ml!qJZXi9-$m+S=ruW_ ztEdduBNrK`rZ-#PBT-*%G3vVvZ>0x7V!rF~#Cr6u#nTf1mdSju}&7d%dc8w#B`>1HU2B#D4r8IuqzU(CZFdt9ChLpJfKY3fp3Alr>`|i(mjxthp#B zPp`uDI$YB-<678&>kYUr!1WGX@1Q<7&*7PZ)|`Ku%+>6rET!-Gq_cT;&u2gDjD98< zooF)&1sykxOtsCKDM|heXLypC1%CIQXX>Z_1Hf=U&W~%($t_7oT1kqzk|a6Y+`He6 z14e$}ED&f$Vo~pN&SS37rWVa^nbquMkM)5XjCOFpRbQclYmI5-U`>i%mjl}8 z*%p2BLEGZKTwq(&`S^|kyqk#8u)RZUFcH8dW_~Hcv&!D*K0*6kevxyD{wC)BYoF%+ z6FZ=N^e57Gm#3It#1pTX_bW0%q>Jc@dd+#~wd>_swdCVvn|F~`)!Nd4A>T9Y~)n{bd)HMzJt3NQC`WrncnAa7Paq* zXK~irKKimH*R9$1iMFBdpl^VgQIcQ234e!LzfsRM^$xKn7)RA-x8e8q*w!ArX&c_O z&&RA#mO-9_G7GG#W1_QLwRL<7N zKleFj*=KT_w^hlZr6VW$W>zLjs_K!U^F@g%4CT3b0cTgTnzO2H|F^0*b8>Cw0*Y38 zC(etX8a}@_zhK1>ioS)jSXA^(Q!InQKb=Y&()o1U%%>KtZ&tgUaHcVzm@g#rX{BdA z1>j$h*~RFG-^h(}+ehzH1}Hn)W=wg>l!>qoi%{#dR#Lm>Bn{4O4X-n zrMB7M^rFvoL>zrSWXEw=8?i0o^|-4^-OZKwofY^^?saXRYwl{R(7y`LuCdRqL2KN$ z#_`M=ylIP>bKDcR;fZbN<@}R^yy|(_)cgk22HCR|&DyOOrR}~#N;A9=_ z^nEB{o~6{RbuOL4Tx!F0Wm+7a}7 zj9@mbu(LstBGk3?dIZ;^MbX2pZ(4^pZMH3X7T4iT+svCde{?Qw!?nyMj)-S#@tgKv z#6P^}pnVU$b^OAExO0$uq>aC($a+}m8`Ao%moxcH^25>2%n|opIXU5hvGvt6U;2`> z{tJ1LzOLrH>g>LZPWSbTO~Bvx^?i2Fd-8Jj)@P0uB$E%7FVyW zI`mZ-4or|}&I%O<(z`lq%8U2yD=8b# zhTv?W9+r+cv1UuqX4KtPV$*U*W7E>g#*>M$Y3WalO-tYWv1z%lv1w^tZfsiYVVo@j z`+(ULv=nF$GMnOZ;?<6%RE#0#^Y0gP-8pUUdy!7@Z|>9nH!bSEb4PctLq>)2f${5X zM7gTqF<HCuWVSmwGd6pUlmw7_zrrBR3>Eg=S z`xaeO-R^sW?{vR4eQ~+(^$EW4Kq~)te^+f#d34DCF7SwcvSG+`W?s~TN7UqKg)sA? z$arRG%@pC=g}!nvRIRhg zBB>?+LVk_%nfVvenwx*2;9}ID7H*^dv?&>P$sD&i80&}5m)=y6QB>FyK2Sc^#G2IZ z3x{8K-C4&yx!5eoxQ^);*Y^ZNEq!M~J>hVAaXk6rYirh^Hub>blcV00tp?{e$MP?# zu#@sc)6I?_GlP^T5+n`#zeKa?k2ui@#X2-}zEt_7>mk z-3KkY=$}4=(7W)Ku~e@5^|17((*6M6($7fQ7se`)igxsRW#Y@}iLD0}s&UPA&1+fL za@~%8`p>zR;%ismB5PM$-nC1=x%Mvu?@`?xTv=`VR-+G9&10T(S+UgT^%>&7ciPrY z`~{oA+dbxqar`ZN@ptV-?;c!>7B3o@>g~!+fW~csbb29TD>^fyK0|QiCjI6zU@aes z_P0iF3j|Kqw%(Tg=5SVVX=lM?{eiZu^o&4h{_c{V-mbz>G%L&RD_d;;J(%Czx1yn; zFSPgCeR|M4Bo~GT@}otG^Vu3;Dm_|7P&N242bm zNVcs`F8I$A5EujZ!&kp>R*2pgyHQ(`6{4+p+>#oz?gDl8-9&ga*cK!Bb>JQABGVJ0 zZ}EB}v`;+|g8dirPMAy6^T?Gj-%`i%o#OaCLr_WR2{u?#S_n^Fmc90$)=rStAcDs+8$oFIbye zSm1-87U~!}z2G`e!=T?=Vk(+F!u$~C3s8O!#XJGI7$ue(PrcNdJz|Lw`LE-M#;mt3 zM&2mX$yFUeu8M!W$M*H$sXp84!*B6)2+?(iz^Os-nKP8KN3VNuJ%WDm7wFrm2duVl zT8(E$@g~U=qIRJ%725f#1yCapEr7@!eG`#8yKIX)e|&D>WcySJCYQYD)3);W7IjA7 zDtRXE3q2=h_SQ9}BhjSys#6DR+`sd6msDis&dv?kC5K_E-48m4)AJ&^1^$YfXe4WO zsFZmo)!{P9GnpueRQSHWxGnYYKF$@&2f_G;pt~Eajl(=6u2IHId|0>t|FTW=dCfM# zyFvf_i};846N4k~r+=%^wpa^+9xY;j8QarQjN3;|U$yOvpY2e9H^=>*`i!D-?hAF&pJ_WPpOB1{ z##q*eHzP&+Bvzpc3h6Y&We8Sw`2C% zF|^j$7UMb_Y>UXmt+url@5{hD#NvibjYA7sRdQ z?b)-U{%eaZTBn=In(pjyQ`1OobUa$qz9fu7E#=KiYeONV$#m&jej#FzP`~%(CF2?X zao?XRN=ufMl=%H9+~QB$j(wChGfUzBYBFbrG~t_B(}LMdQqzLGb_|`#C7l^ObzAPU zii_lL@U(5|qg|bETlsh=^)*4Nmf3#qzNk;?zDNyC`|7FJ@E9GYv&V~4mLQ!XG0QUC z?|a;>*z{HZkG4IyEfVnsn!0aX?)>ff+3$K%kRCXHzUR#Kr%+ln5^BxPEl9u7{Ws)L zZe=Oi$9+6MCq0QS9ciDzN+D(1@m+2ByV{M;Dkn|~qq~)cM zyrl?lq|9r_8%3w3Mxno)NI7{&BITsdP>yH8CQ%LtwZk2t#}p$W62;OCNXt3%@#Bf) z+xSLLfkq#QcaDiEeOF)Wq2TrImpv4mU3<0rWy&4SuS4cchC!^j4QUU9iW~4vU7(^L z?XHA8EP83Q&r31w6N+gokz#&ONh!u_(fRR9xE{EOfB3~=`}SeX*kxuP8MA$3=wtkj zJ~{o3wVZb;sfQ$eJ^VeMW@4(%%b^U(#C1+RbY&u0*Zb0k*PIWZ_ngBJUB!wf%q;m< z;&ko3@&*sFUu}w%+_0vsyuJMfPgaT4F=1MXhZlwiayGy^cp@fD-5^GAXpy9$Jz{tu zs8wxouO=o{yxZA!6ypqxbFywwe8;Y__v8C6t(YFroi@{;y-(|?26tBAj?{Y7U(|}V zl*QV|+6m)^Bin4BR(qq>qvL4xm?{{O@fHJi1N)QNH`s486Xu=|AkimN|BYg0jwE@N z3XqxH3Muj*a2%&{xT`+5iYM1$c@#u#pvaF+ggv-xNVK2wbiz^qP5$$h!vwpWjAKr?v(Q+mdt97 zi4ZB7FcIQAzLac}V}ueyjy^k4u1HP;I5B4?IJ}JMMX4H zo?902Op?2kEB62Vtepz8UoI)ywX3LPcQ#ebF5dkkh^L)r_V82xhGsT`~_*{K|~h}@7?ympcw zRAeSA{Wa;hCQ3Nlj*FxIL$;3^cad$86Pb8c<5hf5Io`uKMui>4_;43!Ea#~Sj)j;4 z{d;KD^w}1x3eh)3{F9CtK_4Tsj6!K2Q4!oF#pe{mDT%&da3Qf;cjkoV1uMg=27wyz zr=IoyoQ3)uG|zjiX5w?fNPk~nu@H<+k_Z~&Hpa4#}iJhr6`GcA~ z_!dwK(^C7HRxb8}8gVY_Q(i7=pKwuI$z0@n;#|~GZT4X2gFq*W~ z-eGMEso=&la^+h_(Z_nKv~RR;3~#8$8^m+C7)RskbjHBkYVbxe9Dt3}|Iq#Szj`iP zyAun%J0D{a_=!ZuzH(RImiEJQ*;*&Kvsiuitp}Wl``6H1l(8>9`S3@8y(V9!t~)E< zF%~3t>n409wQ(X}Mb{-?iEfov9LwN#>%^YHE}ka-5lD{HZ^xP)Fu~guX5i(@O1RB z?}%qkOl|@o+HcnS+hMnEMTOR>v|nJIPvM(4oB1%6w%M+8AMQ$v-i$8WqCZu z#ydZ>Pv(cVlII5{r|3wpD%C6_; zyeU73`itd}tZmViHLzB)vjf>-7H1z#Wb>BZgL8QN{YLUQ7|zE@iNm+=EsxfYRo;{Y zTFxp34B8ZE_t#stL%hfKXx3fl$-zLtJ0;*cJv5Z=6_^Pk5$T0WGn89r`?ymlp68Od zQ|q%{{%fD`Ut7uikMGo}rMf=XY-XRfymb+@FJ2d+0&{BFMf}6JaTSZTB)h^Y^iwZM zL%&1@S=V3RVNZfzY=+QMO_~BF#iLG1Jrj2T7409wa)0QNM^Z@qk;Ibel^(W#)KfkE z{PxzFITPTy*pVL1a-@e}cJbL~>RCB`$yERSjvM3iB>2oajf?^E3=bl!>BV!9e_R%J0oRAm;{dvFZIk6c#%HV-JMEC zJku7ddVc@DefKAnMEBQOdGO-bpMb@}bMIL1yc2rC7L#j#*crfF*@3U7giS-=Mvon= zEqbzB?Y&k|lvpo~FEevlM>4vR3)&Gy5VXBPz8_Rwf;+?zh#gdn7V!n;b{w_$THC6{ zQ_Op=H{9#C{aS~R^FV)>)y_qCUuFBa>ILD;Iie%!%id~Rl!o>A%XZ;!*=2rDE#Jq1 zg4Sn<6rZ*&)^BhIwWL!_&G#sUJU)?m^{GmU#*E`C2L(Cm>$-eKTV&MOQw+*?gE0ca zz023s_J1(gvN2Y-{AvJm@4ox=x5QF#*T!du^XmKo=iNhDS$lT3u52xFmYzRfmq(U3f3Ma-rtj$Y>Jy8Xzps62nihmJWTwmP7c0y5?aPbikL)OE?8Rv$zni_| zfcsMEk_x`e>?_-2wY4KAk}TFTweSe&REoI~F>|OCJz^nHW6<8XOv$r-j9`XsiwGsg zCnY9aZu`A)D}9^#&xkwGKE||}izV2@2(Fm_E123826K3>(iSUDzBAcgzBO4td&MgIekO{^k_9~^k6=U1})bj zPeu0?v=K2eM3>uigbQHyQ0U{wfCquut=0_d@=9{dH=%lplGrgp8q-w`{8HZb#l zxe+d^&vOA+cJjcsu z5?o9BwYYUoNlqkElDVsFg)MG9QRVS-G#&06_qnf)FBUrF-I-Wj>-vW7rPt?o6=X_X z>(N+U>)-8P`3B`_PB3t_`=2awZJ7EsU-^p{$Csg=HGTDy<{Z)0*gtlq{WCa98Ny0W zX=pcjB&oI%J&MJ4R56~*fed18gC=mH4%f`T;kE3Ma@~dgF1&x4eUiwiG28O`*THxdUq7X7q`tc)RV}ZsZ!hz^sGT&yqox0HGTqdQ!?J&tX-}&o^-E+GT;jv6|-F zvfm`Qx&3wfVz{}T#ogU8+*~-?*HS+Cak{AHc!J+)Ji)=R|CLL_H3d_ZTL$}=)>mC8 zpt;kn!vdN+UDi|;1I^{+w=P}TP<1ODfSWAiB)+oW&)Uho(3V!GeFr=vnn*A(t34Q) zASf@9cg^3+!Fa)zFs@Q$TSQfN+7@$yr3!B+-k`crjlCb2SoOA#2+bDTqUOUIP?GJ^ zZ~OHWGjd=55+W>z4R2T4zLnr(BY4MJ;|?HA%;vR4b5jVwzBy%d>9XzJ`VUeb+5P>F z53LoDTi2DR4%NE%k0i^*ZKhuG$;36bt-ZBDAa0X&ec1wW3pTa27alvUODi`NxQ11d zUu)$h7LL(p_xs-f9@T=b8!&5`V?dpaXa_&qlEp^K{=!Q-QGo;g2?s~t|*ePl~a z(fF_P=gSI~gu?zh!qC=*$_h=n<8ps?w4yR^Djco!{ew{)u8->&TW0!SL6zce=Xc(i zIqQ}8q&)*}a^GP*#D{jZk&{03h;LocBBD9)dZ8-ERrYz-VwGI8D$EJhLBsYw(M|bg zr4-vf(LVJrVD4l5r1LsE%3Cd4$Eps@m9KrB+~YhLvJ^`#RrK9k%=mEf%DQzrStJ`AUR3dYmu0qao)Tvwz09o1bvM9dhd3dk<3^_~wDQ13fE0 zFf-G3s4jST+FxePC!@ce^0N-H%;BY`k|1X>bCJ^VH%rBtbbL3f5Hm8beMEcZ*;XE& zVdk04Mb1xoQqgyk%hYRVR|?)xi>6;(wZI}=ixwzYts0CWS2^fA80 zw@D-sQYRVm5I1TCsFfU0qM75gd?y}L>b!25bFbDOUXe&-_xwHg+Gh|Yn>R4kn9HHadeCq zd!>E!dU2m-gjV|~k$C2xytx4_o(d){&1pvFC@9Xz5zpq5d(^2rY>T+7F5BWxF>G6m z+_C~4Gayo;;HWyvxyW(V#Rt|nNPW1$V-spZ_Ek_7+_wD^nO-orfxU#x@ za%3o- zjlVe$e>3GkI<6Jb$!KO6{j`2LrV!UeNAuYdTvJxFeyAch^{-HU(o(>99tg zhm+^-TX)~uH-7TkWLo@ki~FUoU%f^C-;x6wS1W8+@|t;L18I+d8btjPZCV9+7&iMi z_g|q#)b=qmQ>hWgcZkPFsOVh!@?dXKu`hgW{a7T^pXK}R>Fvjzb271JKQnsMQs?k?$T!lI zcF0q}r}e{nUMX>U_(=Y4IN3I!LP}!7}koWPW50%b@toF z@B96DRcU0Xa$Mj-hiaAnnK-jsjE_?wMA(h9#Rc~u9hvCjR^ zz%6>2sJYicKCCd@;=U`~^4mT?Mx@(TI-X(FG82?z{vGG4*qF?))c4Q_z?Du7L1hBv zpWbJ+nJU|2U17dQ^Z@#`HRGz?j^PSjGY3SAZVRL_h!?O$Eyimj=S#geK%xfclWntrWY2p@9ga9ye^rA zPE9u8KJXVDoR~OtV@+9Eb#+-;&F_0BCVFpvM`lh&dShvMAQ%n=y1IV7+p=!U20l>~z&rFkZ2o$KtB;axGT$;Py|fOFKSXu%hQra6Xlir1xeseOLXCtx^0 z94>Kv!n=G>i8~!>t}>e5#xjhcb*ay*btzBP;VJra_*5gV8)G|`MeC%br$M`){l=tQ z8*+X)`-`6TL&?;__VxRT)04q7ojuP^SZcVBOkmz}58H=tf7)beJ&P}AY=zkyZO~S# z%$L)))jdr6yn7gJDTxaSf@z`sOwR9?_Y(2MtPtXtb^l__QGbIGA?iW3=05j6l~COK zghE0sjRg_Au61VgEvl2jA8&Sl?Ejpr2`+hw-ddM@lH~E9ee%rBcMaaT>5*X9!8$1k z)c=~XsZV|C>hC6L3Qol;_co{K#Hv+4sbE#SaA9#p0M#urrastmWYuBk$e9Uh4OlXxzAi=n(=FSO;wUTB|s%H!G){j;h&Fc(1QBKvhNl9sx+vR`ZnBBAxY zW&B$}O^L?Ij>{O1-e(Lak=pVXE45`tFT0o=Z;i*=2TVjX%-HBW{21^Y{|W>Jm{#2X zj(hHTIf(w`HQ$|FduQL@2csKngdq(lN2Y=voz3U$%-hv^bk+3qD)%i1oXS5e4A%nd6QJgj!|YgM8mP%Tm|3kJu4v24742J? zE3KfoYIMBza;OLt(|D;`cH~e5{fwNH+rNUkChL|~n$@8eUeo`}-Fv`Sa#i=^y7TnZ z_0*p9q^Gj#y=zrhWwlyu-_0N zg+o|6Wn2S28|$f=FoYEhY>Agyn;r#!r4hmg+faIFEUeOlx*xU5$EaU)@bYxg!H2FJ zOYt6LA|VfXQnN$77m2q8W901*Jn$N$9lxr;j{Ob`@EkC*&qlQeW(;`J2A` z((87@NhL8ayK|v)A=|OI_O{Lq&(9B6RE?Cr4xT2dlpgP7b)PpSF*TjsR|dB1Z96gi zL(BIlGbg{u_B^SxnO^`u$OiTz;isFv9(g|$ogBE1G&oDc z(^je;7m71j4CRS9iR5Ysr=|{?Z^WGo|6?7BSk>?bIcWgDqEA7)thP%1JnY+eo_J=< zTfse0lb!uT2le6nM}9Oje*d<6 zGyUU~X~~sbAIcW@G%jpeSlDu`d3rYc?7H|SVHgrCLFs=kz4OcQQ6j#V8$DWvheG1%&_bKd6awqmC#JjQ0zh1Y) zlF9f4zS!YBCGsD;mlgi!}?6v)XNr7awH;Cd`|K*E!8knl37C!1yp z`e5Kib~xN2-W>({4#?d&o%pSFDRM`J?g#Z@*OM%7@}@wRw@rF1aLMNtSi@u_{J)T+ zZ9BaI=Td36e4*$!?WNy}GphImvYbLn0LNO?uJq*D8I0fHzy{~p=E4U*_!?k%_itpw-W^__kyP1nexRkz??m&av`+Q@f%M6ViNlwb=jWH>Z(q~==;GqQfdd1h|5o8i zGQ6JpR8O8evAIPHG2biApPDN4Z{4wD+)t<5qQXK8-+Zn?#jZ*^f!|K}j-`QfY5f^^ zET1}A!cM1Ifvqf-t_^xo(Z5yGT12iboI<5dPN5a_EZ`C6208N}-*>&m4=o*?l}{;5 z<&wwdt9&2f#7k|PMxNy}|Au{;QYWB)k{nWg}^FqIQ$DG-}q^`Afb|3HQSzP?~ za0g|%q=dunKfc&)WiL*F6ib!o$S9iAvW0y=p<@p$QbSWaW< zx0JpUoD#9YJQlj+9u4)-+vG%!GhY>ruc9{O@0EQ-?vw~0#)fb$7v05N3$lcaMJ>9` z8UhzX<}*kZ_GukPd#CIWvSL*%uK)DlR|D41^LPQ{F|#v zeJL*Hfs$!o zz%(XHA}M!>>HPx^CNT5~*Zxo3__LpET-w|AwoH{=l$@H@;4`1;z57Iw-{s0S9 z-20Z6-uJ%ueKfPVXJ|uRYsrR%)aDX@Ui!^lJF*gUa(!kn{W?eV{@3W{%OULKfdl*IVg& zYv@c#Qs^jNB_!igUM9;|p;b9&)j4@>Bikqg)A^eETeEJ?PRlE3&7Lnm*jSS9N;Ia* zskTvRYPx#wqptn`c;hE!9#YVbbEPn3NU(w6uh5Lbxq3Br_1+S+_?kQxs{i}Agd zkvj@JX(=`Nrn&FF1#eNJJ14vU{K@$y^Ifx~hWcl}uVm#e2Vs*cYG(@-Rchye9^ zh&H(m*1$pyL4IV31a@v2lTUNWwrV+RgZlY?P(O4jtaIWyhYnu)t+V!{%#l#B50+WP z7)d{3jJVLq7TAf$$H;G}#q z>#a;e#@OQDSn_Va$4%+Y3o^|YKKzJ}vZQ9^EPrvQd7ClnEi|vV|9<0fTTuMF%F2^V zODErzv%!;_SXY>t?{O#Y9LO#76Q8F1fo;U zWsbNONR5(yh6urMVF4F-P}@@@)2Q6Z=rGor~Wsb}r`UtQ8~+Dp~O> z>MAJ3fmr^C7n2<@oSv_#nXfYc-leuwPdAu_umk?{%q?bhFaZxHr=C>qjVH&Jmd4DF zyZ*$c)~}DzBv`!mxJ9o#N7$<{N02ID0c1G<+S3HWJ?6@-TSd|i=>B0H#0=pqEcb%D zcr*kF8~!M)Lk*r2epg^lQfZc%f>}P1`LQHjOB0yJmw& zeShUCDwZ8ElRkaxtzREsS{k2gnlAUu&$&u%0{iMXuVa=)3rV^{^z4H)Gq6IzYow6m z({xMTLIwtrx1=pVL+~fz6Q0PXpqxyaNqCRrL?L?=BqKR#K(-QH8Z3z{msaR^N>v4Z zLIXVwTpUkmq-)+KMWyPny8;u3eN`{c>gv`bEGUs5+QMXmhcjVHE)rrac}?zU(Oehy8Rr-Rs6+0UWe z;pYHpNGJ$Wj`V>7VTomL1jyo|^)1$|;_pDa1ATcZje%!Qz{bk=ij9@E^KI7qFk9Vp z4>CgZ>*wKQT|_-Bqf!>l!10JPz0^2(UGQ>rScU3n9)FwpM&q{YJ>>%jJ39{!l&fpa zf0()7wg2NQ|HnaqkF_^8w&Sn(si(?H3s0Qzm66XvZf;Hg#qx6SI75_$KPb=5Ew9MS z`_E>YUz`P)uVs+`QUTG&74{wjdwTF5!+y(wJ%;KI*}lwy>Yk7+c^qs;yfRsy#9E~p zp?LyN$fxUKx-Jge0pRRU6qQp&X)@^lojl%n{NjDC{Xgd_wtuHKUQaU2<(5anAI_Tp zaf$iWZ_r=Bz5tmSnTf8nzX&^3@E5TMa_|>%n|u*_P>Q_(D^5--xMq$5PZwo-Gm9lL zR0_to==>g*iLg!4rbY&KB=K>6la@0l^*u_m6|ICZJr)}FQF>O$oRAX%9j;chg$G%_ zL+46WkIdw}?e~@mykMD4;8T?c+Z`tGH##le4?1UY<@5FPHD}5S`~zjX+4MbM-Vn0d$r|gXcAd0>id#BqSe2$xY0JL!xx> zE6mPi-o-jv=3Q+G_ry)<;9X4VveNlf%xwYQ1?rc*qEO!hDLR*W#ODy4jky`?8#q%O z)1wj>UA<+CN9O-GC(Z9S9RImx4$9B+iseoWL%SAXKcqq|U# z3;VFpGGxSU3GcEo0j*dtCOA)ZfUn@J$8C^^fCGjCRRVDGqMey$1aT8S>q<`4(ChGc z=ygcYfdyR{)`OUhLNKUZR+?*v%aLCjBsu3 zqkXTJQ1Fx0y=y0!9{GHCz_Aii3Eb-zfv`7>V)=tc1QrVN%yEFY;Y_0-p znsLqTxgY+~jB3C8_Dig-)aEkgM8k<+S&`V;aQa9qpjwFI)p^IJRl{QESC)e2oU?Ba zB|JrQ4k-dLD+$DXIA$e*<`Mqkkh?^`iXe4xFL98iGF4pmB2M zK~%fUbder~y}Fco%IRs?Q*kYtBit<*Kvor0nn!jQ`GvqVu#O4)Kx7GYV-HE7v<2AV#PboIQt#fB zk~%dpam2ij_J*<#W==TFT*k9lFK>G4sXP7o`F{Kf7hCy$ZmDN_+Ebdlbz^LlIL}P%xK?t2%BRvH zK~b!=-4^9z=Pl?`|1s8i!FRnUJwL6mFh6;ZZ?GB_LjL>MwI{AND7j`R@vr>m1eFBY zam)7Hyn!J~1wz&qQeB^~94bmnOeJ%RN<4JP{6Ca>ginsooHQ@rJ3@vQ`VYR4GuGT@ zkR&uh*;0t|X=YbHH<7$&OOwzou$B%{r_w4>r=h&r-Xa4Uf7>{vHT|`s@~_<(diH6n z>a57RH7(`xhWcAG)8ES4{*z^U8#DbRGcS})SlWJ9k;SL&bMne(i-*U?%KgQ@7T=k+ zlkNWEqE7#ntnRV|EFaAv7iv!|^&;j?5p>8&~}`w9F#AZfTrJHlEK zSWK}ig+>}mKl5mTpp7Zf_XcVvpcVp7HjqMOtVki?z|tlhn7FE_h{M7-Egf+fH#NTJ z>#z8jt+jt~_s8aKt^L`>S<>1Yl_45?W~YaIP2L99+RvAFh}OQMwypFmH1?Mh_ZeS`LaA<;hY zDUjPl|Bf{-UmG0-#c3BTf$sO_$JC^-J+mmcJgX?N*5~sj?aU#wonhpr zWt1kSRa91_&E@5J3V*ls<9UnzSU;6TG*h1N2AWYsfPns}+`UbItaleEpfg3r(Nv3~ zGWA&a=s>TGC=0fFKnE-LLI+Fd7NS9ls<59fTI3LIdT^>>W?DwD7TvfkScA?4wK+NU zoN_mxGw&k>x~0GR-AUm;$F1`if9vJ;w`S0{D*82?1>TvzUfQ5NXFELdLU5F4@YnIZ z!C%L1fv<~@Enb4H`0H*njz`mf^Oybmv9_aCo<*p?tZ`OQElT=2hy{k#wfH3(I%nH;VHlPBySs%X5loHgLv476@qz=(!=4 zvEI&>%ACsVpyQ2}ze=?h+Z(>$y!g;V_ncfN9ro$dscFk6jV4Cv?@yZ7z9CqDy@A$k z9i0;3V-Go%_19jT%EB!mux&6c7SlH}rxh(Vc!0DyWhiN@rkN$52>UL`2RMTer=U4? z(G0NOE`nCt5yQwxPo@R$45<5U_Kn7EH)e}A`f%8c{HOV5^*ZyHqL0q6EIM|qxV&z# zK0m*H&{e>c@sndem@)sWytuf$qNs>yATi;9oi{v#H1+V;xj?good$WX6t(c#K0y5` zx-Gy(Gj$s*MY$S+Ho~VN#HAHk^szy=K`O1)5Ug|9i9-0JyT?lY;Ifi%3>#JyIn7Q^ z)!WsB<~Kc5HSh!NP3ot*6GI`=;)3;pTt(}}Y{F_^DxnR~9ix-UlvwRL(nOj{2 zIkoAjnJI~9RASPbjnb99%jW061KeTr&}v23z0xxwayZ)|!}T(8%oHoPtp8tqzHa!a zYP`X`-%|2NpR`NN&pt+fHvP=FuBUidKhb>?$;E#|^aI@yEVM3aVJj*22BlX4pC(z4 z#8NRN6B!H11e!doHE9d1wR+u#xP@j7K?mERA$a!oXb93V?ZTEX5}h+57zAqToLSUK z6@^R%!DOedx=(eDwcVQkj_ed~euw8&*HlJP+BH9S(4cYOEw_9DuP>4VlBx^*^l$bPnAiY_7h1p*QSs%T1p9wb#q zqR;Pd=xeR85}F5vCRQC0y9_d#lU+t9BIBOsP!5B=7=nH&kk6D~gk{rA@GlEH}~?Y}1ie>^zNn z4D?-WU50!qW1x4f(Ga4G0(z%T-43s9*pt}{JJi}Xq{kuVa=V6*wQiS&b`i8sL;DCi ztf9m7d|31jKT3b0nqCQ9B*z=eCKS$<$V6nR(JdOn*&)P2R7WPFAhv%bvrm0`6KOuC zXVh#Yc4huoXzp`k!I9eBUF?_bbmdot`G*d9i~4qKS9^?9^YuaN_wTOz+Lu;C4kJf~@+pUeUNtH z}|GJ9CLJOIEOu*%K6}9V8=91n%DiVVd+;JI2C*@3>V3nl-A#}jV6WRtChGaY!;wn_qc_pKvkn$=kh~FINPLzXCk&7-oT#2{qR93jquS}0 zHqrfTA*GWPU9;~p+4ATc}?UnPj-qL5=dz!iK8IOII< zyygZ8gL|!A9ysi`ao8ULhujv7Lv9lsG9)-;NN~uI;1Ik$+pdX&Q#m*pkEqw29#KD# zX@L#S#wiw8$bm8*F%$5_Wt$RXZsbu!ck=aSx`wwo#%!hQt@O5?`tF_dwr$os;M1^| z`Vr}~+6rBRk$iPbn*@*KfzaQuVSMU`1~_`Kjsc zIo3XP#DyI0-9*XTD33erx~L8X39Fu3II9=DrxWS>5kFa~TM?~Nts&T;5Ce{#82V_r z7v7QZ3q;1$0FHWfKYS0c9#MZ=?ir@GL8}dQp!hd{=Wo{#q_jO6+C$I*4IQAn57FHL zJBn>22;^X|wNtR$DJPt+BgqcYAmVA#DCqCKH9hT3Vr8H3Z-$jU$4E&>4)%v0Qr(iV zT`BYRs|xCieQ!HfQCU4&cB9zdFR2@Z?LEtzLJseV$@8~&F8rdJt@dfDuHLBor=<%y z;zE9Q_|3vDx!bCu0?$gUHMH=l9x=2Dgi+{$J9KNnChwv?*eE)(1@j!4%Ki<>)SHZF z5?)z%nn^8K>3RBDh)wWo2-(}jlU9C11+{U;fHZoG*zMt=!uuvxvW)GarwwR`^T(JQuHww34Gf28T@TS8-1p#vsz*|;(^gqce73@g*Sqh@z4wo~g_`F|FE`I`0h=hgi3D#L^|O4*+G@Ru!~Dflu}V=wGuJ zfZV|rCV^sm0m!KMyZ|5-$sNcBBK`otANbt)xpFKo(duTSG zqn@Da3F6S}@f?UGYLSrT+TE1gYu-i?wjKSOH!P6bSkEUi+73}vZC6s0`CcatL{uOR zHa9;x|B;}O+uNEKe^O&d+J0nS{VwWiHb*V}CZD~pvd&tvrY92SRH{t}$P}t*zPrM9 zWoZlS${sxqn)F-^Me=)s)+pHTX@ee*^H-CG#D*5UZu$2JUKtX+G9-9qNbm~2F25X@ zg)h}U!t6e}?xNoW&W@^D@evu8yR)sdu!ylMfy|bU#f#Xzy6FA2rIZv3<7N7^5z@rx5IHH* z2^v$&KIn;h{JwbA+%L?}oWEj;PLIy{frox8oxl-W1C0=B zhbw}!!q$tl1?I=2$61jxL~pRf7wT462T=zZQo1p!z(-3A1nhHK+ zMD!J;B0v>LcS8qlYm)N9wHVHMGn#KU^A~Pbqvq#5{~1YTD>G+4X}*6>B^|tL=U}G# zn;^x{bw;W+ceAdy5x-%7nH^N608w<1rP*Vq$Kf%PLVGm(v0&E7lajtDn#as8Jr;RN zLOo_MJMt`<9b~3Azf%hQYzj z1hJQ=<1>X%GWR547n|+1Dmdnk`v1`we%gt4*ZWH$-cl?f< zwq<(y2Cf$moXe_){p^ABhyDA_Cn#OKt)ex<6n5tE-9zxmVO{$HYp+1m)JVcd33Kqq z!8wY2YZ9u%s9xFvRG+EGfh%}51lsp$2>FEyH3T0ER1)OpHxksUp;m&rG=%-CPebsl z7_jgWbgs(NuCP|zGx_w`&J{J`dQ|5kXlq~C)%w=#-xV4eS*`iMD&4XFaGlSe=*}?S z6^S{^l34j-cF)LISz%du)oU}Fef}KJyGlA6N>ki9nOUX3HD*GMJecQM*OfHS4Mb-H zv}1jM<{3V8u)cVxC6KesOY7R2~( zGrC1@J>@z@bj`kNV+nsxGulD(0(sFzC&k#_YtqkW3xU{sO(5}J!`>)u&ivBS7Vu+h z)#JcPIyJ=eFXNf(3xteGs3sEI<1M&MLB!L(E7Lbrb+=u&z}$QLKD%zgnUk{>=DkL` zRj1&}RVn^JL6f(RYZuH{c4j2zW_U`IvT7O|y=U@DHW*h$Cv?#HlvTgG!jfZ9YZ#u! zkY%`fLFX#f3#1=d$*1|_a}@S+$SMp;Zb?|~r45#Q&W_ut+i;$PmodDHWgNVVyEMf7 zUHTB$Hl+JtgC!qNx_gIi+d*y6vV~xZ_`R+$Q4vy4A|j%EWRq~^;$qed|d0GGPtYQtYY;r1{9SxKjeP7_=7{^e=qxMe_nrJoZ3l%^O?4c{f4! zcey`<<_|g;WYd>6#1}yp!+tGokm4b$!e2w$z$al<CK_p%ClyxP`3qq0ZVloWc&&ZRS;CGAw(KBX-IZ=(o1pNym$(Rs-wc(SDrE^ zouvjAR-M0}EHy1wWu97a`J$4joRMI|mAUIl_zY1fW)JlR66lvF+Y~AhCa5yN)+>=} zx`<*Wx*j?h4^cAq3d|(m9XylV7Ce*OCNs&9%p^lHlMKmBveu`E-q;hQ^$9C25RqRX z6w9?;N(*$ZI;rpZ@Q3d?aT(Vaxa@>c7nNh1ueyOI&$6ZLc8$~g=FwbKTXN!di*rL$ zj#Fq7wes08iCUNkAj5;SA|fGQL&!M7KAI)EEwGnX=r+t;jfQv?%M&4&x9Pq>)w^EZ zhFx?(Ly%~3vc*mc9jiQNE43#PwztyUBP);Fp<7|mW;H3&;?@$iUsvT(sweA=appuy zij*C=b5)F-Hb1XMUqIP`>e9~As?rkQ>}+~bR^0%C_y=76sKo#4S@XHlqQbHwpUZ_( z?Zii}BVOH2xXLF##|<=pkR+k)ggj4izqULd(5B?-Ht5chtocF44wm~-t369Yz;%I! zpocHjknFpZc%6E{{C3WsJC5Z03|DUU z;eR>P(q%k&;lfQHR`oZTpSnZU-)MaM{I_xpPddc_`h1B6mC3HwjvEcv%CSq#yM9T3 zG#@USj~PqmC?;vE+wx$8#Qua$Qa|)Jf9K9_!={{UvtQB!bzB zl|-jm_#gq9;6>}4_H}zI>ac6>S7O4#3{&F#3{fcjT4`=;l#(*v_aj53~yUB z1fMrltL5KgSJ7K7tpLLp$#e4t%wJN7Mnd6VH=gZVH+JF48uYqIY?op zlYZn!8PO2*eR?>@@=M!Bm0)t6WBV+RhX zW%a|AA3jGuXofd0-|u#(rKY%&8(LKL;Iw&>V)}~w<>eO7K4SCic58P<#S83MI3+6D z#acs7|GB!&iB}oNcohhE_3828dmA+*@jSo=0n%aKc&ETIq_loZ^qt zpq~NEx6)lKy|8wNe{XNVq7kyZ!c7~Dr*6*sl1E!XB>e2MlO3F><75X#L!(C|j zXI0nA4Ilons-~>;Tg86|0poAHaN%`h8IiEE@{MUVXkK!$d+E1L!M;1{D)p6%-}}ZF zkeD90nYM9LPV_cRa@z~EGKT4^Al)fy=?%k;v^jAjZHya%urg}(Gms%jBFB4a&Y1hr zo9J3r2j)_IcsJ`iH`7kV5<#VIL(B#;;;{w}+>Iled+Cb3w^|7&Sl=7AgDm=jm5{61n@3&P^nl+z-@+PclW6dpJu zm(_JHJ%>WuLH;?fCPY4Q;s7PMfJ{1V)q>3@N<|fR@VCA6eTbJp4ff_REJ~Xbi_*qe z6o~noK;Uo1`ibzvDzbK@053!JhEQH6cY~J|)0~SXW{ZB(7J3q*H@H$d|K43|<8LhG z1}UxK#$!o*tqQ9w()t=E&$!yVLJ9_`tq6?1(UXb5=z`?k?c1&77-~xtCiwLT2=eXt zs{>8Vqg&pR)j<`0$>ryYU7cj4NiSFb4>3mIjD1$~NzR3|0slwr)Qqz&5pX7LPMk>_ z<4hpNnLxnV0KI`{6;)f|F%?*K1B8+AJt-0%cd!OrpxE9uGAe%W8o5KX za^Qf{wuvZ#vu(gq!M`7Sa-W8vlLg+m55AB%bB;aA*><7D*+$pfaN2@noRztdC5=#b zx!@cep-dJ>Qz%*X2W6>uB;%mW^yY;q^8cMJEziwA6687a(Z0oBx7waFkIbtl!{wGM zhv%u$U=o+Z4t>rOmk(rH$93K)eZ027DFAl^@F%*zEWd-6qA)c(8=s7#BwGWv|yr3fQeBm-A z*HF{$G0u3EIE4S^4}D0L-IiIu&Gw2p2d|ieo-TD;zvsxoLzAli!i7BZ56b#uctTGyUIhGr7&XQK_VVrNJUbod# z8`}o^bsMs(u=TcGx3$yzdo%>r^wRmsW+t9u)x}F07lp)_wQdhNxdp-m@dmhn!ozuQ@g0rApa; zZ&7O6%6t@zyaU#!p@#ax#9A1i4p+9hjoj>1M-)VJ{wt&^Cg5Jy626ou$RH)ma9VycgG^{lmLKVBn z7N!UjZQMt;r5_}!n%c=0v)9;nVdbBqOzFlf;~ZI(y3d*Ki>AWEyd8IKC!Uf;zo)^< z+XBg!ElCX#EJ@N9*^(r^0sBWKJ(V*^z~0Sy3W{_aVknWTokze=CoL{efNd)l>C&qs?D!-g4Q>rg{P>kzmi z`Mc1ng3n7MeL-aFklY7><;__gH7|-LB0vXV4*{ zGX0>HZK|1mA*^C26sin-d6PAdeLm*y^m1b4Uknl!yv31AQ^0X!{10 zaE-^eu{yWFotfP+Utipm-hQT`vHd6N*Eifi7NL7p=S}9__o>bsjq^XuNJ>{Xy{@3 z&J==&Ey+3(CZsQ3Ovre~gg~({u}i;y7yTl(n$Rz!86GEGA@9I0S_M0-wX{!<-A7p4 zZ?zrJZ3l3ojRylxZ$(0jClF`Us<u9 zM&L_IqVbI%Q!R$t2HdTRu$69qSN~|kroqJt%X@sOu2ff2V)k=q z&Bqdrw*arSwt&wm8=prK7A$??0?icS;Zg|R8Wo??7cV|#JmXWKSomzz?-$=A`dx(0 zO@vLH_?qN8`pfk|4%R!yRTX ziwF64-&*zOE9JR~?lRxyY&e^(o{W|OLXF2q2m`ZoWJW6nd8tH$iA6C-s zx_>)C2Q+kmpu-vh-$O0OX^WZ`bUW4$G|>z6w1v1SD=TV!Gqn5Ox_u<_?egw3#z+48*nK%_HZo zrZg1B8G9{5ZaQMm`3TYUUR6Z1zMW=$$eQ)-cCGnHyS4PiJL@u@XI-G!vo53H7AV4t`8B z0)9+G^xVC4uNB)J&u$+vhc|LB2twH(ht}hGg(ZS@S2;wmt|h8C@{^lB{b@DuP-g2X zvB?f^8Q(BxyapJ)@ja^eM&r^4Ad;0W-yJNH<>Xr;+1T>R3*Af4lNm7BL~FeJ{AbkH zS3Y*qJPn!I?ZAB_ef{o)1FC_rzni`rRXkIug{yc*!oKvyi+vf-*cT`|_7RsOnFZk$ zA$LGpZq^VaeAFh}XJMJ`e;ohUMp%O$2R4mPs~2%T-PTnf^#T9G`ZZo&ek8frKfwm+0aE%>c4sr68Igp$38?GK-dG?Mw)P~zLtcu)Lz4W70FP*9A>T%DiRAj!> zJOdl`_$AHVOaI**l0(9HCwR=oCr%wk83yZIF8j++!VJlYZla{)G&7LSQxcBbHjGFd zM*8BVBpJ_?Bv33$s@3nu{?e$Sz*z$R2E3QRjuN_;$U7jV;A|nX;ZgmhqeK_;7F{gp zwz%cJh6FOi8$W5p!W9nTu4v5MG{x+@!K`r zRf8p2th(hqKe+fjS!tZrBl7y*d#tU!W^4JIC3(f=4MSWw!gvUD5<(w)6DCzR(Z{5w zkI5MHA${@Ehm2?X5GWRX(C@L|56=qbH1Lmj>Pz==Jy*cKFFP z+u`L7w!;e)+YT?I;@J4 zh9IFrO4|M?%k0Rlvb@cpPLZQl2bYPL4o6NYrqU?w!{C({%3<>t5(c=d3GG-x7^n zT0akp;$k3zjnmBlNiSn=Y`2lmWX0{7^*e2cgG=CWa5$?=eP|$i`rx4{H3+VhXTG44 zKe>V24NCG8eH&Jlcvk)p?tm~*S-iMdT0S;4WqjcL-RhB*&n=ig_E%Q=izBsh(n}J`~&f+DY%-BI@t>5CWBGM+IlP;5-gC}0{V;ZRIVKXO~L#TVX9(hBdU%@#g) z=(Ziywu{<$m)JwRU=MxiLEV3l`e7@J(>fNwdR-0Dcm#)a3({d(j>-7dW4`{%zqMUz ze$g~_cwa>g`NiaPoIf>LOg=Tm`Tmr&RG|J%@SjB#0K3Tf2)r}Fe?BUaPj!5Cl_R_WRcHG*dvuKALO!xue4YnTk z=^2dR(<5z>e0mD$3GAH%Z2GMk6`z56-B(Y29RHI?D+f8wA%z#vbpc(=&R?U)bHt-O z8P=?N8ZUZI_#233yGP#>$Zy}T+xiJBVUgwWaAgtT|IHXQcdEP1!yfgJnYZ9uU0Q$f zRL_Z4@*y%l9*x$U^!}!>o@Vt!?_9+^S=u-qw^MFqg^!2GUo2fKYIMaCO8oo8a z4*LT|#t!$zj~yN_*kNcj?C_{y>~I_WAn|KA)34nebOK`^rMUbI1XGsVQi-@Nd1Edo z%hv-QOkX_p2KHcj!zuOARRtaL3%L0GcR;`AN;pKk?-2RjSY9{EMHmAmvlX}?suj4L ze3;n!ih4=Wy>8%v!>fqp1)D@V|CFYVCeGIKfz9u~6YsO};A9(N=YHF$nFSqa5Mc-%9hg7JX%R zdO>gLwY}HU|El*@71m}{9ja<<`?7lIvuflf^8=5l5widMJe7QLrj~!0=5nbM|M0by zr=NIyB0bmb%F3qycel2x*DbF+d5QV4U(g@$WDuT?x~{PBG-;hhfF)S2Q|Jq~N0Cv0 zCGJ~4miT_b5<}rw;&#CjLxLrSVqu9+EB5ci39F0n*oChnJno}wNMnbHCZIP9NF{M$ zM|^iIU*D+CJ2CP0&n2yuc^6WW-yHDTnJV5|YkTc{QuP|~VYAEM*}J)+Yoo8l`EGE!-+;OVbh08$ZzW8_BWaiJhldwVH*y|@K6cU?KTTt&9db&X zw4lhbhbs3$VG+5sOQ>T{Ov3oq_|crdQU+XlN`0?km!8F%X>sW}$wgf@`+RokS2nBd0uDng+W>&lL;r(ahqb0j}_cu zAO^*7-})(r?-z<;D4b%rT_}bjp%{i%qZl3quD~ZC!~@8eK~5ji&=8FQrQqBnaZj)V z%jg|6`k;oOA)C|?>=w|)&CtCMCmhr5$81VGMs!C85$!h^AKf|9r=VDji#L^?SnfVC z3GW*jz3TG=Ny$g2r{^9>^$nD=qfcX78-npKHUC?sJW^U*Tv}S3ROk;QJ5zoAt3#n% z%@zLq!-vxgJi~kUs)}EP`T69JPd?)2a-Ur!6kHNDJp{u<-rpWMo-z z&zHWWwtg|wx3Rn3Yo~1(-L`{Vgxt5Qnj4MFAB1#RyL=y{!?q9IX|{ghk+Gm9yM1}( zIV*{SG7>2hkfT-$(m2q*km#U`PMWtvYPU@puq|O%*d1e6;J)>*Q@&r;DMR7wl-p&U zG9>Giq3G+BJ;qoI4o?vI9-Lb?YG@;27~UYzX9eP$VP#_z&OWnu#CWW!j=PzFEr}~ z3EYPBKYSHAQweI;u;0Lby4qsV9$R>sgYiAECTyWMh}CvY+$V}}QGgLyi521@tuJ2v zOL8ijSb37X0UGYf$ZM>t$nX_dZbhfyR#ZOWiHp3+P28a6;AnQSqdQVNbL9D$cP?M=X0XKZEQ!p~pN#y05@RSdVM- z>bUHYw)Q=n-zaWHXKVX|YT|snfAQHCrlFjibjuzGIcLeDo9*P!IAv4LxXqckPFUnq zG54*XGx7bxnHUP^Ox!MEt$l1~U^%9n_zKQz zefkderkDE>YXwh%F&Z}pdZcU7&p;~Tw?Hb|MLm0I6m~OQGad2WhpFB2#-VocQ^Hf% zx8p$>yLz$`WWb0?ZN~Q2NIJM)2 zgq1>S6D>POy_QfbB95VB=lg{27y{in_3Aj6aSzUA(;Av4%3~iR;ZxIuap6;ebJ>i zd6+7Y%cv=$MLzk#V~Wpi93KqoS>t)%VM#z~4ehc`E>IO#9UoYTdaUA~1zi@IL^A|E zQ`uUYc_BUhCQoWXY9VEEIaoAO1D_|;Ja+9RR~y${lIjlA0!7r?bybfHk5OKi4FjdG z&1%n0NmZ%o=gJ4|x-u$#dfNPEV*SJ@IW$3MH|@H~q79A_gU)V~&4oA*QRJPE`_|8e z_7z*F{xLtNWhJ*t#6l>>$m5)b369ms|KHrOdLE?o*^*F>w?bHzbz&TgX+D>6G zBuEJxoVbFWUt&^$;U}!$T71NNB!%{?-s%rWCUfs z`KPD4PBf7(m30O^ZR=Pmx1ANO4NPscF|{$qd4T)Yk14)iFvU` z*Ct;2n-6^`t_5dKoVto#tgbrs^q*p1g}!{Z>#!wLjZlongylONk6Z=6CXskPO_hD1 z>vPc@xM&WtX$~^!I+Ly?cToYgx%84q6Ht*eStU>#Kb{%BHl{R=QG+G*I!;BF9xTms#(jit0n(Z86a`jO?S3Vimx0+M(V8Mi|~A@ z$%m{%e>qh--^}oj*FC+QS=3ZjkZ%}SSsjP!H#DT@cWvy>UhD@?VdOhAEcUFNrF+V>kD}xGhEMMzd{SL_yf@&plC+ZS4STo$B+mP90qlP4p zYk>M=X7;MFXWPo|MFgKy729?C*Vod27pMXQ{H9lRnXWx|?A#kDtrrzLx!>Yd@No~! z`(VOzM8|(@Gf!C|Xf+`c7bpIHx`t&Ak{$0b>%ok}zcViUtR?fBASpEW8sljX>D7?c zc$&U}bFWRu$h{_g@vaXU&+9{=SnFdK{T|N!7EkUq8M}|x4YV+@j!7G=85{*YsoN$U zI=q-vdPjBXw8H4Iz$kTIOti(3la1Hisw*zetZdKn!nAqedA%kFtUP;Ik-W3C zN8MS#3wdvd7uPagcp={%3)kRkNSJ#+zRsQoLhcAIIj++I!x+nQEyw$Id|E)FB`AFct zjGd;nhp5hnDX)dJ%~RV^tL>O>bNV^PUXSa`mlx0CTw~6>co*uLvgZA#UauT;&b+yc zJUrNK5C(ibnq$atn0fnrfi6a6Y#p%N{IyeQJjdGiDcM1KwF5vVkQ znjRb-I7B<>5UuOYx*xV~NVua-}bgV3V~sRgCeW13nep&k{zS~Vcmkx%dGbCc(mSIekZ zY01i`_5KiuZ{vJ=gE8{yNngB_CgYjX1d2sz$jskj=_+J@fPO8IPfvP9H-j2j(uP{v z(7nNfO4<mO&A;}$*;-^S5xSP#fT>?SzD znh!TYsTxY9Z%ww=lbdEI-MT{UUyt?ug?bz?6&iCWPpqfDcw!D^JV&(&6g#R-Mg^kU zHtFAlS|ixM;WsDah6qn?Y|eCGp(Be`<R`;kwa6-52jFl4tQM5-9d6l2OPJGNIpyj4yjFT9GK<3F40p#BGtGJ&@BXQhr2v zB71ZQ6v&UbO}}Luy=AL~Uu4PSc|evtSW*tqyW-B07j8}Gf-;;R&)(=?Lf%Bi|4Yi8 z_$wxfklcw(7s#DR*>)5%;KC=5b0<#3$ek#C@luA2XUY&LI%S0BPLw-1ccMU&JMo}J zDXoODR{He~ggvo%#Lk^4&*9vO0tIp>?xI=Y{E-1m*&f}thu(#g^(4JF?z3Aw`4oj- zy1`9|tw+yb6)UGA)67fFs%VpqGp{1k4Du>YCLFb5tq?T?DJX?nqUTkVzIbUy#xux)sJ#e&RdG_lY7hG{r*DCoInZjO%jEg^G-V~B^k?CxR=0Yr^Or=(#%TP~CY1Z5r)3P4d4@=im{B`vXPeRVGZTY;q%U6jk?~AF0>z>q z`aSmh;WH|hjGemm<;ck>Z-6EkHbu_sN$ZEMC2!hciyCC{H`` zlIbmCp2mP8Bs!6;maCD;ZFQ=Om95bjw#DXv%#2J^GYRwR3Y&g7U*pW0^EJvHoUc(J z*e{Vaqkz^jtfmQc?W1ed+bg2?W?Sc}BI+rn9=2TabtR3ewD0DeIEVq0J0j(4l)iZL zHOhF-*C`Z zb1p}L0ycEvN&EDBf~_X}Zn2uMZte(C$`M*AbNZe+;#tt_K4jIvS+uT@-|;k!JiUJ2 z6(hf+&AReJ%=Iz%%eSnS;<27dOz9+#R9o^T=Xm_}x$$#T>Pst+9HT6c<>h{^F+WUk z?4Ub0=}3`(>BmHKuv|cglSnOYivuMRk=aAJ#o(wOW3Jq1zm@*n)P2*9m(nHsL{zt}qxu==lfqGxyc+wWg?bW5* zkSigPBx-1IkavugAX@^-1_1!L>VeX(;AG5#)?U-7(m?hociUG7!# z5!qJIi$A*QO3NmL{fF_AN?$rax~Ja~UIyrU44N-RErx{`MJ>rRSI90ks9OhVep0OY z$<=MS)aJG3A&thT(fCT;hkA5At53Xcd^GRul@X{TxXLJb3)(d5@d`_5T~>**e`TN{KYWUincpeu(R%PZE2E8}f9n;RBxR=wuN zc<^I>H@{y)n$~}FxcORbvVH`Zf=9+rGwTrL$LVuX(;Zzi9r~Y(!g#< z7(uJ*iD}JHwkOcay9SPKu6(OUrTUBvPiy|O?eAU8FHTEe)fVMDH-GMKW5>nM`Ub~# zR5i3!*W8-X?DOY%{&wJKkvpe^yxw5z5WF2AOYwIJZ}WsVXm?Tw9<$bJBn^c0#fvu? z&v+9k7T$XF`>|IGw>_j=B~});M|s{ftx&|JJxmgkw9UpX6WLgzEMm5jKDl*pnDm>j4eHLOp09S7(_a6;qu^RgU_oF%fK3j?DD-&Wu!5@xPVo z8JpGq<)-$IO`AH}H?5A>ds_EwEG^x*r?qWQcWG(&9^)g7yp@L5?(Wvst}f_%uvW!~ zWt=QrIkZ+$>xXkyABd5wTKeL}qKs!O3KR>A_2lOjJ6E;zbFONEI9Ihm&Ro^f7RXh- zN55ka(E*~JkriLY#jPa_#PI0l9G1U2psR`QKA_^rVIA+fj-AEY*dR;UvU3UzY$M6! zh(h!ywCdd!$37UtvsU`zr2-kxR3K1nDv(jp@>okhWCO`qu!X*ZeSV#Jtfg&-#`Ru3 zPO?J5mMY^W==+ao=m_0~dQNe2f&fiK&2DXz#LJZ7nhE1&%5iES!0?&s1MFLlUxrVfE(QAdq_|9W#=%Uc5H;BNiQU@s^BPVsWWxl!&N zj8_^6iS4rTUdP23!g627%LN?SuU##A$y+#e`lH~K41W~Pf4w%g(*zKeC-N?4dH=7=0PbU1KriF6oPxr^q^HpthkiyS2k!5?P3?uXnpZuNH&h1%8A2$yT~7z%iAa>SQY#Ku%u?y7=?Q%qPps%F4@&ixCHQg5tpDNzc_p*>%26*oM^#)+)r<`l9Th$a~6th}=xF zW=>-Ll4#yU>xgU7Izmh4jQ8XF5xI%@N`??$$y^%x%Hl`qkNT0nh5He+S*amd%gSjS z+gmx}PyES{2?p7MNG1x66O+v66cNUm&+DvYVu%*Ql6x}E+g9|={ptA~C9fO2`s%^g zRqd?mEUKEc@}1u>IA|O+Uz18XEPuajzCJC{Wt6?|_KUZwQS+-$QvhC4b-EX+&W+M# z^IKoC&N0qh^gTMuIeS)1Ciw8vC}xFg8D}oE_V$JZyq>*u^^VBxk|18RLUOIIm!RnF(cX35ZTH(v*5ulc_t8-DfSg$4qS7sm~%vzVL`>lpQD0+ z>WCMMQbhomgs#9@M_@+f*<9?E%NGn=zhvZUo9)0yH1D}Z(;qet3Fmgc-7CoGIaZbD* z(z2n-9d>^+V-FOLwaU`VKfp;%ObxON`Z ziSHw9bN&zDeIRuAi-+e*gqoA@`bNBV<&WL9y7GsyXXV!jPka0y2!+e$3X(g&dii3S z+fZ*L)_cPzANWv)*HQZ8oy#j~?gwA=s0ZI_;YZhkNLW%`Hh%WfJVEN%8$;^gzV+jW z?-%?qBzq!5vR)Yy%rGRFVJH@6y7YH+5x!qaMF?Kc?D+t^F0E%huenOZs*8J#l_DOF zccrhXScH*=1)oIxKcrqn!fAE6O;xX4{-1{vP7)Px&YhE5vW3K2OZ*#EeViEzd7Mxf zL!ht}8ZVW9KvmoW?#~|auVmE-&bWAb9Td67`VnG5-H-?12 zF(lN-P%Qq2>_t3EGIG%O5qDyl|0T|+6SS#z?t~vmKPA&F7JSji)%}C5)L_57SaUge#frE{yP%Q80QI2 zLhAD2W>ukOif9!ijJ+$*&Z}>mEyk4D;!)rIGT|~fpXja$vul2KIB1D(U%vRv+($dk zzF6lmN)AB&bJmHV`XQvnn)qLEA~-;^%@X{9AdGUGtV4!m9Wu1qI^U0DQ&#(1bCR&f#ICJ+wlPD$MvtG)>3WItw8&MQ}8gzGeL zu6@*L2=D@K6Ut#oD2Jiwl=Di~8evMBT013iq+Jc^6v8530#!$}m=KMe?8+ll8=~Xh zung_x6B(&-64b?2ijP>_2sAbAtUp4L2a==xm8(GVFlEM&Iv+=aXo~B22u(30G{sPK zn)=^di-c)zejPN|m6Kdq3*~T^+d+5%M&_tWvO4L-QJEw;PV$SVIEhgVzQ#2I?D`~h zGLm{)uOv^y$%uKBoQzn$c_}>Yf2vl=x=%T39aT$Kr=hh}F1aO6Vp>^a@e*S@5f;l? zx_${o4ohvNaa)tanav}gbhvN*Cmp_DPC5+Xq%%X5#Spx%1G^=+31?$SI2%K;I2(CI z|1YRz!jy=tMr+jQI%O~&Kpd&6$*My7s+CRdjhEzN7dKIV=8)xeeG}R}-)T!^LpF^? z%XI;5F88gU#`u1rF@`{6*gY8v-aWZZXpAADF@|E%*#Ez3oveRHh50YOswb;5!__LE zWW-5~s~0~}6Ba$PuJL-Zmp7BgfR!za;`*+%Y4ZQe3Mda#gpbrK0ZpFP(CHw)#}!S4 zCK(c%WGEI*{%@;^!c=$m<=}u(VgN%NHC83TSFNo=N_CtRxe`Z_l+sc^6-rS*viD-i z!Oiw;c*{NOV&E(Sz&~A92K~l<$83%n7&{>;8D4R(Mx|01K8B^4^iFpL}cHCi!aPwG(U3w z=GS`E_bodmCH_;8ww{W5%&Snndc^h?viUz&*Wp&ZsuMGzM0LH zw+wc44i0v941SHUefGx?;|?x=&l2Mf&#XNCrq={p8(*`$@{yJuT_q)5J6c+H;@_Pu zEv>CB^q+diapvi|CLP5scG#HRWMh`Ij78Rnao_qe%l8XUXGo-QhGcy+B)DWqaLG_~ zTp|aAR8v7@8}d&%Ym`aehleTBL&im}OvgL{S@W0{kUf8mv=E48ix}UiwOP?z6yvB^ z_x^afKQ8V$dFATtS5?0A>6lq3gP>OLKp&t941ULgq%)+HP3BA zCkzRlFti$-@F>s;GO#-7$)i>QuHIL+SSR)FPZ@{{>pYmL_2ZWrdKU) z_c)#LAuo#0`X-8Z6g$o<>EQ<1fj!cMw=g6$!;sJnL$PQEk|K|KxvJbTmkFFJN7g|z zNmcH;n$DhHD?fDAs$3t z5V!^8JBCCut9h6Ilc2_6}Wg-5Jl z9`(|ytL$lXM_b&nEA4$JY^m?u zXYM?>voh%1zkPWnYOy`_=mh&D&e7hzmCpUOl>cobMQ8kwC;=K#j;w8s8d>Y7@f`K) zC)sTEntS9Gd2W@g^fo2jzF9OsA^ZM3iP`IjTj z;k_bnoS{1xGz1;~T+j{}b5-RHBjTs4vmlwYWzdr=eLn8B?VjY(W(DD*Y-Vz2Pn>A} z(#TxSpRbhXxjikHrTta&PmGgxs%#jRO*vyZnxX(@nkBs*P;l-{mfC^5A^4? zlo524G8Y~tTRbXWpmrEXTZ~4{5#*;kID#Qw%8>C)83M(o3>k&f49BK}ze+2rU4SQV zB6`?F_#V+clKl%STt*|8;~}CL&Q!32?%6^2?9=`G2%6T=G(kr-bQCi}_a3vj`6=Cg zirPVur|4;?qGyW<=GkGpt`Lu%)zhxTikrG~+)jgf6De#~VI+T>JET58lIv?7Yib^A zDO8t(hE{%@>gy@>7P%6$v$GmnTD@&u#yRu9Rmvl!#l@wi#Yu(!c$my}6~#x6ly0c# zt@rurd)4;O(w^`yKTD-3es5mB-|bFIO>reRw5a^XDRaeFRpl$JGElQ>j_kBYEIR9? zo%`!VVaVLdR@#B6R$4!eWgBO_6ei=D!UT#%VfFeQ_4Zy(zl-qPV&S<<_d?3((-3T~ z!7=$Uxk*qoPJG)zv$4e-qcTWl#=J2SCl@eh&t2y^Kd0L5^_@ube#DlUut!g*Qkr?> z@*APANud+LNEAJ}U-!j3^YSd7d4Xcjyo{=+U$a-gQSx<3)E?E3ruEfC>x=WvaHeBq zWtF&4v56xeAb$}wI$Jb^oqb$GnwjmsZ~L{`82cTps=-ODS# zZCm$-x~qnG9KKdnJ_sldAI*>2-U2 zz5-WbUUuhF=YpDe)rIubTe32}sf9(pl)e6ua!+x3hWiUd81c}=Z~7OXZOL#MMovyX zRo%`?OrFoX{IhNC)njEBvf6V}(u|a}OY4Wc$og4se9EE~^1lF|*k{qmDCJ0;v2^N( zX|9-09FD;!q%U3?k?~9;0>!2g8O3};An=I^i!wO6cP)HEp22)VAjk*E#ZpE&FP6m!{R=(xCcJ zC*8~v-P98%NP1MqX@5a}Nv;WUaLqMAH$^lB}zhuhW&aJ;+GC-2zg0R zMU^v;l+qp3bO)+kAS>EYx<=)zKvpy^r$-f$gQB^7tf`BV9zIwMb<2)Lk8n*kC-<4} zNy*6R*tB`W!b17x%o#j(vDRpyOYvV=;*od zk^aTsw4}QXm6@9P$h>;}s(V_!MOZ7>ecL{p++y!r`)F2XDe`8F=nGkF_t4Cx5U1J` zReq7ac=?iyXTBs*Y`!F;c<&M@(%uE@J?F3xS*2h9dRQVTL$CcUsIj{xs3kZ_Vdb>VxG}=VOD< zS02yi7s2DVzubS~gui_3$PwfHEEt_!G=D@+zkYuiWi*HH;T-uM{;B3+3s$xp)F~*W z*-j>|R%p>!GFoUIvUZp1OVBk}9D>e4Mj>LR%9?TXv&Sd0!%Kf8jw5~XavT}Y97mw& z9EY(l`jJWfTM!EijWMbxF`ZBykU&!NQ0Ks^N-KtsSVm7=%taq*QB<#>%P6XBDNetT znSO&OJwMG?n4i46aIl7Co0R`PcI}C)4fAWUSq$qexgtUJwjH|~Dk{sjlwZhd%T7*J zsp*$hjrh|NQ&ZFCRn_t1<|h-4Z?3M={98J{UVLm}e{wSG$EIC3TKr}^t-0rk)1dBW zH&HDE$%sSXb6b5WLhk>2c77pnfU; zYN;s%@5KL0-h0Pac2)P{_nfP%uB)!Au2C;D>V1l4G<`B*743Ok%(=_xOFkXWg}L(Je=||H$w6 zvp@RG+2xeG*V=2Zz1DZFt#v!mW3MUcp39@&k^waW%b9DE&L9M==V~^#f4sUNKfkr= zR|h||zq;C=Ra7x_<@{WW^M1Rcsye$M=yB&8c4`MhLpf{eYOC_DbW8*T<%Pk9?BcGz z;o2+Zbxn84hM03*ZJ;}`4j*wd9`oGaahJ+7zVVdniMDyAvi27$YbiaIwHK*8oc3J7*)eA@KoJZ`s%G%ugmt#SAh4V>k#>+bJ*|N6M zGJof)+M3*%;@XNLzrUrl#-G>J(i%KhUf*N~WhJ;z}%j;9lJWR}jTeWV|)n$vaI+^;#b zn6pIRJO-{7`tXI(v%N(Z7wwOE)Z9g%5{!n>WwX1I62~k# zt*4Uav?itq`K&QA%xTSicOI^JRvPy{L0n5tYrQ)em9)((m9)Q5NlWReq`gR`_29Z3 zcfH{0Vr$)Bz^|2)Mq+nrY4cadZ^?|-#4XvrGl8q&*WQ+OIX^wEBD&FQKk$J+yKr|w z?xjmPg?C@D9?h%((WiUk+rLRYIN+O&VB^}sv%}!P4KC%#ff50?Hf01H&q0%@vL=j# z-yMl;&@3DG3hf^E6{B2?QL8Y0xvOu&c-5eV$eDW6QjZpT*IUs-q|91et1jJXdWol9 z->kbXYTH^z4N0V9Y@XIwue+SEMmebWtc%$pxmlX3Hd$L?G?AXg^b95 zn_tmZ`PJF%z_zl=?4pvwRjqBsHJt^kcDD5Ne!_asD^H((_eZUv`LKLxU_JiENEJ||FESQyAHttcpGCS>c?OLv8T`TeEG!#CaJJoHoi`QIG= zsm(+2vOu#F{s*A5w!?Hm-xC9PF$m-Jdxc_Y~U170@-GgW6ox`|MYtKan%bh9o)F#vBg|7OX<#g4S zM7s8w=M!VN#--~{&~GE?N?Y+Z(@rl-A6oXHg&OBhtYUH+-eJ_x)^!f8V%6e#rTWHs zJmrijoxxkg<9goI#o92^%}@loMO^qGwl^PsxmR|$(KOz>D$n)f=QLH{CXW31)0?T?qow7+ zgfyM845q$*mo=lV{v3_Q>1=JuPP>|XBRFY&ZhcPf$=TWYFWr6eq}6t}b22ZqwxK7R zUjCl`etP+DHeUYPngGJ+Jghh2Tk1kbj~3Jfr}pge&p4qkEj=D^imhkDU-)~t`U73? zEE!LK_VBTvSJc;6RMgoG)FZeiN$$>eti;qJh|{AM!Tfr;SZDiE$}Vm5!g<qjRjLu>jbmof)^n^I7w7Pe(+<6d|9X%%up#Wi20 z>Bl{8y(y6rMCmkL#~-evx*d^|`fTcR+f8XZ-X!sEy6+_-EOy^Zga*DH6dZ7`M8_j- z^oi^E+i;g4eehdxy$jz!e;(z^46d2OixzhIeLSUouluwaw985r-4UCtokk&y!Z2f9 zdC}Zv;>&ZBG%lxkLD8CES!GsHNkL<4d+A{Hs$H$n5jTC|3)a>@FA9x}4pc<20n^)e zHqG0ChpqN|J7k{QFZ*+9jRQ-c&bKV9ysj=MP*9j>XSYUl#zRZt{~WyV^Ugxc&a&h1 z0Z(3Zmi%vU)<3cIhXH5A`U>Z4b_{Q<1`YPX%P?z=gF9#e-Rg43e&5!V+@WomxI_C1 zcW5a!ci`Qif@=P>g334W?8jbHk{z4)L82bI*qt^rv5KE>E3U+=HwoI)^Rm%AhbN!y z$NR+ZA{-*zB9>Blw^~YRL(}tZ#5XA3I&a*PArWJ&T3Sx~`EX<*NX|0WnK^4y_|nHe zZVmo%QSCu>{tk?Bft=lLY~hQ4rG9dqHG+Le-Tv@H|gXg}c_Ev4ogTDi0r@zugXLNU=e zcrNplNqp!cY8MmtJHrU5N+O9YPYD-S%3^f4H!`r?a^*RAu{1O9w9u4Gb!q`S%AivzhZI=T@t$*V?euGjRS{2r0|9?5g65 z+CZ>0D{HXNKODnq-#Wd&G@@4=^D_tID8}U+G+LfgLY-_CMzafg+A5dNc$Q=qMk@=o z4W_mMr8ZM)Lm%RbI^6MX!xb_5jNTC3pW5i?-`D3dQj4)ts+rP{uWbj=Ch>71RT!*C%j&9@q1@p2sygNa%kJdqI8HS-g|kKhTEu zi|Bh1{E_NR@y?EMVwiKX6X62HE~`5)-SVd94sMj~x^L^_?Gc=xIPfzF-H_bEu}YUetFl!_~I{Vs~> zv9)KP8xUYqL5_Vr)AIM~CzJQ;7TZC?1CUbl)(p6ZBTX-AEUu6m3{o_6V`?&KK5Skx>En8U$sOQyoLzeX<<)S`MDF;rVEqyTVj|=^l0W& z>;jFrw_dcEwUaViP*2BKjC#^L1ofmP?rdmJuDUJ}t3F(Za2*0=Yd{l08hJ-O=^e>2 z2vO9NSWMU8P28dPab?#O_9jO$7Z-e2 zti9m5V;Fa?DY@W7$rqChpP+4-{}R#pxbG6~ zy5v!>S}ws-K%!yiYWX>W0kP zR`_Rw=YG;x=nvS{!S4KESs<&gcVbn|*|YTxTaF&}Z;lGL@F&kW|5{sLUyDEP3n}a7 z{11ZnIwIQrDc2HBZKVohoda&Ha@S3wqpC2TwHVJ@Toe7Y3fI)l=1i|S@I|w`da%6> z?Tnr5H|_ms7nEEl+Qc59Z=gLuv^3GwfrCMxQM^kmh1~aRU+(*9El`boi)mr}7$w?n z+)F=6tai>jVzqPmWy!VkI&cx~(ow{eSeS_d&qmZvzg3w8FO|+x7^`4e5y(_=OJ76L z1EKqa`9MsCDsv7F?j>LFI3%Ol??yckzJWrEc0f z7J*BZ&CNMq%(Ab0a6?5cfj7Q!WIIt)V(*iDJ?&T#_9A0X5hN35rC6HxrLi!MPtb;DQ4fccM&kp>vO=)UUNI)B2?S zWPQ?7y7j5sytkWQ0xAm4H70w|v=5?v9VjfgIeoU`=41s??S`w3$PdO2YG3C1+T+T$ z-Dp3AXE8e9xM^3-*_*Z;1=uA8SH*Ay&qYqVs@V0R$(Hv<;8jlnUbQa?yz19QS~R){ ztIW2=KP^L8xd5zo7uS}@0<6veZfAcyW=;9@IoBs3d3S=apD<5r2;4!GRT0L>2OmL^ z%N;({*cdq*|5Dr46Onz8wz=-u%FbTqxu8X^`3lYbg`h#cI|oCiE`+)o_ugVWnFxeF z(?%a=ncG&0wo1IU0sj(_)rfx^(YMv~B@UslB-Uf4Urmoy2rc405Z|_}O@g+P-==6Q zDJj~D76yIJ6!-7(u&TJ7c?KYYyEFeQ;H&;D%i2PGRgHbq15S4OMMC7kL=;@*FYvGq z#Lj*CdnCV3am3&FW6+kKMnPgtB|&0oU2-IrwkF5;6uO*3j8BzIxpGjd9B-rcp&Ca! zMpgO|+e43|l(?UvU0Buu!E+Deex3!$9kFNT zJdDmt&{_Q$MZrpO{VjK&r~6u&YtZ8H%qEO@o9RnC9kn&tMF=J3DWqgIT9#9f`B3#; z$x&Lg`D+i_{JF;#yGUxxR=U+YPIGf%TNeW_3*Y&QtegE_CZF>!4?PqM+xp0gCZLPn zqW?znG~OpV9Fu8|!ebvuqmIVp%{tu66xo48MHqM!b{AM`_pC z&Yh-RQ9<~PSRrKf_2Wsh`a+sUV^xB7YfGQ4fJv{DlZ&fg{qbaM8hp0Yofc?R!zWa$F|XPxyI z;m@9No@}kHMOb|ZG&~f+Ew^D`H0I)8-5d!R|6I_mJB7YgZQ3Yby=24DXHoB}Gk4cT zW}wbqYThl^@rPbrrdJoH)|1e@oBQd-51iUK` zkcv8DEzk@`>InWE^KtZRg*B5+R^I)=&{S(#RiLP3@M2fp>VkpUo}PiPS-<0S*$V(7 z-*wkr_N_Mxv$L$rOFt__7SoFQy6n>OKvqR%NtK%f=QozZ-&t}#WdG`|;pg6ctp6DF znkWqhK!f#`A8Q}6+N1dPT==$AMU7OOHm_9BX9*Rwl#UAR<{j;k5m!0dV_L+Ms!yZ; ztIxC%uQ6guBcSAvI~QeT1a=uT)cHG#Yni`M{WdL?6qQW+NWi>6C^OK?CDUtS5*KBn zSV@FdVaH@HBIf^4BzI98)`A%~;){qOYX7-FM@ZJL<+ikH)8>_G`YfTEmeNtJ%e+J9 z4t-VXpTsxfdg?kgtZR_;`ov8U3U5UV{q@^S3p42NG$rB(cbU>IuX8FXgpzg+ASk^~ zv`xwL8y)vJ^PWqQ-Y7a7g|1iqj7M&RR9WkLDl!`f@vAu-2UE&KZSzW3?XR;@o}7-Z zoQ=|pI%$_FalPbxls27@QquV-CC07OX)Q6BspnnQ>N?lf}d8zlf9Se@PK}`_l8iq%!h%mMY&BeuEW&cnnv~|J~z+ zDZBGc;;!0Yojq&SfiCpD39{rwN@PhjY~6yo@Jbi$FLcpTI=ZYj?^q29Czc_iPE;GA z4^6&-y3}g4s2zY<645#KW7g59Pd}OTr8kIc+)1=B1I4^)A-?sLDV;*;v?-nTJRet_ zol4_$Gp>hUSxJ7XuXvoiV=Kr`Wna_f6}Y5B@O}KcJDHn8 z|K4g!Tk)o&;JqF0YOI#11E!r`kU3K#nw6ZWXaXWznf>IN?~>_r34O@fm%y#D-jK8_ z__7>Uu`Cu*wA1IYN-KG;$7iwnlFMno%$&q3lR^-_D=vkV{o8MK8eRoy<($o!#>$mr zlE;ec%X%Lz9kd-#PUli{O}V~kn^#WM{=$h`O2>&E=KURzV_hz95ckFiVaCMhGid1~ zKSV85+CmG}r0GXnI5;)(o7Q@jOmQ$*uc|?7G}o1N&6`MZj=QO@?B7#iL7h(H0Y_kA zWE|%>eyb0^BLJI#FS7f+=F2msJd9M1J5m9RRDpX%TVv3@VgznAW&~*#9}(DPoe{q)>FTt> z^rHNjG9}lR$R!?|A)MsY%!OW!iD_qbtX}Rv=HxC|pL3?|EzWe%`a<~i={Hg?<=!*@ z-oDE>T7ve6zE4Hrz|yyq>Iru&mAuIrz57_*G3W=}M@gPC(Z>(E*i&lcv=MK{@6ElA zKa4f4yPzpbq$~AtiDL3Pue86+D=np;SK6xsZ`^O*7)1(q;cMt&+K=y)9TpIW;3C15 zGi#L~DwMJl<{4ZMsKd)|pbk$C5FH-TbGTNo6E%40r5e1Hh-BV?euCQZxc6G_$d*(x zqp`ZYY|7G#=#wdPm|-vdS~rW?D>E=b_(w@|n0+$B8&0>I#VioRA3fOH9E5*q2j=%q z{CawHcVYxmamY^J7I)@*jqqN49Xs_%BCmeD4 zSLb^-zFTe4YtSnD>n*sF^V}xzRPxA_c@B4d+f9l1QgV!Xv&k`nyP;=Fzhoco*>6g2 zP7CxCoT*2S$plx95%lFQTsbY@SW|P>MEG`~9r`{}RJ%{%%95)p&y^x?-dAX6;+-2$ z3s`yN+)vjef|YIMpz!&xd>%+;Vi^wM9C_xCZo_=s1w_C}>k@cq55|z=xCdjBiih?@ zGT?gUA?+_bq@~n6L}{fhY;`*gm|EUVZY|0bEndJY;&&*Lm2K7~RKs z8rl7L<+0?jWrG#uUN&ArdEm5%?|c%dMdVfZ!r6lWD|0=QoQrMH@OSynTdm+U%J+5n z+k}xx#c7)&wkNNgru~J}w3Lq1Ivnm#8gjyLpG;C-j~j=tpmypyNGqNz%0otP#f<{*;*+)5@hQN%Aq;K9@(vl4oVi z$T#7qmgi%P%BG2wnHg0lVopZtMEfDF7*|2eICY{!7`IeBbZCV-k@goJ(o%XJ(q81D z8OQU%oHPA~mqgduah-Y5IFAG+EgALX3y3%&A09!U zBe*6X9>eu9eCMqB&RLXBn9>Q)dm9>0qS`Z{^AWwN9T7U~EEn;`=3z~KlhN36yN7&@ z^h;z~3d8@NHeaJ%n5b(@&c?m8s91M_uQ+Zc7!@DzDuM*|ftI$rR+M0zWseiUNCwyw zqbl5Y4Z9}2L(t1wN{?RFUf$5lg1;HW+m~aPr_K9`*Yc9FQQu8nYOA@MR+VY|F6Ay_ zm^D6-C?6RWu7K<%9!B9!;k9e9Y-%rZ8<9V94{d?m70zA9AFgd&FW`Cse78b0bCmhq zj1)=CyWmiA9Z&5@pV9H#9` z`eT@PP1^S2H&b58{!Qf7Ve~qTUPn!@qbMCSC34riDb0iH=iGU^8($<5LFCX&c#3CR z-ttv71++O<(U0|wGgdwA+WPAm58RgzH!{>gAsGwMAb4b_SJq~gcPd@Im zP?LjkBa&sksU=p6h{0>X_i4{E)K$2nkdOZP=-*=6TF@49+ltUuglC2@(j~Yq!L^{; zulbrxf8vyw-$1^B{`D607n(ipE5o(!&-zWTe%v!;O3bM=VoJ<5H*QLl9}}j;bDV9^ zjnRi#G0YL|FOYWj=kIr#aAf5+#%b5{=jv$qgSS(-RIEoG@x9dInsMEXyH1+BPJ(8wF3s4k z78qiB<*A9f0#|OY8iG7QH3TV9LrByLq=goigXX;lQ95i&l;qS5q^D{IQWDKTq;@ot zATgnQ@>l}Ts(?QdOpq!6>gPOg!y{)IOyDK^>UFQYa#_-^MtsBk5`qO{?Y3!G;ZtL$ws-wTm6ac|ii-Oyelh&6lOg1CDX??h(RsijsLh6S1{TxH>l1*L9$# zWYt`kGOK1a{G*ap(8ROb-a+r|q$y3}`)H3)i`bNDp&XbtC3<6lyNP@! zd2|GFWv45NdT_7yl$^by;-Jc%}8>SXF)pE2)X#3ilk z(oe1HQi_fENh_hF0UpU?eqt2uw8XdVj5(BF>2YrVDs2j7>j&y-mHDlB9-et{%<2a> z&=*DP^)8HBsy*DU2qMxeFKB<^1udoL1?@$j94+OdFAKJZXj5&c*1Xn~{e@q&l#XB8%{!>YcV5RI{%r@HRhw^z zOqX0!YRM#`y$3zHehixXHQOlldVMo@Uz8&1$(uASltAlEi8;JCn9>HX7D+2UTxbQL z=Vf`AX=cobojDN=6iUQh#$YdeVMqgFFC+qJJV^wQ)-8_!lFaAT7+unQIqpJYalGR$ zqH#dPT}UYt?m~KH!d*x&#a&2=xC@V2no}F^5;HZg_Mn-YOwEsbw8-iHOyhxonZbG5 zT-8ZA?xuYhFNwB^+JbX17vw}~wFOUuyVd4F%VrRi3*zo-b9Zt&%9Fj*QTkK=CLN`e ziH_2XbnL^I34Vq$U+<^PCxS-$DJ7*uj~0K=R{Wl=ah6)i=3ELh2=XrxaVu9T5w{VO zENyJjjLsfNdT)F>=Z|FEQAt!n_?AdM=R=4I+VAeCsDm>is1(#)hu=l1L>zglRa$jh zuToe0zc3wK(Q0ZjiPy-v;)+HtEAB?ngPCSi>*L&M=@;#U4B75#=G4&zt=oksiv8Z> zI;=>?Mp#@Vjwn`7PfYQUY#lbyCM}2`S~#DZziRTp;J|^&Rn{G@a`tNH%hveQeH|VB z{T&^B@n+BR+M4(<6fC~4YC#ZDQDbS(R98hs*OdK`8aj8MalYk72vt{O{`!4qpMRBq z0X#rk)u`{wpg;4NiOxQhQfF_1ol5jsFOm7$mmZ%cjBO1lR09gto2SG_=1VkJ2YS)U z-f4PuqO``8qWQcBOx*yeNrVIF7QwqCkgK#Jbzp1+>^?lo;Mi~Hmvt`7%-vD2YNolT z_X+E5uR4zZtgbult0#`~<>F7LVgSGhMH^uN;G z^G5ThQ$nqCqe^JIqn3~hdtQ%guUu}yXfkbHMq8h=e6+PCezb{6(iY9d&2iQ`B9kUS zwO-JJ7Vuni%{V^oMcd_|DMc-7L@m+h#(lK*os7|5(#1_mpjND}lvMiL{IZsc#Qf=? z(l$`(6F9h_(Z2M+d+xq_|Ni~f%kQ>t`x!}fe(C81N|hjaIw@tnVJZCWCFfCp*1h4M ze|Wz2JBc?;U1xle zV0bp+dXq-Uy3BiCw=2{<1;S_^99m>%XK~% zJ9t41B%6=g=7qZ2cR6*nC6T(_=G{6Ui4BaRfQjdnQKy|rpF%s+KD0;_tjtr5h}~v- z(ay*WCGy*NhW##g_2cQ4T>T_FiL}PrD$>o_v%PFyS2>={k89M`fE!f{a2fJQ-9?g z71SOh3gnvxP|pmKiWnX?Eu6g*rZfTi3gUs;LW$?2KC4f0cahO`5{IxQKgl8*3Kpx@ zWTd7&8~zDn!v5a*Uxt7;J@2DDzGdmTRPy+(OE;dM|IVKW?KeLd{?HFju9<&J_`UXg zWWI_`sU808i-_|X2E8s}Bxo(qMYKxlGY_=Q3%#`Oa(Zb?BE9;|yO}RUP~AI09o0m) znf7h?TJALVTo+tv;+Y5ZUg=v-qVFa2)wmo=cDd$x#oB8Tzx}i+oyPmmy7QT57+-Md zec7~L_9&%a$hinHwx*1X@q-nfjj-OZkC)YaWM!u#*k6cUA;4$x=OawRmW>RKzN^+9 z;5N!w(Tz8!(T%mu3%6Rc(&dWZR7I1w(E#Sw{M^+HwY5F;}oqo=fro<@6 zMN?YDy^J&?w_fvIHuaZLzXsoR8QTs7+6S-ov0bBjw1Sa!t&;_8P^nVb&J;HRIq=L8}ab zgNRmvH6i0!@9$@!VpU!k!f4w zBGa^#J~FKu;}UNf9fXBPBHXw)i_fp4$cYZqhr0?Q8CHWTlqY?rMWfIpIuMpG^b)(7 z_&)S{HR{*nZn0bIyQx_-`;2@E{o&K5M2tr*?o$1gPuPwpYzI99DI(QGD;-C$vq^Iv zljvjFZsS7uKNqa8I=%LBr#EPQJ$!3^X|;j6a;gF?rB`VwiJAwGj{*chNJg8 zeb(Q&`$#!gqZ7aN0K7eO7Gsl$?cjQn3tGiTtu+H1y4lq|n?Wnd#iOW~QjAC`#;wZq zVH{yI#;Oi2M2$6?mPYsKQRGXvY2kkGh$%($pbEW#jK=fC+9pv+g7N1bK_ZZ31)(mf zUrNmRaoi;olXmpTN^% zQQ7JFAQrqBfAU7GJ}dETIDZEghO}&v>iiAsoGT2T;VB&V-fiFMg;l~oN`453{X~R^ zoNgY+@n)BkV$b2|#10-7TlYML+=RD*4yt{u z0Ty+;%dtefFkh>bnB9pMAj$PR2&xgE$Ms!yF2qM`EE^+^CR}Y}9r`i$ecC*Svf(K1 z5?{M;mtK<})XTch+#!f7{SIm(hfEt|B*T^c$oC$E7?2Kvm=gyeVQO#GPl;|hWdx&H?iD#=sqMoAHiETEn`4f8L+4u#tDs9k=ZT}oa|9wHYNddp(uyt8Dc^F0h( z@`MjhZ0Wo%{V5;zC*oK$$vGd$bMCv@wF4|+-9m@pGEyy+2>~N>2kxyZAL50&Q|vSn6*3Olco@?|>^UR08e;mDhmEv<@($Ty!_a z!inytc|F#dXK=0EVoHpcr$=E2onCNQUQ-szT1t7R-^_Tr zlcq#Vz`QBV;~kWRvg*n#IdlDS-Lh;l(hQSaAh>;}h*ja1g@s10hP>BFq6yYU5TbJ}5A z$dQ9+*@tiAE@1)J;;WZ>z2?63DEb`5_a8HN6J5_7QSxg}pfqPnjJzAhU1DPueN$y` z1L}n*Wt4PPUSV`z`fW<0+;s6E8BQEY%fC@snfcU_`&TR-aeu3Qmdi+OSuP{Bg);IS=8L@L95_xiDwUDvK+okel9^cIW#n4( z4BAMyn^N@b$(`Ua>W1@pqO9$*JJD;(Ly?V)*V8W|SI(M}L>p@x^WIS&sy@KIxXQ-8 z_`*xBv?qVxbY0f+@(9u>J$o&el9@yJTjIXsN!^UM6@ye?oE$TYh9V)j2Ekm!E z>>aR9M^7lJQ-SH8QS!$%)z#HVv*1Zv3_sn^JRWhOe9==%>@UR1&hRJaoqyvwC1WB( z1;Z9_kzw@X=Yc=Dn+SjoS=eDnB%DO^X=!;hU%Tnq4vxxm=}-t76yix0_?I%Y68{qA zRBQUyqLygUCbTdrti`mnpe2YFm660;$d_>K=1!&;_YiZzUUDs%3+bhp3n`_-Tu3Wp z7Z~L?<$g7z{D{(Hlpj(+nJ7QupyXb_W#UN!{Z1^x&v#E+OolO|GE{zXF*edESiBGB4t@-DdHmfc5xw67{z}Nz~soY{U|WHx0UJ)SuQZkNWF2 z{po*~49FVkC%DrnhN;o?r8J_Kz7;fU1)V!g3$3YTF%+a9SH4I6xP!QdmJ#;SYd&iP z^^AxaHFu2Siv*9M9$iM4UgXN;F-@9S~R^DF=EXw*XLlI z+AvOScuK!%Pj;q|zQN0xLfV(ON!r8|nZaz7@}2Q#3eoDREnFW@;2zax`eUy7ELlZp zyV5%j;nzrxD6R#^-QUHXp{^D@cj%nV>?yyy!+Wvk4kgZeuV)XX@ux)<6VIm){mn|5 zDenBC<9@~s@@&UFz5{L!ZjLn>nyysYTcIY&E5U&UH3~| z;UA8lsLn1eDsHs@;@w1MtZ+FM;MjLR)&N0e`hAJ6&llero%?rJ? z?{a!;OCr6;&AaJ|*Y*6csbyBI9Ia-13;My|do=05{i`_OL7mm6fb9zpSF|Gm3p<;JuLd~$=l+^z+{@_xwWeh)TDTUh zLkrg!_R?!UOICh*!1aqZ;)|%=5x4OKWCX7Q=&5^^V$@0&ChCEQ(GG24WXc{MYP1!= z9(NE%3S8K-l_B;ZjDszkPE1V9ZE9)RG&eDEVpGd&ylD{6`_>N*tzSPhxW2r17h_I$ z_4e-Ozq{=>ds+hu-|5PNC+)^?TkqgtZ|}f>i}j42L3a>TAB5IOKaik#4y8f!Xqy+A zpnaFi1Z_!_30+v*1Xt&CEqV94(5>QJ}4dJ<5^v=hUr8bYwoO&Ut1B9X?5{qJQL2dBjl5g3H)@IN z6fG1-@ih9K`Gi?q(~iM2UgdlBjMr!kO?vx8`e4>X-jP%7(we_Koona(LYYX8w)19+ zcr3&5cEhi8HoQiCs$m>(7s0P;Jb}d0tpi6|ReV5B1ZAp|t9at?y z3UH^|1xivDb%3g3nTTSLqdwO@w2C#2XfC~{%MM20GgjgU1xtrL8LrBuO|ZZ)G7R$D?tuiIFAC@m@R+ zm3S|ShTWPZ8dmF)MZ+e?dP%ftdaRf9Am_$9)=Nr?^^#H|)@wc9 zFKD3*=jC~JI?AbeNKLM%=A{)C(G96NIq%wv4dM~~QsZSg1E68Lng(%R5;40uX~e8V zAZo-cwY|LS$EvUyY@Y2)qN$@i+u zbWt~$HhRupnhk1{_|A{wPulyK7lkt>Y;4(Cd(`506F*}$V~*2z#mMIXB5>sVI?iXo z_vPTX=b)YT8_A_vj+%1x9x=Un!d8_l6~(p?wPtmjKHYc*?SXx`n;76h(?a_qSLzA0 zP>0!pYsD+DUau+HH=++?Xg8U=Ie&pojeIwA7i~2q%B}|7B{Nte9E6s%I_N$0R5QYe z*6b&sTky({yF_zcxJ@n`dO<7~b=?Y~EUvToQS z8Fx#akQDQQ#)4$lsCw>1wJy37%>s?+vB)uPC1%K4BY+pCd ziI8!f^8N3~sB$IZs7h2@{HRJ@@==wxmwHq?&6f}v-|miTCq{4$Mw3!^1FqNNn)`lU z%e-8{$R@GibXK;eALuWA(wdmw^kC>Wi?b^$hJqI-j@FmomvYFTzv4VUaOdW#(B#-c z(O`K+R_UqfuELUlJO0Nbuc5ggU z`j%g=s>sf1s9GwuE6RIIkGC8e2-fA~W#_G#@9H0TT|wPMC{*kB2Q2H`=ME>EH@ltl zT?_4(8mns8HqI2TuBs?1TUa$#7RWCwDa|eo1+x2lfBAp%1A#zAFj!=9ZUr#64o7G^ z!ZG@0Z*-SXAt!V zm0P5+yrBo*CQ^#g&{|7$z_2NC-%Mn?c-1CBYw9i=O*_}Y9j3GcrQN2)jKuWAF{2wX zefowY)MC6y!swcp-P+Otqg&PRkjn)~98Rp}1}iR72}yL*^Tw9^5$lPGg83sy7C(`j z*FRiU?awMJS$&{)px3_SIF|i*V|8^yLv?lIkIrpR#upo$->9xQe!RS9ddChc^jA4B z)K-)t1z=GrgB!wQ2c8a6XXfW zIicNr2|f0mE~gNW-h(S|6beMnMyhOX=@?Br_TdiuoYNe%z8ijOVDfF#(C@6Kd@TvwSwoi z3eldre4HA_=Pw@(Ubfac-(P*^pIZt8S$1(*MO`3R8OWahU+10sK&7l08g^s1v(u`K z%meDnq@rLpBs8t8YplbY#( zxs%=sB1%PODoSC4X=gOhIPR2{(<4>geADeIY3s&KxHB*nZJp1}S;OIb9)8$rd#I>( z+p16q!mqsT!sNW2zpF46dBe}nTCL6lPxqeseruuMPa@X`@~g74=gU9$7)}Nvjb|a} zI8XcFRo&89Bjiv3Sr7`!3`qmMAn@}6y2r8(a&TE~m+#{;R zhwGVq6S0}h3?j6aI?|dk5`v85YA10M+i(?&dS@;QeGcs%lX!#JmA%nFCwc6G0ra|| z3+3QcL?b z^CfMdw8Sq_N{ioL?73nI6uSZuZ~E=TjZT;nZGrUlsLi1b*SZ%bpUC%Gc`~gWf)J9~ zua+ie3DG``XIpDZ^u93?mlk~OLFCCU@E3h?pfae+Ea%%z`*xJ}ni8YA517&cjt=gX z%*LKH{E@M7SH)*WMedAa)k3k7xT^;>{^8g>=xO=Fna|A~w%)leH}ClV{l}b-z4yIV z<3mLUc2L7J18LLG5lRP1{)j`^sFDNGtm%C7o1FK}KY#GO+b7+#Sg7yJMeI4dFngbi@G7lg9NWnxyef6^ zV=HwpW^CmN$;X!3th93uQG!Wn%#11b9UCw&xMD@MS7M#CFR@O7ievi@^xc8JjPNDy z$r~-KI4irY0Ll2HSUR~|sTy`?Kq@*pw`>`DAoTiRL1lh*b!E<;(E2uLvbn!F_3DeS zwC}u_7f3}t=lISy>?kW=yWw@k10^|mc3#2NmJK!eS$TQ+3s%;#W6s}ZwIA4=lf!vK zzsQLQZ8sag2v4mbWv3D-OSvO;QMnT6!v0iqDCW6rj=r~DKY;H=Z>^dccC3Z zN(0a=JlR<f&eG%KamWQcRwZe5Q?>w-Ui4Qf#H8t!Uy%lzG(g5ycayog6oQ-a6D={9u0WtpE@g z75qj7LEN~v$Au6tHtz2wggBM8)mf~Y+OlO;ZC$80bgBRRKy6*kP_3ecJ2uz2aN#?< zw^zGx;mABu|J7#SKS$`2O0y$fM8}G!%gQynM7qcmlGBC$Luu~>U4|gRWVa?+vSqGF zyXyH;BEo9Q+&cvsDCfL+nLl(!NDu%f4h=D#9b=5fhKpmUsTro5-kk0rAaAz z(g=6=Qpb#!T+gI5lX-vD(gDA_KbDG!j~6QXm5SM&AZJ=_?d_rQrr)nE%FeE>c78Z? z?&QIyP_gYVsF-;5O@~XJciV$ib@}%=k6K5qit`(in9{8g=a0%(71v~SghHY0U8S|< z1-4z5U)Ye9-`vuiKVM!RtbW;CWF9I$V%Yb0|0U-k*DIM>T(4qhrDC_+pizi5bQ;5G@2afqTK^BHoFA{Mt6SAvQ^WZ& z1svQv5v#{@9oG8(2^1pkX%G_Chw@-#XF|-RmKd3pZ%X-)r-k5C##?KT4%BtIyjy&o zab4oYEW>pf?pTz5c4w zj)J^ke&FiyK(3uN(D%%hvq3BH)hi3ZD~IiD=iio`FWOIBeah~@T#3?w-@nQ7gA(*3 z%I<%}?EXm!EeR#G6iW%M%R~w7_u?thXTGWrqs|xviBTB>)u_KunD%H+bV1fhRE=5; zXgv`0E9R7UN{vTo6nmh72YUU4l)8uTM(0BxwfbM5k!XKMa)oDZaz6Vt{JHbzL}dQ# zK=jV9KsBC}PJFHpoQSI`@MLo4VZ7#`9nMvqCP-1?mD;NTD%O5 zT+{dN0)-jVEEE=R!-}XyDq(uLusZ|Ea|2yl-I?fZvi;Tjt?sQ84~E`Wl3P(Z7`!|> zUs#iWm-Sh1v+oy6&W2aPb~QS7HP~BTkz01t#xZyuA`{Zp9j0(T0cB$^R^pAmr$Aed z32pU0)QrW@R!c%#Ek$YDY5GUAF{^B(4NPTYv+382H>qrFhHPw&la0iys%+$S({<)H z5!t9~SHF3dW>{dPkbWEI4w4!6_PeyX;@clX8!ZWKv=pUH2XYun|4j2v`@Q&i zH)`I=d?J#mYd`3yb8U}l--BO8&F?TM%(%b(pps;rm_yARe(yQcmwA?W=77x0OK88u zovC*zii87n`wUgN_J%4N>WrZ%1yptg^L3$VqOUpcw=5r_v-MS1BGB2^V}lXs>?wiH zu2bl&wa?pBUa08l=_m!3HZ)ehOR==0<*``WXTM^wwDzmqCD)gYHTQ6Yht?ssf|*XP zSa)KUGag3P-7RtJu9k$8v=qxpT9?R4Jmp^7L$si zrZkVzX;V6l(nV9ci03nY{vw`uafN&uRix>hR32P*&Oicsx3e{9B}%6xO5Ew93G0b< z!P(i_6V?H8pp%mq8f@sv&MGM>?p)nl(LZc263hE1wRLs1p_+o~kaf~u8Bz9@b}du( zwn5puwa8>R4UAydiu726h4nOfXd0GBIXJvIDke`?9&*|>HF?8gaikiBzvO3#_ zm72Qw#Rz{+0Qvc2aONhA8FTUbP?j@qeJBM?NjOv6VmVXm5;-$bH`jjY`O*tF_L;AW zYJ{WUXG%L-+w@J*SX1($WK&p?)QW)!k18v8AhYuUdxtX>w7%fvEZDm|Nt%bDx?i2Q zPa2*5ScE>ikd^ben^pcGC`6394>dbtRv|43g|rk)A+1ZK5M_t9iR{o)dK#@vcJ!Hd z5NUeUl#XKNGeZURLd;WQ5s!jOgSciqTOa5-;)`kyR|h;#_!#-dJa3cfA+K1#?KUm zhKKqq1iD(YaohH$dHXeFj(dOKT6M2=yQnHfxmlOC$UOhS#Z%bS{qKu&!HXL)&;P0E z-1jOAEuKwKMsQP3QGTwSJ#Rm7_3y24_;u%(CGGcSY> zHM?TCM@zyzT8iZ!txLu|+9uqirI(I-h)hw$@-;*}>KkZ97%?U8W|^1tn9DB`fzFy} zBx^JiIFT-L2F@n%1hL%P&2t3lqVL!X{@m|Ak=%3;y*UFJw{-&7JfmO*`cHX!2()1- zx|N4LuvBo)S{J_U(MPQ{A1tcftsuFZfrtK0veeyM3NtcP__r(F{QW|gpJpTcG>(~e!gtDgCHRRs+xEHqbi%hUhM%+~{G_E=e$u*R{G@Hd zPg;8E_=#GIK9wi}$<~8k0;-BuBiAaCNNvTypEP%#1ZU9t!`vCWXjEvu5JoTvIH<4Hpk9`Vvo?02dg}gwnSIl*3cx;10Jh6{ckT{mU((o4yGefR}p zx#3zkWJ;P{BX-?mMs8X61i#4`9le`!YlkUC&w8Y!ngO>EuSx&0XxJ-~RI%$`EJEKb zdzL|5xFL@QAOpO&2f^jM_VLH9(N7h0?pM_J#i2#}Hdh(`Uj6F&;s^5c?p5&jp4yG8 z1pJ+Gb^K1->F-p>qrmO^T~7Mr`iV_@`kPx?H`M)_qQTF!jz-Yn@%(iZ*?_J>x-A&~ zT8QH>EeU^VDVD#qE*XDmoA8&GURwUrr;@)8B4>|q+reeJ)^w&wZ~vehJ-BSAKfd3Z3q@enKXs&r0Q37o_}x@67)T zvc1z2s~Oda$?G#Ea@VjaF;5;nirl+v|NW?w^8~~@LYttrF+1ljQ`!Z-61%+Mkj4Hh zQG>v%LkddV8m(BehSF9Q<-@2AOZctC)kdQHMoWP3o8+=s1n({4oy5hS!8K1Kh~_0p zi%*Z>lf5{2jN5=N(C#%k6VC4>fvt~ZuemSd_Tg!A;im=%ub+NLVSWsX{kPiBeYeI% zvF8=N$Y9nBT}dh_4pUzwA`Cl+14|dso?$GM0kpvaW1pBqYBk zs?0ZY3z^xY{Jd|`cFo`qIDZ<<=$>>M=fCfK-u@FBsBS!Y(;}TEv2+@Phi9u*3_3Aa zIjzG!)bz*55G@Ivv=mDxtxKd6?Nr((GDJ)1DYa5Nl|Gf((RA0h$-H@!S>+~79X-x+ z!WcDg^*Zz9JEG86L`Ce_A|U{(!1&!z01uSB>HhF9kjj1We$LMOorj7t8jauKyl=rd zW__IY;v3(Z8Z2^YITzXIAI51PXRXzsA_kOT52hlmRgsLmf9w?)Y3~y zOP&uWnlDeGrLS4FR?1|R<_o6R0_ez0A0o5G)pr-F@4g zwlz%Na1Py;7s$vQ&hDM}ZO_fCpJ=#8;}33YovxMmgP+aJI8SETuXQ=+Ycm@dg+PCT z@(wMI#46CIs)A#_38RfnEOd=%ZHrX#!qkW{*B;&)?^jt zlvjoFe^|fk;PIYNbylFrejABy9gjM}_b&4w?Sf@_wrqIA*5;mprsg{f*My47a;=jN*g zvegydXX(68pnNh!m~*9Jq@(J=l8dXlAI!~tPy#3xS`K#vYfEN3PGI)u=34eUT^7iQ z7@MygUbm^axuvsfv2}L1xuvqJ;x@^>esj;p5`UobWqq52ft>t;78r*WS2hz_FE+X7 z)lx@eE-ju5?L*D_m|3qS;RY?ma)Z`o;s)*a;<;hSd?U3=WO#{uF;V#vLq=+AB=ma7 zddYD}9gR5-SH=MeN!XRnu^3G+GbzclY2gGS3wQvlkiFn?Tv4pe*<8KCFszs)o#SEeU0{ z6iZpH%S2i2_u?r#V7`%F#dVUlhBmZ*sJb9OzqQJ7_CCC?8u`GAD*7&+ zpKEqLY8O;h=M=Pin)^SmT3ykZv!<@LDsQ1>s4%OnFxZe?+}_huajCq%$@;uI-Cg}q zd14Q22D5I~^dp8Vj>K_=mV_&`6w4J_m&g^=^|ej(LoKD}i-M3JQKme@L+fTSK8L`2Jda=&a)Tbq74b`X0>8M?SjlC6bru2x5a9OJRuTF z@~v!%wwM zicp>eGD&i>OoB(~(-E|k=4nx1A!Ul7rB=ox*>TCxS0F>KA`|)-v#hC(qrFa}eaS1l z{1wIaMav4{{Q6HDP%CxAGZB4YJuCs5`CQO$TjS7fS`r#-DVD}smq=qu2W=DSpr!Ow zUWs&|om-!(_@Zm@)oC4Vih@j`msh9>+ehRVGWwDh96?H&+;`r01&N_cswsGw-_Aq! z0cX_uyt652eFYF$d#}3yWb$A9k24*M4Mk^9+INYoBF?S@S|ayd4Q4D+dlH4YH4>dD zGgeDVO^IBLr>4{;QZsSJ>XXvb(%X#HXEDFAoRdrphq^*UM=%gOX+F6viUk}-Vu*Z)pw=S@6}tb z_~>2cS@cU$>z6hCn5jR8dis=(fdh`Mi~}@Gi@9$kPD^hwN*U{16R69}In0X<8WkYCguAsKKb8SaiS;t!Y)$Y>$ zzB%V-4Yf5$Dw~y6%{6>K;<;wsn1xATTe$b9ZH<{G3LqUNYeNBMo1CiY!{|^xWSh2Z zlsZi*8m&-*o;>lo%(RhHnoTKvyh4;yIzbbSTqwfzYCM;jFKO}9tY-t}sf>ahHYM_n z=09W(Q~fp2b>D~wg;>kySl8n zHW0|m_MhLK?MJlNb4yo(mSuly>3s0YUfXZ|;g|m^{LO#=H+xlh-;(p^w9CiSYMa&Y z|6^*YP9@kq^(#+-D@=st7&0Ba5NaZ#L9^X^r0JtE5n(GK?B1K4Kl>{F+WI0_dY+ZA(UXZ6n>gOi$+jVy=#yxU8`dE;+*Ygl&!>$S@zS69kWhD^8V#7!r?ouCg=P1 z>u%gL{}+!0T{<22-xHaiw^*Z*`N?<{&d>QY^HbV%eo86%{FFAGpHh0M=chbX=ckmG z&rhl6{M>AQo#r(Go&-Fh_Vg2`o!H^cXgPgd{0H-(^?8@aVj|08Y3_M_eIa3H-WKDT zruBpEdGE0b7-H5GdXl{m9= zEtAXR%(BY$%!X{N@rV8QM)+(e&{Su9w^;W@xNUoc+r*EROe)}<2bU9-+oY77+oVmo zO-e5{x5-m!uPp#)sBcDfGO1N0*(Pw3^xs5D0WP8x+-Pcv;@M?N)Z@3~nc}roEB=1m z#rU!#rr!~i7ENgpr8A~<2Biz8bOEKSrgRn0--PF1#S^c}e&B`iZaj|14-^N_4RJxX z^b3xb#vK^38mB6HT$DB=?CcBcf^#QNp8P~!XniE!Y<2$t- zT-Lda%ICYUTtGyczf1QPt{rzjYUJz za(YNM2-Q{^KsS{f)8>9^9(8C@oGH&(m*`a1?!uEPO}L{J3pR;O!NyWoWvQykcXx@whRJ_)Dfyno z|K5J?sk)%`o|uWd4W}JIVfoROd2ST{`pWU(m0g&*Z@l(7$N$yq*0ZulJm&7_`+#5q zuFpb+c+b;OwVK*rS@EzM!5##%sfhi=Glx05jV;f2^|Wb6EDmiz3$c@xh~Vu7+1unw+!thWCEvGuG6f z7S$f@ahYk&D-l*Wezb5!jCAAfS*ybNt$%Gl{oMwJMg+?`^WAj(WgmY(j$UzjY1Z)4 zHs2}V1?$!bFUekMIL%&3+mx4N7m}Qpr0s?ClH9*iULuZMzmm~d!d0>(+5lc40*SjL zl|tkMwN1@{YXo;L+{IWgeHJ6Y_m~nfOWZxtMjgA;(%#IOaK`jLgWj}~T)_J;ycoGv z?j^c#WsLXOoj*rt;e7au;JvYHg`Klap(@*7S~|JJ(89G?$5tf9e&D==A%>yF&hGhd ztzukQd2vNmB*ZW{yTgqwq)vLw|0c+@5#&0#)r~B?j4`6k!tz~?Ah<1*Y*VsP3YZdg zoorLe=DnaszDtcFjB*j$t4(_~O8urpjPxc`BDz@OL}iU*yo`PUaW@O5M6Bv5_YLBM zV$_TFJdQ8egZGjzj^j%t;!5^9h-w4v#X=_gZ;5_k<_x``nKQVTk@y5;&%iToa^J<; zTkzyt+$TToyA{{Bf``W8yn^n-uw^;ru%b%yFC`*eJ3Bf>B)woA=~I9Cm)4H|Sn!Aq=!|ETb z>2?;}lc;0yv_-u`^1f(^`qgIKF$*3ef`+=*0|X|yjlQC}-#_QBc1 zUKda2&M$q*+WEzzqK=-`rS8&MHnM)Ie%}7*XUaZz_le2Y8I}Z6%NzK3FtLT#bx-G|QAM zwqtI~jw^t%4Y)Or`*Lxei@pV>Zvjdbrc{Aar72b7E+1%7jk_q_YD`NFTDZq*K?~R3 z0Iu6`&2z~uTzBD`r__y^JDBI6c4770QUBMkXB5q0Q;J5)3x5%ptvwkTuIuPt{6fj# zp!>PQc(X`N*$qmRJ@X3b{fvMcL$6rdBr*O{dmdkX9zFJ=hwz{LvWuv{h;O`Xp2Ky7 zzwn>!qDhYPhow* zSoT1LH<@_z*x273d!#UbHhN&rI|fdCv%3IWNy}fHSMv_DcboM(@GAH0r!aQ3j-N`od(bv&d?lu53GOY!2&-*U?oV&=A>T9em3X7& zj;J+>9*xy_BF`qEw^-U!+a*WPU+j{P`~@ zQtSNJI~k5x8EnrFmIboU~*|Rsok^c}`EMDV2gQOp⪻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%0AB-MX~^U`4!a>OS*uj1H6 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 uLBUELwRssRytaMTU(Eoq~qBjV)v|6An%^vaZa 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

diq=hEIk;C1OG8VURKDVGwT;=`XpE z%X<+Pq07_=hskAlm(>j8?qlIe;+d!3Fuuh(3pEfv3pJ9)VG-XCMNlG!T7;|ATBz%& z$hlZ@iw3rI?~fsD+7k((8o<*FUM zQsU{i6BE{tQq6nA+u~kqwyb08yX+%RZ6Ct8LranSH#<^aVyM~r%tNKs6(wm^%SnT@ zszqyy%$2*BCvy|bx#7(DK*ZcTMVA_z04}mIMoo={kO8~hpW zjI`A28#kBHj;c2w2v5B2kBIcKiZ|jJXTF#7%u%w6XO2GqI`F?}Q}N%(T9W6CE6_rc z7Exo79y!U~j`p=J-M_BH;}FNolb*Qz5#(QDe?tUy-r2t4y(ONkjD}*%+W+LVw=C6N zkUxCo+*F(OHnYxGVV#U2POL}m5ACRi6Rh+XXH3*|cwBjT1%7v4Rb8-hzO=a9_)3@{ z^rk6!ruM4Cj&1ve71};!m}jvuSfiCYQL#~fZD{QMbvv^t1KY{nzPx z>u`_WQn6R1-~UN_)fH2l2jmO6Z}kYKp0u5Ef(%_CzYDxA+FD-{sFuOY@gn zKkb=4aj4ptXS%YzLpPj1Qegd!*1(2_*6XY%3TyJpQX73f zU)rt$e^It+7G~vCre@XF)n-i=6?sbMr;PEi<B zVvL*DeYmD2Ln}ixTU?0;;zSh-TG7g}8m0o)r(DM7`mq+P)V%r*>zgr4Wl6N*Rq2@v zhC8@mEk;Iz>_~#d-cH#*94|a3UGQ<;@60K!cFt*Sf;r`mK%S``f%xR)9wQ49&8)>d ziI0ZbU7lX=9X;cp14k~wN>o-G9<|!*+e9da{7~cu~eCm^$WxWjr z_tqOJ^VbHqDF^44;LHAMCU~OOb8^yrgJMe4)!Ub*+dl+iUT**j41oPWx^46y5`F7}sha z#cQ#tgg-|x+DLqFzP;H=OYbd)A&e+WAj+f9-AqxGD>6d7PcE3|%R{GL=34k?#hihs zpB|Se$=BwigCl=6cg~&ZK655B>)f32I!AJc&b`KHl2{0_6fLNcBmVtnMAwJlliQa< zTrPJjoD1@4eGH$f-3s?7@=Wbd!k$F>>g8DrMxo@E7A5x{-D15!i3M{Si_?d8gz=bETixSP(TNmoeW@gH3n$|WK7dNl{)~IpB zVfoOjYRb!NYRk%u*Sk{Nf|STEEsu-r(~B6HqTP~%*~#fd-)NhWFIQ)-e9#Q`Xsi$7-zTj%F5{7V94Li|bO911>Rt(|%C0OpYS zU&OQJW8W`lH|OIoOmpT?-D4HB9Ni-aJy@Mi)i|RUB78<|lkV4qvGegnVgll;5c#Y2 zq|DZmZ{3M8#k0)pD|(i3{+JCquo({JXIwIzu+av= z3-j~qSBf}zb6f_e92VR`9=twnHm2>kjW~2+7AZlqxdxn7PtTBQQSuhp^eWQ#h<@_w z7Gtp`x>bVl3P2U{8Pmd6Bh_Lg$#hUUQSpCJ_hHsQy*eVZ#ZychPK`m|0wuY43thMp zZ($3rh-vHUE{YXN!bzY8&nW@)Ed?$x z2O@}LJ>N81K09ySoD^X2R!2sKu2HZ8&IRhB2C38jvn~ZKdN`I{IW{=CbWOJR`$nQ<`<(Wt1B97n_;2-e@y-br1F`35{jr?L}qA zIzR@Zrae+fKk!Rg3ct``fx*bx)MEO<-ShLi9hkuN5%Z*_H1`m)4-8^m?}b;0HB4De zn8><1*j{Be|I*(ff4OLQ(N}Wq!e8w|?{wXpvL{owIBRA2OLJvL(3`VbqMwtyIb(t# zV1!b38I8I}xIS1j-lh(rFQ5h2TxI)pKl;KL)1)=1emSi{iCHqbE%^kwc>6HkK1@r` zjzYqoTM8L~l}CSem^8hHh6svX5=j%MIK^Kx2-z7MeSGMl7lmS*H(Q&O<*oj`s0xcdw#zAoblD**3Qz>&aFXZk+(KBw&D{SmvE%*-;%gh4fO6| zVA?(inlh?ffY~xocdfvtDQ%Ae%!ybT8JLd@Joo759y~Yj+-uKhnZ93!8Krejlz|#6 zjDZt5#B&bRvl@)rrCU6&fHtB+!_o67QAx&6CNVB(vXmClq===1@=(S(1uD`pY5aXm zgz?EIUlOudpHak6{~9UF2Or<{XiR|dU9BfUq^phh#n32pF=^!SDTjn&GYRcFf!H`; zXLk^tUyeD<0W!1Prd$pw1A38y<(Rd6%-Yi_skoDB-+>guHCJJleus7w`xe=hE7kWY zDBI`mVRf(^Rg2K19?V?Vx) z7)MwODoz-){Ol-VG{xn3r6kMGm1{=|8>8cgPdwqQJHveZq0qC6xawcM^70ra{EsK1 zV}}n0P7Te^56uJ(D~6syMX+!TvD!Xo_F&3UBOR-aC_!rUYRpZMO*2~NV&}T_J=(sq z`id|o)U{ZHnC%R{jakgbbv8!v=r>rM)~8$CUAWOt>;kci#VgH~8{XG->Nh&^jf3|0 zG~gShdc%J7+=y?YUCC>;d*jH0;bCoY^>^&VFW9YHyPbCq;eAGr_|8#WAGI+b&}E>o zy=9IH5K`AQB%x)I%Enhh*=Gj}t@{mcY=AJE>o;^#5mf!F3A@*h9hNhU_+v9o`_KZIrHm1iguEBbu`uo`vfA+4C3in1P`b_>u{IIR?(5P{=~Z9iYrQJ;*?e2Nor2)Bt=k1#QtQ}>iuS{ zpe_pU>}_)~V&fTU8=C+1+tbmJKg0qvMO6PV^t__7`uC+cQNdrRNZ_5mhohr@54Ozo z%+I$OXJV)x`gAxP__$K4*Mx(Bw3Q?V*kRlHhwR)g+DeRL6v5(<=tB|iD4M(V-B>Ge z5%gAXQ19007VX0ln-^&12og`^fnWp{VKb^Xi8LS4tr5H_Ry=JTTJg-MRDFpZZo+-Z zk_E;NRI*nnec+&5;s9Ubjc^fI05mkNXc6KJm}cVG-aT<`)GWmJKDr(|-$bC=93g-1c`F3Aa?{x03|nej#)G z0bfPv`M6BHD`5a`@9gYe2I0OMhj}I5K$&7;p5zP(R=Rd$UKzv5gT9eCi|7E=qTVO! zs|LJFX;Esg^jh7U)|#@$7;jJ&-qicF0%+SY9;fax9yeg$Tchu-!M$PJQ}`mD4iU}; z%EQQlDt6;)7y5A>s2nP%BDspVxtc(rGzqvFD&U5Ao2E`=xaS*6u&aN~5`SOCU;907 zGrOQ9*ZR}LpYVB2Gq2#>Kkl*~G&gxm@3%fRBQ%<@ex1MhdkRyVN^^@n z?$li)1!iGhewoWV6qxcB_)nZ}n4N7fjw{=aYe3>_KG?gxDQ^a47=d8j{}ga?iM;Uh0{y%I&&4;aB6R`%EP!X++lm$6ZO^tl zGGwM_vLKLz%U>N8FndAf?B{n_C*rd8T02(OxiCCCJ8Zo#fuoo6Br!8ojfJ$h9rHxV zN*`7xq^;MUr)b}ax*Mw%!@d(*y{eZ7e|wJow|g8IR*NR)@sB4)3}_){X! zxrpJ<$PN61&MN(hxuaDt0y+Ht{P&bKhsT6*nJ}0I~ zBpCf5sfY`TUnmuShvf66firl5L56;ofoI~srAJ9J^gQUrJ$gTQNg@G~&+5Z{N{9^H z7wkCCj#1xIkC7-3h$m99wJh`$G$G`uqmgXWJu2LlP;@f*WxP>X$wX?0OTiq%C4S*BacM}gIX+2HQE zNk1dMFg{2-O1<5oXGQRKke`^7ZoJDVHYFWpBlkDTHlUwMY%RtXccSM`*u=5&FT&o{ zku1GXBSl`M^}9s;`EzeJAH2mA8OORH(|sXMG;4|23w^e-bZW|1)ili9-QllHwam`8 z7!%6Gy{@LPu%@=C2-A%y!cNG%4X7_s1j*Bl)lA$o&%oo1^DJi0_<+5lIpbd45|6cd zreff-BUF3RJj|5JsH@X&l8)`V)ecICoNL0I5)av|pApy7uUqOg@^A!~D?#=(qNxP^ zEcBz5AoQabVkxB%(1oiHWkCicWypniZ-1bvw`aXs1Xp)KK=Owo4Yhk~)*R{WJ+h`o z{cFDO;)g$c@t;xh%`7S^=w7p__TraaKW;pF?C@1~TJYl^G&*lN&=q7oq;2D@4S81bf;N&owvUKclek;sA*`Z!H2YR zgH}gf=WSZ8fhHbD9sPfCD8+pNDb=AVHLP1aXGT$^12d-Z8LZw&-vGU*>dmznXT5IG zG8U{U_xZ|CK&o!NB>Ugpy6r5NO^Egnch#)gQ^<`U8wW2M15@5QW)JJM6#o~+E$QeXP9@=di>B`BA6+ml9* zVH{6HTg+WdmzR_|2 z)YK-eM_o69*1hne9RQ`TOZf?COlEIcvEMv_ zw@x^}NAgZM!ZWCb%im9ayarb)s>q`s90zY02RTSaki1rGU{Q`=d=asJhZVAg@te|) zmipX_MoLX-R$=S;0@GX6UNF^o6qUNtGu>vY8Jv;q<~4S9bE@@Twf5D&iDf{TO-|%g z*VPxyRTnpRu91A_Bh}p=cUF$45NEa*_}poo?O%MaWIX43%!gJgC&K)a0e(4R*KMO5 zZ^f!TX3K}GjV+FZpe&_?Xx0*fvRqn9mP?EA8QNXkWkkwz#)s4!j1LJmlhH|am-`S( zhc?ie`|xi4gj$u^1qz4b#kE)TFo`=v)#P^~T>`4+J5)8+?_&>_FsJRb zY?qQ!#`gaH_Kg0e`sc69j~btU@#{sohYooPht{q!Gqoy8GhcBnRnZHdialcDXS)s? zk2r!VbgHVV(sXpw8P_4mE7bFV?L{ksJKF-xWCrHez^*65<~##5mgs2)cuY_X<@zZt zw;J7IB&klfh)0yHM#jdKpN#&`X3&ZJ-J$zZ9}eplv#`Vq-iw~}jrQqhL@F{)BK88~ zV`4AZC+10Hw%--Ai%|5BV>?7Doj;g+tznPxIm?_nsl zw`1-YRf3MeEK^I-l9O>roi5!X?!HI2=uu@B6A+BvJKm|S5KO+p_TEKcDGqjl;1hLp+=VV(ZjENmr-+@HLcdLd9-* zdYjf-6?IczFOvf+@(LTX({r;j%(O|Pqv)9Ni1nGYhT;;MlxgPt>-f zl*oOhD{6FK+9jQ!x~ynr`v>)NVi3tA@(Y+5Pv4caxMu0`R(mwXC8B*)q+^5bzXAQ} z$r3IROsQn9Gq$BhrG+C%80w0{noGv)t9rbD@)ADr^g)6wcFB%R%r=q2Lf`~T*v9zW zgs~=c-D8g#!T0C-cRQJqS0PjKo&=0zeMRw%@z}1MC43Va8AD{{f$!B%eZ8ESleyp> zW=fppjU5i}^gF!Mucb>p=2%+wpoDOd z_%TW_qqH};lT#9gGp*3S#F^IF^IwUcL==;QWGrfj2Hk3~M^Q*%6*(aXNpErx_e9cS zP8I#0(prOeX?;q3lzW{G_%?D4CD0~Zv-<6J-G4ittizK%c(TWSSLN9;J4lVn?4Seo zZzn&EYks0Fyog%Vs^2U|p!eY{MmrmiyH=7n|7S6o*_Hfgj1_R&ZqE`wad}7v_0=PIkS~5?@e-+3m>Y0!NR%!`5R#NPvUf2^l_z(};?sloEU*{S(w< z(xM(K(JlILM|6uBp7b3_PiD1@VEz@_j#^EgP^&R}Q?!~yT*b2_&*`n8Cqr7)s-3#U z3|?wPdTzyv7TZI3N~~G2Smo{G=--WBq4r4BTCzvtUP^sOcrQhsl6@0>RI+bMrpclX zM^N0NsvyU~(I6(z)cy!tHd0zGkyAsF2Wc>$A7^Wr*O76o=ZA+cW@W}6z>(t~U#j%N zvTG?fm9>t2)jnt?w*aawFE2HH%4jDKz4)P_JCLGQv!>!kmE^zBu*OO9uZvZLioeA7 zb=OInJzq($Bu)IA5$B5%nv^44GsZ^;w#7Gv(w zyw#}RWJWr*q4XxEvkK!xdMlMJJEVKDIywKfX7E3OI=o`#pS@Sm*v_zQ>qP2uBj?IF=lusI^LaJ zm^pIn801(pXtLGbn=crQS$AM&85c;w?nUAPj4&CxW$-!XP*5N4OPEpn4)#^J=H4n> z_hq!(t6SXFvm%s?T8y_+Ks9B%m+2?u(Mmj#=%UD~I*iRdzJdF)(^`b4S7VXS*69}O z5NyybYRz@{y|SO8zi|u3+Jd`7xZZ~AZRo#S_a~xg6P}2lQ1q&jj>mMbus@OKMTqCH z16TAM$}c{Hklb1 zC3au%k>sox+V=!_P5ebSI(k)P-z4VlWyY){|7amm{>gbkO8!ZU@{cl3S}OL!{5N%v z(v5z?7R)_Q*mS~`*Vq)FKdsM97~aC-hnHtajp!C_$hEq)7H=`t08EN|!2?oscZyMlXCD~pCPm0qImaPqh4=b^5Qc_O+ zE7I;?<2f+@Rk74&mrp4#<=B>fl!9PPWddg?NUU=Ndx^=EuQ}3=w57C@{UD_sz2nkS-f?Ng zi*&N$i|Wmq9|7GW2hpaJcPZ@{mzEZDueiTl10JBQMxVDl;ck+wp9N ze#RQ2lthvfL|bbDys^~QQj$Xf=hJ;vDxiisK7{EQOP$w|L|-CCgr1?h2dB3+{bklm zWvMyoMJ2wh-@w%@={(1-O&ye>0b zm<>TJwF}hn*wTVnK@VnM@VCzZm%%lKY6Z@7v87atJW!#ZRbXBE?f%Sjkn!l#?AI;w z)1YoK-&=51jhf!{c`BUMBK96?9LC`G>lQOyB z>Oqx}cA2Z*RqO4lytgzvD=Sd)$D>c|EG>1V=6YMtotvt(9y7B`O4GAL^J=lHe^=t= z?kT9vt4I%)`%5wp*0iUY`8l2%S9)cAW5Mad@+vbkcC{x8n(JT~b;hXc7T7kz1BY~V zCvpLOnVFc&Ow6prAxyN0(9Xil=GnZ#+zI8S%EFo|1FcmIUHCxyajlaBq@_4OT8aat z#hg3J@Z?;uS&y|D{b@h#z;ELkr+;i0u6N-Z_vv1&)JQxktNW;5aTq<0>DDp4OCAyL z6Ekk;eTqO&qOJ@CKtx@Pq#P1!0mqshu7=v~*UG6WFSSpfIEpGIW?@15+0)0$tq+^! z#r}+}&}qdS>feNR@U`~gDpx3hky+}?b=B1P%Q7~5d1MYBdmWrntxaQt02YN*CuPP&#HSg6u)`<(~7Ij5~ZZ&|mlG)8z zso2rt0|-Y~)i`1!tCotQs%R@Ek$OfxtimteYX4$Jd5Qjqy%2q{%4Nz3b1~+KmC&~p zk=4H|kqC$K%qhc6tvPLd&-}rvm%mNZQ;0?W4jMfGtB5rHE@;XfF!7fLcEyrCuVRt3 zBGo-wk!iY>#&b}h z{mfLuL}l*uqChiudfDaY)#6wF4tEuq5|8q+Zc5}{P< zZ$IWwB)qIt&n40Qq@KL3s3$E&J!vubG&$vZ^f-(utkW%3%?KVpd?WpUL;Bf}O?{O| zK)O+G%kL9!N2Gs3>Ww6(VRG}Fo`~b>NS6^sJN55M7U26He)!JQJF_$9=F)R^o;Lok z)vm$N>o=6VyDlmqqzK=0P?$d_RYuJ7_Y>98sy_m(w zs1U38t2deVwL`b4orw(}~TEO-vM)Hulx#<<<6^e;d1k6DidHHEvu~ zJNLP=!UDfPFVChw&o1M7CMKyG(cB>$&-;64&&3tOJ(pCSRvsp472_FCmXQ|G&0I5L zhjDja4yrNQOzA4IW!bf>{XCDqNv&58T_aqby;^IJmn*k6i zagA{?s5kh#cXxH|>h}A)cXf5`?)IB&Z+i2ajhdT&QCtSp;r5n`dH1+px9uLIGmJpJ zyS}C-5U8oCH@DSq=qxYq+)!V?zN5UnWBunt|4=?^e9;|x%G_hU+w>Ra`Q2%muG?O7 zCe^z0y!G!Nz{h+((9{&b2PB1NJOF>pEud+=9r@jAdt`VLA@v(0A+(|-Q-c2ERLltT z9ZN8y62X<#Qe&^FKHawuZ;t4e_*T?7(Y}>djHG-k^qOqJH_*Gx`x4(@M7EZCm%ipb zy2V)SHc&+L#TL9FF$~FrRTz3~yWvuC zrKRS7X#R)rsH~hV7Q@UyUKn+~8NAR39!Dm0%Gs3b4OUbh!OT%sXMm=H)(@jpDJxs; z)t84k=5CDgS;bzf^&333AOlY%`XKZbiB4Ip#-%LYty{z(@6|2lKknAlCa)-J@5c3! zOZcD%?+dlLZ&KqP!$>D|iyNZM=k}ZyWb1l$ZjW{2YB}pfeq()Y_HXC8p9`2}eLYyJF# z;e&i0yeu|DPSF8iTW@ppNGmLfO+b21q?|#tV#d)W#FtT*2#!?g5@{)2BCSNagpy0W zPsybaOVQ|7>KkQOP!Dy0-ozSq>UTTQV$OnmTR%qX1P2V+yug^g(jAP3t;O4vZk@PZ zkL&e#ce8$%J^=0uL@p`YQTc)P>3;k0)~IfcqBWsg6BvWqNH~|;Xb!(*5y%1c3m4G; z8r`}E{ka~m!LPX{PNYJ~F<028VP3ZpUx~R^hJGFB?`v!W!au%l+nU*DJTs6<_^UA& ztL9F|$G(RCRS7@i75(LYe|d(lB#!d?tZ&r#mlwZPl(%KI?fV?mImjweW6{5KFyc`s4 ztwyM_5@kTQ0-z9cJf#Ll0ch0(TG5wWi)*#hT!)#9i|I9?34F{*--- zc$<`69K?NP;}9n+b`5c|V%H?Y$trG1VBIEBByjHxgssf73RuFE1X5{yCnH|jPI1< znixsH?#IX|XFWP1%BX;h!(9!LveHsWS!pFk%F>stC`P%YqztJi){?{*WE_QNlh$_p zqD}ZkyKEUnuj8Ief@|A_>wUOpglZG658(O$t|?JggQC^gBe)v-AuDV=hs_kWm21PO zqpaUZ&bXnXZ&xt5v#+9}Z)Y&LtFL0q7rtQZe>S({x=uObr*hlQoz;`ZFK@c@PNVgv z)F+J2+kRK@uVD_>n)>=Rt)-={YpmRwiGL}{Np+i^ zLT|C#LD9N~Lf_9HGd}7Leba0VojYMYX>Kx03Idt#OxF!BpGo~tMSXomInuH+H2=7< zJ0XsCogG&?ZL9+aWn->7@e#ivb3d~k1Zyg&%=)LDwl{;E#5$eQ;=U#oGb}kX%4()p zQR$=_-8T`6R*gme!Z(UVhEV)b~}?)>f3))rF2ebf1m0C2x({vMCGFVhEB+c3TU^ z&EPH8!t4hX3{-=XI3bZj{g^`&^KClUE?m<~ZQ#E0NoVOdSg*maTYj`^bc_4uTHT@! zs@E-|csXJ{MyL0zK|e`^!d1VK9d`X?_D60D2&Kmo<;3_Jr2o;l6xy+((hjQ zT}R7>@zDM8__X(9IZel^Vb-_`3Wm?(z^i3B^@ro0Pg(CJA~)^0@sn6)_12Gnxq=wo zyf8-B)w=?AJ#uVo0epSbqi?kJC~>+6;OV1%-s|Ym|2H6Ynf)zTTUzYYvC?9NI%3Is zY$-(T*#|n)KiGk5yCp7-eg9S}OH~r8Gx{%g@9f#+AS>j}(YY)a$lSe8L#{cy`miDmj^J zcn&9X{Si{IZg}uwQ8bLVEIY?-9J(oya5Rs`a#?=s=$EU=W!W0U>lzd$d-0<~7mwxT zuN%Bcp?J?VIw)S(R1$gV@ZP+`dqh|6#9BUUjINOPB9Y*#(qSa3TSb29gNSFh3GHct zSAnvESrdPS;-fO$SGF~AZDO4Xu1(%nxHf4~yKdB6wGkszyDE>Ol7GA#ju4YS)!vY} zT^Wh-;sd%x+ie#{5{xe27S9K`9M_|lc=8i_Je@Lz>;FyNdw|!KRcFIG=jy5#t6u4< z_uji@*(#QMw`Iw)Wm~S}G7V-R1H&-QfJ257YRbUC1ZJ24X2>u#lr%`8ndA$BKp-R` z^p?Pv0HeeAzGt1aZ`GAF%>V!2@8^+q_CEWZd$rcuYp=c5yVjn=HRV(65bhn%u1!9p zfxNzO%P+A8jFHNozx+#U`Y*htIXS<;U7J7fT>i&?am3pC7tg&b@hTlFhy`^=|FJ~! zUkZ!;ZUW43Wx?E>m3E}VeoWQg_wAx(R%y?_eb{#ia@PvWXbb#M3)oj*Z(W7lQKty1 zw>tvWtF6_bdUdQIQM5%QN)fcza;RRtqp03maFYHE%7?7ivUWG4pI(#o=3QKk$4zS- ztx40OFM?H{CGN=GhG3D{8?yG;zXR{3A8x04b|+fyJ+##uLnbpk6$J z>m%+6J?oktI$4ng$#C9i>5CY95%0ci-p#yS+9j89hk3gR5x-3B^A0SFUc}e1Z*_6M z=Q>hHoVR9VdlqAS`Qp`Lr9>BiO960+{$E~~;F?ir%7^T+rOu{SZGWgpF~A|lh7W2o;tjcherb1hPIK?YobJ55$j5H2=nj_Lelrh{LQ&u%j!0cwZvkC8- zHmzxl+k|(~J4>{vjv`t#+%rRMrk9ck0GG-37niX+%nX1$iL9 zh}O#k52XqZJ^ZPlU@Gr`npL=F1e4dIL*!b0^5f=7+F4sni|Focro}9QE#L<+UV=7I zj%~qvRU-`IS|XdYv-BJ7$D3wNi+25fyh${~UOb_z*F3I|U&D_(A{5!AwI{aLAg->* zH|XvOgeo#cRt=M;K?@@SOH8jPwB2K!oqSN;C8H7!@uUz?X!SlqF0zHY8H zEjhzqn0=tAyQechCzzJztBIB&wXBvClq0!Ky<_$D4SChM^A+0$>lx_ zZyC%>w&4CaA84#7N`WUht8V$g__OxburLwv5~@uEBQfjy9mtK~kH?96vhpA|M4u4# z^#3dheGqsT!Bh?6vxZHJ7&P*7y(>+P;Jf;GDM7kYv0wadj2P&f7%|vtTEsjtVjyx! z?V)nH1J|laCU7lsDV96YP@n;xqkja}`Py*mYmgsbe+a9-H1ot>!Kx43eBoG)^A5Yp z#j202Rdjmus&Xp@r+%QSJ;Rrml~ajB7prRor=A+K@OaRgM55yQE{LJ{8GNk+h#gE| zU&JirHb@IS3iR@3Tw{fBMXM8!o(%diSE0$<1v1W1gi*vv(w`o5DP4vh*3+pl<5)kT z$FztV9x^SWu|`abh`1rVY1DmF6F4a`0Kqwld=PI3Il!k-IwsAtlW1)-E$XmIyh-qJ zLwG`C06TH5@<9tntQw*)^zWL%o90Z5{)isDN%D$`^`oU7E=NrbD}&ir5Tj_z**93w z5&Rv2v^&4(K68AgwlNu)_MS`Uj#NAEvb&1P(lVC@R=LBo@}2isC!BsYnv=5vnd^LI z)xkj8L{2d=?Nxatf@wdrE>LD~S^XZ*`BUVAdZx1IpfiXa{3oia5|KsB#BPiAe+ogx z|96n>^#*m$7(t_HMdG6i!THu}_`&z8$8`s;iP~g;C$0ruq4;${S7>Xk=n8u16h}eq zJ7sc3?E4A=6K>Mje+T^g)5+HE#+eQ$*M8ZRrH9w5W%lOU$ANusKJI+Q{^ko(DJ~9S z5jX_JzjtA7?s4rF>W3E-0p9>mRF)gTYygLwOpBVU0rVA=Wf3?jb`N`%tAgF^0*A@d zZu2Z7-h-w^ON;p{k~c$t{3xD~eU{q791&W-h>n-KPmD1#cM8>kiHuKxj$Z?dpSMpq zjn)^Oo*e6|OFub&ckIN!{Vi{?DsLCp&aMuL7ryypI^#dSP%~eeef+rnw&kYw_w3@t zK1acr2u7Z~#iG96FZxX!^fZIeipJUJ}5c;&FP zUKoevS>>>_5_4Erop28G+p2em+!iZ@+~)Ze;ax7QEBP z7>8i#d$Hr&PM?R>1kTfsLEfbpRC)@z3XU?bEgWM{lv{~s9TK70Y+CdMx0)8UF;7pF z%F!jDxaeX*r1jv<%vxc8FRmHY?K97cheSVxmIQqha>7D0o{$}^>_)|UknDKzk8n4n z&k~u!Cp50H+uR}M?VxE9$C-k0>a`=rRCYSV`v$ zWyIQ>eb&DDM0VZS!Jh7eV|D+qO0{5ByD4raVEWw3X)}VZOAfza}RK zSp4@br!C_6%szAYzsrh?a2$%yS7cu_CIRGNJMj4H?VkWy-v-3u0BnLkgY>X=JMq^^ zuoU~f>>5gqw&*=$b^A2Xk$l#ER%=iV(hurqUK7L%x!vRH8qq1j-CW!i{FFY=>iBXx z6>Gc8ClmeDZd$B*Q-L?D?9t|vm4KDsH@SRu^OjxkkQ{c}=K<)W&l|GpQ0v)+8-9UVQ^ z9d1J*JMk}WM^q<=cMytyK`ykvh!*C%hjD7RkfX+ zpl~vHaMX7mJQ#xYu@`a5XTbsH3ozS$qgXef&*chz5)zr@o=!iJ{_$O=MeH>F;Ct}7^a^do(+AzB zS=)u#q~RXK5Dp$&I%Jb85MFs<&I>B)%ZqU;k}+mt!9Q(%cX;wj-j%Sj%)xP17I5n_ zzg$?fTe&u9JMUL6>2Gpt=}XF}lLNO*mXx-&-4cd=mx=;}zklw!OXsrEl$AHJyuiET z@bL-dAo(}zdpY>G89NhJO!+GKM{g|=GHF}K-n|A?6kjvFfqI|3Ov9Z9(3dM~ ztGUw(ZZ^Bz>@a=wJ@%RwQGl#0M%*TCC4DDXQX)fTe=jR1u?l*hScM~|#V8wh>qqeo zj^diQ1*vC3%slIvki&{tkFCRO0PAki^icgKIU&kx$0FEcxc$S5;m*4Bw^~WnMX5PG zH%bNOWAz6+J(N1@FCV?ec_~cqx@E&+W|@>@_FIi9npgD3A@q=0_JimWZ|Ii2FOAIw9+=r9!kUos{;~2 zok?FFv7=ku8BN_skFm7qF(&RnTBR7x{YbgX(F)T~&AbIX68$GLU!%CpebeVztBh52 zxW zwLXqKdkk+nY3`jw>zrww!@C&uJ%{(6ixUC!vkrxTL1WS5FwK}86^%ZR)*x7_Q^S|) z*Q;#kZ|gr?1p-;R7!4pl@5{y=o)jI@YIRV=ac`{xGLm-w-;bsl)V%_R$g4 zKA{yvG?A>yT$`fT; z)oxntpmVEG7bA(T+-2@@MHLI_Ih>5E&u8;isbW0E9J(@dpZ>dg(<1J27e>pD zrxBy+OWCy!o;Y07cA7S083&?YcPsADUt5i9UCrs+7Yq>n!E^ZR?jFn3lGQUV0kc_c%EtSvkuqP z3FWv}KkQcX9J$_$JKHfzqJNtC$lA$*zsbXWi3G)wfY73zvVs5*tz8L; zE=mBFCg!Yw^JeP})~_D)Bw*?I6AuAlO*xoz=YA)=D6BQGkaXJhyfcDJU-?Evbt_ys zV5PZ`9B41)pw)~~%Pk}ajpiQbX-E$AdCCEIGLdo+G*2;tTx(k7I-@7`t{gOib5r0f z@h;pWP2-x<#_KJ(=H8iOcHo-!DSfLFr6KY~zX5G~?%mW6Pn@Ade;JP^BKkSt|8z8w ztdyA3c;{)X-7z}DBzkx!bTHAwJ5(n|X@oG;L(%JZjNtS5*>R; zsu|xFDLy-LtapaQ=g>E5q6!kfv-Q|M3edAr0^~gI{4PP$!4r3ci_rY`Ja?Vu`tf?K zAG=`joB@KDxzGndC+-LQ(6X{0prllq7O?;grqzH}qiIo6{Gf3QXiU4V!`#u6l30mQ z-%I?FdSHf3?+|+1@D7dd@qOZTp}nWi5|_gLg7^hRW>{-j?=Rv$aiPL(=n0G^qKUoF z0@W102aHodct}vnk(vXLJFlv+x5{`rX2o5hU5qNinHl%yW~1C(X&`NPaAP$#h3Ux1 z$z!eIXP(*T>5_VP*>UyF$)_@#_Cjn>EHl}8xvnnyo2yJnznmO?<4kF=W>dwhqu|GB z#Q-_G<%ZwcbHtSpf0!73y@6tsotKMs>BG^IgSAI>4rE1ajUA8`t~<<^K4~!`^J1+! zJo!~tj7VEUdskj{c)I7a@Bov?v@;}6URNC28FklW#mUCC`0GR?sP^GXB;Goyb|V-C z;u7>*5dXu#KV&h)(9R0 zy;xKKthFEVK@Bfh;;9HMv9=UT?By?jL)-_f1C7&godz9}i8(HKVZjn>i&jUGxySfH z5}s0TMY*{Xs&}{B^zFvz8oZx+uF>>Tdj;{1Hr#3R-X{?~p3b75+lf1rfdPzS43GM0 z2-nnG7OqEe&5DQz%oEh8Q@C>ocMjotH)KWZA)X(l2zAY|Al6Mk>x}o#GkB7?xA>S~ zU8Umbr)5CGG3E~A2GJFOZ;e$-8^dY>zeRPC{*Kg1)~mX@{^9VW5#@j1(R0KVt1u;W zW+VTQ5(bgqCLi400XfM~Z7Bhwwex+7f2B^$^PlLJFfagP&k3LUbv={s=$9PItqyCrr3T9lwZe43r zSl*U?MQ)$+4Gb?!S_7eK!BKy2u*7?`k@BINla( z>8Xm6!-unixg&e`T8FG(EWLfsx=~H-TZ_xf0)etJcm1R9`)Zi)`&80@L*^)9%z*Vn z>WW;MqyA#lxD@=MZ;aQ1s1#ix=sHSecV?CQ~=eN`=roSUSsIT*i^48UN^}jT?b6u(w#EHjymXXAPwBLvQBOi@n)_x zh{r`+l#Ng{s?dxgu0^zu?0eK|;U1_Sazx(=uf>ES1B5UQIgY;G-?I)V&arS7{|-NB~wCh$suAZ%r4J%0Sl_}L_Gatr2uj~lt3N%|&u z&GnxCmL&MA#c~y1Yb%o18DH;)Y%wkFu8Cz+TbF1^!Riw=$4FVY4Ak_Zsw&U2BwX48O3jUuHF{Nf zUw~iq03nRoJ-hx`>hU^1+xy-r0XcSFckXD7^JxDn{iP;~c^0*Hv)Wqf1>iVe+nX)` z$Lz+|w)|5kS75JeyRz=G;28H{-97H^gozWO?dmfqJ|BBPIhm`g!!kx<7@viIl-fKT z$p~NPHF|A%{)wUoX+iEVtsPhewz)hX$H;Nqn=<#NaBsqW=d|gY#`m1S_f*eF6RriJ zC@4g!f5C_}@rY|hA^Oce7#?zXNyM=lh;oGZDhqom-s*u5f7U)fyT8^gsM~YtEDGvA z>=o2qP~%a5Ti*(8fvr5}$(^2M@Z<3PZppgxoIGDGp@*AuO7h)ux~0DKU|B`hvAke~ z-5g~{UI}e_w;u1ifrh|iwl8dZ>*{mC7ZCS641YT3IClihcCfKasB-nWjUKTm1$pEH zKPVM8Xh~!%)_C-A?k9uhx`(MW&sTz58Sc1B+*jK&&)m<$ea1K#Z`02d|Ejhk<87?q zEZ>aCB-Zej7I!9GF?44_9Gak5=!Ii8F4pm|y16=!Lo0SoUR`twP4uq8elomd?tD~u z+qw^tY+aW1cjWRsnQNc2EPvOj1zm-KNjT+v-2QU(A{-v~NX8yu5%Hy;xpn+DU}o^N zPNIH@Lr8*GQ*a2PkF`aszuMfZ2A!pfjavO#<{qmZ=eRt`GkwYzA{w5>zLT8J0)5M_ z2~L^S0OeEr@i`-=HG*%|igB_lluVg%_i5&16YCdlg$vNH2A*eJ!4050yA{{euyBR- zHmBSAlrx%ReR1iR$43*!DMB73>+L#4QtZRWTaVUepIER8_j9KFNz`OwRKiRh;&RUU z4r6U327JU_A9*eTb*Du8nj)fo+KOHswLdc2Cs;^9-$*pM0Q4@vyGeUlGi4nVYnuo_ zeNz>h2NM2!!c7UN{pjKg>*^9zX29&>p^%_yElevZT-BGyE>X9`pMp#21; zr?Y1zJ`tW579sp2Ep)rEx)txS_q{I!-8pyaj1;*&b80d13b%B_%iVavPTwKS8Dj95 zb4dKo7r`mT--RRX)IXuxEfo|>1?|G|ccHjlyTP)tV$Y~)je-LbT@}n-G|n!(o-O&J z$T_ZrV`! zh$XAR`J`@UBbKZ`(L%KqRi*RurBzKM4Fv^_Bla7kX4ic>4^!=tBhBYH0k2x$()qS@ zds$^gdAYkKgBK>WQg4nnwzB1K} zO9i+5uJotl9+9;iC)!bVt~&SFUx+c>wQzoD;@laUY)Ohu&);-WChqbq|gU~sWyG|#xMHzeevvFk8FNq>dp(Vz2%nI)=ey|U%xO> zcV&EVaGXDVmv^2%z0>*B7cTF_|MuT4T)42%vAwUXtZ#cqdskO`M^_h?1gy<1*uRrj zmGI@Qhx~s8)S^923)=_DE_K&;AHKPT?@P*PUo2&OVU#JwwRnOgn_Ba6Tg~%~t%-k= zvODa)ebn5grMJ1w^RXB?h5VByS#dGM2`mFIMU5YjY z-k6(ORMeYurhIE_c4_)O7vs|Qx((yW6_0EkyRiNA>4~zA{+qIU3JUGK8|yX&QhjN5 zTw*Ux4ZW=I!gi%O?ds>DaRw1HIOgt=xlYr^k&HD`>Z>M$KDH|@Dfp{XaBsJ{M^CM2 zA3OzGg!H^V%}mAJxYLMdx%cih&oVYaibrC~Ce8gx_ess}vGES|`0q1g_F+sY;>~hG8l4>P+JE}=w#wo_f5jFLKUUSBAC4dUzV*(q z3FDl3vq6v*wzf3np5J!2^*3e~AtxQaSMswKRAyereA2fui)bZtPm%;aj~lN?vT4Qg zH_hCmhdd)ahHH`6tAQFqv1RbUtL^&Z*!dC zM{Y?=@9Jw!P0nA}wy&eRV|O^4zncz7*LuJI$e}|=&nS1lT3u37RaH__{odWDPq!a9 z(Eh65P0dJ2ZYVDGXXp9-ot;0j-WtZ;rN0j3&(5Y7W^LNE$^Ijct4lW)WoH)^XXSW0 z@|?@xLRi+_*ayAVvk$lnPREKYaTsz*_CWM|YAIf+Ki_K zE`AKI}cw>1FjuH+`g*thSWe(EgCrNp=5f3%#-v#JY=Xk^bjEF@0~2C-M32_z?0< z?^EJy&1kM_sd$fi4*AZ8YsBhGgsK_W%$Q*H9Qoes@x8exlzb(68er|Zt20vKDee&g z@2J@LKuxsS8_o;gZC|>0_XC6XZ+|ko^GK}}z3h9%rejY%b@?l(o^i5n;^@f8(TO_! zePwKLaEw1z-njD?EB(y)_}APzgn9XeWq#D(NICXG=@;}-YQvYQtgD!L7d#q7qrxkfU|Al@G3oNOO|1I|gcN$~H6ugp)~-}~O|;B>X{um0@Fu?HW# zX$Agm+?HkKjXH0dvr0xszgEp!lDYYXH`8lV4hfhf8xGd;l0Ht~Yb;oFnF7 z7yNRE4d#GenRcu~;_V=IQRW?yZPM2q#>pyBCmEDtMgp(ZN7IaJwRTB&U3b`@eNA#r zbIlvM?l5Poz?~_&?v$JR^aj_P7Jc^2LTYqJ^X;v8V=KlGp(o#w=i*3JD%u!CMiSqo zcZqK*z;g%i+yOjy(A;6p5G8L0cV-yJ<6KRxZFD^b@mStykOzrptMGgXuk+pZ*)#v# z*|O&&{SRa{ZBh8r9NnCuXRRL5{yX-=wF8?>d?#UCS23&QG;upzkAKI zd-0v5h5*r!jJUXQG%?F*O#m70`rcxcD{e{{Cb~Xibd8E|t!sT{aKP@m+WFzkrme&f z@lf;Qy~iJa{8j(v+xIWMnd$c^7HLQ67_mrM{-3G_*55`GpB%j7$eF=^#SFIXyu6}P z0Tlf~$H~FP#lf2T@rqX{>gY`Ukau+XlgqF+lBa#x$se>>rG|bo&gmq03}kL3u?Msg zD=&QZDj&Pd*e;Bfohsv``i3^pTsYeWo~RwU&fH(;eL}#Mm2%V1d0b~&s;(I)%J%zbm@P=F1q3Ihn7C8jMm?V;ki`>#}8W-V`JZN zQ9^hfRxPi;H6?+AU`}_EKld+FJ#W#5Puhuxh|x+8za)819T;<4#AeWmhhrw-x=2{qpH;xF)89G9$YPqCNz%&Uc8;mgnX$cFxn^ zR06I`5gGthXc8!FD(R3x<{^B-_ZMzmzuP|hN}lNbZk*`dJ-n&v_!Cdu8dq&w2R^dl z@vN?WrDYktDXlLx=2uEjkCivI@b;{X6QT3F-_~?|Dn@NPPfSgHwHzoOD?2^=?F-gz zo+-9;=!5PW&OM_857nrPRzGDGKpr|kp>5!u1su;d*LJqhLcJ%irMn4gYwhEymtrxi z^+jHXtS=o$Yngs2(dS|dtM7_Wi0_JeUY{t&6ZPOy(4FJr%^^ZV?-QXhWLm5?GHF`$ zA}Bs}!t~O2!)U6Y5Sj5Nm~~d_qX&UGM*8-Xy2Aq=(XYbxt7_d`ndoHc-=sKj+Uw{8Pv&VYZaOUjZy@y|+ z((of>(g{m{87!HdEeUSkw$1*a zio}hWX=HzgdsH<~VfXfuwIiHfXugUarUfFyEDpdT?IsJD=(EVZ=Jq zT89x_^YJ7&EVh}dh)oYiwBSR8J@rtcDyyu7{I1#IlriJ=j9DHK^4Gb z>bvbA6yUY z@VeA=J3aIIt$i8EJhS@0=EqJhel5Y~9Vbopvy`~$63yX4s zIVb9NHWwCE)?CQxE+|aNzt}idkezS)eb+aS7o>ng4OYh7;vy3KthX8OocOrK-`WIi z#mcD6&nA*J8&tPp8D+b($z~5|B|9JS+VBKny-$QnfoXBoo;Iy%@T1h70n>PctgYmz zKC4kT#n(!%kItz+Gp-Nsk@`%`?VfPoSYh~w8L~X!#5i7y3a#bm2z06awT?~iFV4wG zYbbJ@J&zwREKT<3tsA*?W}(e_+dSPv!9e-aH^X@t?ikwMffIn+D}qI7^VOX>zTDir zAWCM{wpU!Ye{petNl}^gr7-3hchU5I>Ndt3!ecW-Ne_V+jLvXRkpy3WoHNH5wa>Id z_K)y}5q%vw0E&q>Z2)xARgZBVc~dCPqiY?<=~~CwjEt+pd)i!jYix%3v1;{TSCV7Z z)il*$J2K$9I>p{37+_g_L|VVHVWH0XGoLkCKiA@voF{dUyv8}Y9C0_Krk}C=t!H*D zF79xii5p39w(k%+F1q#u>pl!YX8r(lpZ=j1W_x1-iw^@KSm$7PKbpKb}( zA|hKhBs~ENmV<)a>n0;_TfDmQy!3jH6#)dbLQgI;vUNWtr*?>kOCs@sYs6uQAHM|G zJVB`5dU*fy4C$2~apLr(rkw-o>ed^TonT!5(|G9JN85hr3SL4j^r3EVJ=FCg06jb1@GlU;$Huvb6?KLgNu+(qV zWqK9k7xI=f!+p?wqaRm-^kM8vyt)BUQuZax>eX*S957eiJ)rR(&^Uo@DZ$wWfqS_c zA-oVtxTVm8CIX^h^Dc`<7cOFs$v$VUlwVOYw zpZb)&HAzeDxrPU%SOsXuUBBL?maK96c)FE5K}|p`b|^!H=#h3%ubpql zbtkSn<4`hOELn?35{?lO2gvGL{pRDN>rZU1uit!P{pj({^;b3z4{zp=UH|;!zJ34p zgw=nS^Uz1F{yXh~&K-T_<$XIk5#h#fM7X=V+fmcSx%E2drbhUiVXve&M!LftOW%pGPy|xkxjq@k5#gO)H4My~O?7 z`$4BRaG%)x9&?{{rh>SmYX$RCWo}BvQtlV@%^{2@=_va~N+$P>ap>rV^Z}fpb0`uC z(74=roGa1yzcwAod&4godafwG=!KqZ4}^!FUmYH8etHGMFWuj~&~U!8IJmxYr$nC@ zss|&Y&%gYl2{&6qA!ejv4ojT508y<*#Hl3D{jWTZRC^qe+6KxIY4LN-w>| zJV#ktJSClZ$Xw;MkDgoB6A;TNJw{2&7dPY!1uJ9Ox{^>LR` zZ)AA6xWuRN<2o`aJo!Hb6!ulRo7A zwHv&@c7toBF89~UUHxle@jz!ZK$|eTnldW)HM-D(J1vl}I*d}?OvGXbXu)SyANOG# zJ)8DSl@+aF8 z{4GN8*E)Qi+Fs&k7MizVK5jF%*Q7`F$z`a{s=kjvap|dA zou?|vDEcnB+IQi3`j6{z-HmHTnCa>3bDtYQulh4sr%0YyzT(XQqB%L=2bbXm{j7SIepb$O8Oxbo=hBiAc zhP9()Jau#fsJ#la#al4Vr_In=Z7^^1dvqh%GoJX#&axb)>VI@;$ zxIi=EN)Yxnpd~p=O(x@;&s?yv?tB=OmfbnA zBjG&bt_MgZ@Qi-)aGqheil=0c1CHWav09ulg4Gfviugn5$5oDp{J6BD1oJ??67#SI zzDA$QHWX#k#&B~h&Ijt$5GYn2#z5^?KA8W$e?4M#fAGP}C2Rj;i?{9xQd$1!d}?(V&YA6(O?u*{C6 ze-LN}U}7~RJbbAN4`EU7h41r_INBHPRFC1|^J!^));mYj(ixI+9)Hh!tjfp`mi@Cx zHd=4};SV1yE-EVKPt25D`rG`9ocZ~jiu}!c_kN`H#J^TX#IdlVDO;WTgN_p{FAtWM zmwR(j{Oipghb79viV*a2rDC^T;&L>VJ)oNIqKU>+ANU?KiYtn&Z@jPgLXbOPrd)o-4hs?RT|+Ejf*YGI%_ zJukEHY}KHbg>5Cx%s5|8w%;D*-Eh8s-M781#nRcWBW~g~{pv?N--cT~9H<)ESH$kq zX-UYgo#=xyNHB4CT=AusE52wV>Lj5fb&^!#j`oK6LUi@~7YI?fyEBaw@%$J`j_r?@ z@t8fw$-3T}+^ZRBH?}li&Ca|};zegFceiE-vAsH8xwnJyB424FEn{{gOTS;XacZhM zSQh9AobNi*9V{#D4c;nIqgxv%OVj*mDap6BY$-`gPS32j_8EfGhW01za%(F8Cv;X7 zycPrSuD{l!CiBX<_OD;oYO6MPX+x9NGM0N5YAR__Q_Cgh*INHc_Odwb#)tOdV6O!*6Hup^mlgl^T%2Yl-Rzy@|ja- z+P>iX$Htl2LqC1ZYpysA_Q@-DPsg_2V6b;vN5|HlV6bOvM@xHqOKW@k^SfEX+ zQf@)TIecl1A^7(mxB8~Kt`@y%U0PvLPtMuC*{srxS6YAln%8_LM!=mLE&)!#hi|U!nFJgoBD82r*(r};oKA<_W$Tj22Wqi`cAw2V8vjby7?C#KcaVe z&mrQYJ14EcB)c%>LFB%z96Si^+tkmdyEInzm0j3&k6$~lv9hmNDspExS_jNH;$>$| zYZm-EV)%8+@asBU#qtXq2U;>~@~u(_t$~l${;J{58n<#Z-K~L3;%=R*JFMRH5V~+I~PU=Do(U-SE{`A6ml!q2OMCw0_50v)sT+%l@jXdsAbbMKgGTJG3 zL!RexNOAbgll!alJTqHPB7p;#2Lt&0QS%9-Xze#G)=}JyF`R>(>(jWN#x-#$g5Z)k zwR}3`)T~ohA;W%tY+uVv(J1m>rM6Ne^k!;nh0Zf`A_j!PJT;G=WsvzNh@<18%r@Hv^)jB z@PD%>{RreiEVU!x@UCn4!EegLZd}vPM0pTDlSE8qG%IEv!C!cEMR{1x8yv^?Ua%Ia zI1OQ_k1pbD7fYe$9XU^~O)UPWnK}Rt;o{uFpqCA0bvbv@Gv9XRskyCr)?lnU;9f{- zH4osNi`~eCx|H+<$OTW6<9gT(U0dyHdZMS3LD6LNR+wH^1g|$O+E|*K##)&AETf8y zT1zBRVp>Fh>iucFWzMvCrlr{7_#WV$@^l*4d+-hRVDv#Vnp$8E?-ozzG_FpAqkQsN z)Trdjt91oEzltd=*wh$Nj+trqCJLDvodgp{#fR^x?7WeotC<YF@ ztr81uBObaSD8n6K~PWG}q2|$sc z!=^WJRDf}0$;uYb*-8-|$!?B~2s{TIwtf$u#iBk5&U`_^$jsNh9{qFjt%>R0iEpvn zl@r?PQn!ry?pR!HKrCh4D0NKSAa?$TOG(TMQTO!I)}WSL*7e}^AIg91dq=F{r#_UN zSSn(S0%vFQ*`GwM2wQ3kPR&_er+XhuAOf!M>9B7nWI%k-lz>xK9b|xBXd*h3z%@a1 zCc(Oux*9}na)p4TU|v#M)`9wxSw(cdK0$PTp=q(ci;Z!Dr(xwvAUp9qt8A5;QKcAF zfjbgSmuvBL%hOGGf;%_*wdH%!uf5Z>!eycp?@^f;#&t+0^w~(6peI~pf}U{7gna%9 zd?xGt^V^@o^(pMh;@3_NDU$@1k`wIg-BhbBZK*@f14y*$85yrS4y?oA6Iopckx(jBLg zE?a(2e?6y!=y+tO&_DbP7Kn%DxKL`Hy#!IF1Kr50_4Fofz8 zrp}O&;qsA4XUOPC`H0mS^o7a^VXSrVOwuJt$E7$s_E=3KMUe*@qUw6Au-=3Rx9VzR z^hz@-deuFc-MpREko~p2H=r7_bvU!jdQ-PQ^}vCH`>p;JR7=sXe)YbhK%lU#Jyy%? zu0Q>4fB^hO2O`5QvR717ghivUuOQNa$GAca!$LdyhwpWYj^Ard zIG@bF#!Tjn4Gj;)Et7T2V{W{#Qb1ALwBBi&P z(adO-s6H^R7{3AIiEZ0xM$m&ZWm@C|a~&nBHh?Sc-ubM0VuQG%CpKjFh4SItFj`nb zT)cQ?;uYKrU)n{J16KlfnasG7jrELOE}gjjJYtu(s!G=1E2-w+W;y9?_iV||8D4*< zrpw(>w=pRBa=+TQ&-v$M`*)+_NzT8<_{`L+zI1Wtm>bumeLwHJ$(>_km|v`Qpfju& zl%;R1*Yo7C){C}S>qYt83%)20jn{%YCXaNqRu_|4kYEAjt@I^qHRFh7WuAcC+XYDx zJTmpER573pw%~FvI!=o0MC2|ryU|>PMM;}#HAvcNt)Mz%=3dSCfvb6^>sqhoU6FX{ zv6_RenVALIGxhVWIb~^Smi^upv}JS@YUzQFTc*0YTUzJqXZyOk+gh)e*y*Llu|mJS z?sD6Bu0J&+quv@x;2o!a+-dYBMfwGK&63Zqz z@Pea}5%lU!oAKO_5pyi}h#)6IO;B(LF+;iM;_N?!>v+iHaBUdP$B27t(Tt7t6Z3I`YlPDLLwits%d@_d z?)+hv6VF9cym<5qC0P%$o-k9X78I%kg;<-HXny81>Uu++8JU|y+?uXTvO|hopM>Iq zVw1Rpj3)M$Gf`TiEwwd;Po8!;#~HQ~_Ma$&_|>@GTHQQ0CV|BoGp+1917md`^onsi zyC2-+72`gCX1>OG%+6%F?uIqaD`$6cTVa#b<6fxk%}UPC%Be`n1+usBd_j5DtqEq6 z*c-DrXPEn3)|8dAhFMjXJC}OUk=n4{XhTMRrA2NMjT_5NxleBLKO%ac!>X-s*^4)a_OP-JQhzcc85?hi z;4UITOP<1zlxt^eS=xvg6p?!8nz;tKxC^kbA=S%_dG1?c8=U za?5kp`Rc2KrDdJ1i5FT$v@td6YxtZ%CZKe#WEd@uQgI=qvbGCcMn zcQooKEoLuJW~4=#Vf>LE47EhbS!UhE;cQsFZG37I45)Th_wg?{g{XH+{^x zl`0)sphSjyx60h*4D2;6M&^X#VzD+}0}c)&n#~C2>~)wHk@u{W)$h`r)q%#`Du7T145CXVT(ceL4Ee=SoZ`+~Xouve(E9Zoz$%S|Yn&S)jjH zV#Ryk_r4FEx92FnC$XnKp-axgESp_l(OXd$bQ0hP%nOEd< zU4oq9YIB!ym?qPDk+Owp%t=(+{r`N!_*`G#9F1%K9&flZ+TA_MAA8T0EBCz5YQD#L z>it&p-FEW8%xHD>=*)or9+{XJ!H@G1+giGG*?HIh#t-uJ&I4n2vrRg5VJ+K~^ioiP znKbk@^hHns)jN!|2QXGz@zHkl5lE&0eK|Uo8B&x`+22q?slVf_l>A#`P`0d+Bak_N zSOUlSy79Szfw}Sedih;vS?{sxH}_r5NWUs5xrP4YE=un2aD>Po8*)X{$9erl=R0F} zOg1!D3Q}^=P`{u3_bjVS>X$k+t4IPWi;7zA7oh1^(3XqU!|1cChYHPgu3; zh?L=-2|2LzrRIfR;MFQNRqm67;gdB(1>xnYt<8bKkRL){p`nMN;OD*40OiqzfOOWj?Ew@QSSy1&V^h>c+!qSalCL+C~w&ACLG zms39|^RhqKZr;GUQM*iwQE|p#i9+YeUHTrL+(nIj_!@rVXzVx`GwANHvXVrV4dfXe z%>w(_IfQ3koR67G_pKYXp52(|qRO^hx#HvzLsnSoOJ27wx2dh8u&b}mOsLUF5LwLp zDyc4;oekDZ?cZ-*w7$9Y&7T7{W)~I|1^xbv^fX^;ONUi&^{bYeopYWqt*k5!R#)qs zJBKr0R9|-iiznKeIKXIay?kylwYA)(wr()3HD?uLYJ@|-Vn`REmzVy`o^+;itWP*u z3(G5J97(kF%6!M zadR#B`{lXNDVPnAJ;{P+q(maXijE#KC9q zPt{g;zA)k^Sb^A8Alw5*Rm4~u9Q9$*e=j#aHn;NThD|fwJu{mc@VloQzpo5+bPNx7 zbPU;>p@Z&9oLp%a_U;?1tQ^|c+q-YLqGEVoZ{O%>U*G!m&JV1QExoMw^v`)_X#{{{ z%DJ8Zj!ifG>8brZTic&R{{5CKuO0YXcfxPV6DJtW;t2>l@pp&pi=AG?TXHP5MNfYz zo|I_#YI7`gJoQp3KBX7brw5t!_2f;=BofpYC1X486ID$ewb$hdbyR%xRcusDIiT2$ zkPqKot;NY3zJ|nbW*;*28Xt+OF>Gy~>b(-UJ14s+qokxbb!YchH_y_V1oJ*-SQ*VG z=bkvM32b}&{MxSmtTi{n_YehwqjS(KY(AX z_DOz?gHj=WjYsfHTjbX;=qyxDjIM~xxr~gGHko(O_t0Tl-2GPKd&FWakl6s9Nj)|4 zRA(i5x>By?ay%V~hnYyo$?1n5wpt#_4sP|b{Od0QH23O9@*e*8BUayIkN8*Q-OpMh zL2`Q<@=woM8%}Tdau}y%ZXNc`gIAh|w=e0Z9kQfulSjLA%q-v_4}^j2kZX}#54G#Y&sXfFcVcN*6IsYgmqpTtxN5{3FoAB ze@Dm97d{>VSNOp2$)9w3aD|UASXEK#^sx{-m+ts`cP}>YyA%9mtrwoIus`Vo;3uP1 ztd^IGzG8RhL0?FrX%#|`(Z7UIpi2;R3F3aexljK_HF~+y?=roNW=W3oMm(i^?Ll*& znJlBGMSLB1-t_2UG_EAuhqd#hs-!P;TsGMDi`NFNS+Q4OwN0qDTQu@${9u@!C6 z=hSVUWzAKwJ*dwH!9{vZsLv$c&ozoXVT@YeuzWR*2%mby`K89G9!Dms#J`n7x=6to&|hZa6obcK4b*my&iMeX)H>S1>cUwv!7@5nN~r<3b_E3Kv)> zk>`UcPqcn#1!ziCXpOm71Ddn8J?D^)=Nux{#UdotdoUu_Rs)4YRUc~EK+@4upmy#AKuse79rd@ey#GZ7}t)BII$PBF*%1mp7%;+gv zoVleKFH#b+H5L2GS=fxfp1v{4gUn6J1AW27we`!0S@;R(Z>*socQ!V5bu~72#!knA`ifJh z${Sk8TZ@ZZ$E};JkE&7Vylm0=$GWPjy1I%Ak+Tl?4BrCUR>Sh>#9w|Z=t_#vL!O2{ zsfb4uPKryFTGLmHzIwN>!Srzl)^1un!$f=tis5Jn)zsGOz_rwK!rY6=PYgk&VQ{lF zJQn$Iui=KF#a%<$|6|=$R*{z7RrA5T^n#2)aZ&1hL$BGD6HLQVZr{4=F1QaLu{!Q? zKJuv5ako`ffAH|(#!FQdUGwd)%IYr6$nhtqy><9RLuy)PX026l>2Iy)LvBRYWXAb= zq)h|-8+($j2W6PaL9A#U+Hy83y{pNPqGaB|UnFr_?q#*wVy79~33^E8ICsACJT?3d zmx?=0-%i*gx)@Yt2Kv{$Dl`*SkVOG*N% zJNvl^14VZ?2xB`pt&Wx_2X5OxI8@pdcy%i3P^6`0_);@3O?RdH(tRn(>wbNm^Z8`! z?p4qjf=AlUy0q;9;(I=cl?mrTL9U-EXv=vSDWFZVJKL&2S&5G_3s>*6;%f@-2+~V* znAB8~*aPRVj@3ELJPhqSg!dC`%P4~OF>(OfBU_f02xICYc!daK+={D`U+aHOA7nYg z{N&6|FFkgqZbs8%c@SQ>Ytgx|I<_3`I8GPi=;T51FrKa($@8aYt;a%5N1L=;E5F-rOvqtI2a81J`&;)CwH*hl-H-<1v%Aafq7(bhWL-P5ZReBwPArT&LQr$<^CXuq+`@ z532jD2_Br5sO%{FE#&R<|4h$X_*@%?b~@&wB#(gx+_$BnEm>osxz=F%Xt{;vnvUdL zYXAqN5>IGe#j7-@&(Npe0Gdm!4SMPI&S7w9&gIY%(|2SguEd>JV8uY#x)xo-OsCvR z?0HF?a%R?!k^U?3&VaJI$gRYz`oYM_pLIkQG%FZ>>xr)J`l+fbn)P(4(an0wthS#a z?-(-+>BwQo@IKeOw$JcwUku+^?L&CEIgD?7QhJF<*14&utI(|64DP6|Bo0}spUFIx z9lh9Ep?HnHm%OEotaVfdaXo$wKaj5-=F=5x$qE$uSoC+ zbMw1BXMfQU>2=%N#zdrv)1%gpqIuWsa_&&luc1xJJMp&dTeG)KpAc`Gwi0{Wbkyp+ zZA5A56XD1{?c3~eQ+#ld+>}0Mq*j3U`@wtWtJ}C%9PKK7Zw-kS(*|8Lp@)4#i5zg} zR#;E%uaVDj+;9)AKlz{S#tnBe(W1KKs@O06z3d^o5lfZza~QFUy)GJ^bp==fj**-+ z^i4;tpa)IgL5vFNSsh6|%e-!S%|i3^AgHSIG^Bf(FAzCDd(GP!%h+gI8=-H-BcyY5 zySc~eA4I^=`={T6Ho!FAE-3a5`1A$vcVX=_H!2+nyH}pSq*}QkDzduLL_Yh#16Jj` zvYR)1c|aGK2edz@*Lq+$XZFCs!&aj^m7QN%{>OrWKxrw?d`_&U|E=fr&pIP>e}=1r zCr<{er)FmC_g;F;`sC7+r=0%?R#XJ>qx;)=m+y@(*AKhZmdJDQ!tRam!fILhtJD5&?PdC|8?1k*oYmX zGR-~wvbfLssd!;utyv>GBfPM?SGUn{PKCK+$Kj6cf;-kq&%CUMD|zl%>(0cRjEYN7 zTiK1D?WjFxfK*4($9yU9Cu#&*aPX#fOKbouG|?i(^KzL^A?yE z&-f`btul-+b;mcGzGn0_x_vy|Nj`%$JtjFi7yJhEj)!L*E}m1dqO&o|Lk z+h5pNP~dB#V|G_{i(jD3H4P29iv?v>R?&*;bLrEk-MzZ_h;o3Z8cKQ_xWia^HYkyV zcDBnMo^5G^Gd6xRtJa5Wax4i_odybpyd-J3tA6$@^L!R4nc>npVEPn?#g$J#NAbze z!B?eyJWtyni9}wW;NjE5z7P20aEI;EW2>7AeYy4p%ktwKhTpUPB(b!+ZYAm>ALM+| z)kV239bfIyQ9QasaXh-(7wge|4p|*~w*-_cb}4LuvRd_o6ca>qB*mo9J%KzLSG=r7 z36s&U*c+Vf)(4$KIo2~y!ST1OY90Ue*}+qt@bp@5Us2#dr)2ns&UtiV^khR4eZ7p* z2yS>dE^b(A9*JB@rNDGZU^H&H1n(2fuTqUTVC_>JFtcB@Z-8|r z!4oISYFfsci;9}ZtT!i;(w|&<()zolPo8l8rMj}Ry1J~)mDe-AgYcDQ!avdl*&(&* z4`%&>Wc7AKuOaCjYD_EJF+FEl@PF7)YPp;MXw6*>o=Z~JT*57S^@5$$umcIT~>sQV@x@T(B zGD|8l>JQJ&HeL)?^q%c|c}_=OL3-g+m!0?h7(b#D>0>8WHxqHd{q9UB<>=Rlrd&e= z<)jr$Iq4_mdO#&<5qp{sI^^@spov7trPiM2N9owjps3`!L{Q9FWKw`w1(S2!c;ge1 z)gxtNX-7@Lm7KdnuK0bysRqv%|G3p_e>f4XL-c+AsX*`ORLkgwj`o*@obl&shFE`? z-uRzihw{VLzc0@P^})XiwC6cr$C4iP)+1sIQZSbV85;7zSA%krm&7VOdY|XkrQnY4 zc!=|Cc6ExZM6eZbSK>U>tNI*sv4>5I+MPQj;(h4f)ltmH-fLQ#br$ZSr`Z*jjN6FH zI^I4e3i(^G$_ZfoaC$E9Ex(47-d_>8NdUk{8)nr@zbIb%G3-`+KEGu>y7Ck`+A-h3 zLxVO{9S{%wnYxku2oHVoSB;0>H@%uU#JQ7#b@HH#$D`gELG|yu`@{eRrg3MqC{&8(}AUebH>aBfAO zmD93+b8qISU6sWmNP8(2w%R)l^6t%zhiDS6Mb zqKWK?jV1PkxqBzRN?l=64N_lpnJL(^!6ns{hg%T21LPvYII zII_(=Lpj}qPgM_lxF#$J1uY5WgE78(X1f7RkJ~a~KXKc)afH$?=i-VSCn|kkAW&@k z^7494^>+8z!Cg6_DeJ7$pruuwfa!4pnnjW$;B)8g8?g=zz>jt!>1ptr+^Ga*h=i?l zc}$%v{vrD4w3jDY)S4D?UDS(27$HiHE3qmoaV0w*#T1dVgP=a6rNicV;uJh+ zjn%OK-D-`Odyk_s@94)e3)-4%GXupw%er$FQ~Bf#AMfhkHIBpX^U{zFka1n(NJM?c z54+(_%d#ziJ2O*#J61EZ>4%{XKJD5RE%1OIO8T}pdx-;yp1qS1vsYTNvse1nwv<-L zwmgK-l)gjw1jX=hwn{H&>j76DB*qE-3EqoG0`m;~-QwQWz3?P@B(Ga4UhupFeHYJ@ z=*QFBAvwewOyWA;dg^WJ;&O6%T?~}Ls8v))%?=nzpSQ5Cppj9Karmk1V3bCFBT6#< z;E1*UsSkzC(*!E{pCZDao=P?WQ0Qgh>lyHsr)M8XI&9^Fugt`d*k{L@W1sqj#6Go^ zIQFTdRu}tZHi%}I^MojUx()NU)3oSsVKpwISLxT&QH-xmo7Oa>h+ch(g&qX|8Qr6g z?=Y^Jhq%gE=xQgtoArO9BXz`i8wx7+ZJ4Y&{_&4nW6x!E&7+{=KuX6Su40n^Pft&D zO2Q*UCx6^!VxiX0S2L}h*Lv~Lb}t^vz2hWuqmCqB~D}H=_t#2Z8JSKSn3@p9_620)zts?Bac|k4`(;;@nWSfWvp~z-Jtcpp>=__ z@z&Py_F@!N{;8Gwba_chSy@R*`RbIx|B4NnZm6y}aiXHSW~8;Gq;=$*$DD5=A2n!l zQt6Mo3f<6vS+o~>@5i7Uh_mKi4^?bUjlSjU@$EOG7!i%G$0taXM$liXqUal$E74}2 zWTt*II7VCZ46v+-K*GufLL+ zd5=a<_x0^$4$J?Xxc$^^*6UYx0A-#+8q3&y`vWC4?UgK+i(9+ltV_>WuySW- zoxk<@cCN}b@QFiPB%g&C+Bx4n;8itH#XH)KCQ&)e*h5WKA`}$Qm7`Ud+y1b}@6tkN7$1!i}4L9l&aD%&3z0cjL?o!H3 zuf}5V#&wDiqphq@u^L>1X;B8$US>YDj%vZE4W_jL+#rICXfGYH8+}BVgmb8gf$gY@ zU2zx`*FK^<&DUJKzV?s2fcAeJd3;I&+BaS|SLVFSZeT$B{#7i0R+;mtHPfDtQZEwD z-chOH?8@4@+>>P0AFpNse9H;?7dUq$W|NZ?#IAveg96Y^V%i12VN6?}*O)fm4Zg`v zlzuh6p9hWrqu=>ah}CQyyGw>?yRvtkC^wTldX+RQmVAi zUm03?jtonPZZ|Fm4Q75TP0a z=e{^L1|CaEiH9pCr4>#|W>M+qv1$luDWjB@Vm*teE8KdP2zj{QBTOE79K zwk>9TbksZ!dE<($tBk{n3|Z62F*}bOv(W>+z57S2t^FJBx@*H-UrgvjvKm;+>K8rD zEj>Lg%{^Il6^o1I^{t!Qii+Ac`KsUhkhA%b2dobzlI<&t&Of;sXgq+Ha(>452G52e z65}ekz^sBEP$~_w*5mFwLfH3O(-+D=YchQy-(8F8%!3sFN>3#M!GRK?Lg99pc><4lACs5 z4Y_GLHas^?`?#}`+_c^JjDX7twGkM%)4sj*Vuxy5g+k6Q zmDRQHsPN^*&t+34z3BOD!m<}Lqb-tm=Um=pLK_Ub8P&ucNQ`uN*%&EpG`&k?Fssqi z>!f|0IXoloIUrcHuMd6Vg(8wnqOSwshMQ4c*axelc3^q9Q?!2hvOVT(%dwty@)rJZ zW$2jD@Y5IWKz!6%NDLZN>PRjN^$GL+n4R@GNH#P1B;RjKOupX^jFKF{9T*jgTWT+{ z@r?XS{Id=^m6@_TpkEa!62ivE%lFgwNWP!8xN8v~{)G8_qI4O9VXb~0#~2%P0M(!NC2p>g$pMVe@hd@Zm&*ebp1j~pz@J>$ec`b6=b>D{!>$}xLHo0|$Ue6w9Qi=c zSQ>gZM6H_jrjL74;TA@NLe=055kF041gi|xgL4w+Y{C5&w?{qltR|r6Y4JoQIUlhP zmUa5|I}`WK6S&o!ScJbnY~tq)2(mE|X7ZKGFcbyZYS|@_O}oo@?Xy3b~#h*MGBY&+p6p4bS%! zz7K=%C*9oY&7g(kdv1=&8*IQR$q=M(C!}k&cP;sz`V8mldh=dd8H{K%k6K4;LLYHk z%!tsw34A^gloB;dWFs%9SK&;Gn3q<_Zq#HKiM4iGD^1pTd7$=1VVLtT%jJV6Oxlf; z32Oh?W8O!WPYK07hPj~1(`|^AGCTW_;pw3mo-&>)JSFFqr+iX+U+i2^eQ)AiP#qP@ z9^7lbk)kho>aC93pKza)NCx8Ohk7%2CC0CmBPt@0SWPF&61BGo%eg;QzA{hrP|}=L z;PF*rrH9rWE7d2&`>ri|b{K&yzQ)WnX3bzPhif^PPDiaSR!Yp0KEd1%ML27pj&=z1N_k4H*ouqb_u|@Td~B%H zSd}>iu-sQ3Hr?y#w+T@@qi>zt*I@csRjJLi7y*!+(r(kIUM->?^fP%91+z-Ln438nZuQd; zm1zt6>^I!&RN+*(p`~ZSQfpG1tM1n#D0gpo<8~H7vA-r%zt{PjoUc2tJ7$&7f3|ev zw*9Pn(sH2XC0h05>d27*tDabUF3evzZ~fr;e?GJ|TYQ1@E-jg>dk__Qh#uqIl3d+` z5xKhBS}s>t?{mMSdz=}(Rq}0TKts*d)xMB7cDorDIalP_$hjhYoGZ-Vod@UW3wu%W zcfHB+qUG=kcV4V4-n%Xwx^OZ)k5_6saV{_(y*24(aF2Tlq9WB*HodU89=n^>W&-?W(HwEX@d+M@zTqzCY;L}@K66oy{4`*!JVgNxhR?koINz{<|; zD*WESyN?Be$^Oihs*GI^U+&xNuIE2iym9OHn$G^l=KHeSi-Wm29~e1Nl9HF5TM0L# z8=pMl&V_dD!;j!(Y@8SlS`tT@hqmA-iOW~5GGKZKAlp2_haOrT$rYVd3RwM0`{+d^ znvS(zw2$bgfJYl3D58(MbN#uEhFblrcVWG@X0WOFYEIU5EzMU;-ymn*o!N9aJD8DT zFI4Yu&8bMw99^w%>v(X}=B+hd-NAw2iSBbaazSzgOW&jtGz zecL}GXQlnm&WC5@sI>m`i-&9FsI-*KrJ>bw=JH@yuN;wfUE@%W9FdmS(%BchfPC}! zuZ|T`4?y-(n}A2y>z;Z?#JC_^cCLV>(EGHo3-G+e=Y${H3g?IRh4?XQo|1Y1IwDjL zV2c?+Ux#pPo9WwzPu^=PD`KzZPu8=x>Ov(B~Cf!Ah{&7hW$w`$F08gJ#?ycqTPIhfUuwX4Kki2zX2M z3#ua^#9u=t0d>~9G-fRU&JorU7SdL9h{?|2^(`d#oTJ_==6o;48Rl z>b;Pbo-}>TJqXnx(2@P1p41>1F(WlsPHLaaD!@6ytN=N=h6oEm4ijOav7#7+#qw58 zl;Hm6wF!jmFT6T|wfn;Kh11p-A_^2hUkJ`3RHL9T>9vscWYQ8p(OBZL_JAUoF=R;_^hQrf6%s7ruFFR#uAIkw+Ear^BPw|^y3ro7eTLfeKXChYGW zJ-Ot({1)q%i4t!A_@eWmece&~y^0IeS`H(w+^&^ULxxhJJ^l-$l;*N9{~@-ngY58G z`(zE23`46hk7-r(46E{B)vlJRTIqq56&Vb#^)Tb=TT+%$jc6H^$_*-m(xMC=1ZAal zFhT~UkC_L*S=|SrD7|q}6b;)k!i;mvF>9d0;9C;G+lE4Q+{{J(i2h`&(Y z%=%ahA`|-a7-CYN^z;LF@X@?!kI)a&B5#g^H_|#D!5ir#Z}QCu^>e{T0Ld170MW|& z2F9H8aYwWKSX(wSmy2}+qkK?;vB@gFs#TAwd-+OdU1ZI=FvdaL!1o9N zZ2iyyn;1`dQ!f3jjX7a_Jn?RGunTfv?O`m{Uc1U2PrB66CaytaRu~YpI8)mKZXP6} zSf2i;Q742Nk}Vw>f*dC^8qqk6rb>=KVQY7n`-rila42##4#h#&Ps96xKKj`GAZQdyZ;=-F195Gn#h9B|Y68^)l+ArY zZtw;AS$di4b&Ga#=F^FeBeM~eq5!)l8kM2|v#I#zK8&u6N}+yLG%AHq_uw+=SY!uW zts1hx!Ka8I@eGhEmVS{i+t8r>lN4k)mFMdk3^99RM`l#^`%TZb?zn1@iK?*5jYsGd7}Zl{QneT4bwG^MadPbA=B3$bf4C&M6Cq^0J_R8G zgbZVHG8srlDq;a38O9#62=2}Ca566FdvoeY8P{Cru+s&x;#^oW5cwc|N%abcN8usTVxJR~eWdWL;_mK#B0(Xj>u z4M&AcB21EkX#C$38brhRXPa+mN0$6u!LRFwSBJRi#INIRfVg!Y`{vABVKyiiiCZTl z3b#&L^kxt0w|J*^5bWd$g~qsb+7x*RIKsV-@N3q*Z6N(Bb;^2LY{XBt2k=g9hs%Nm`6O z;{K77O8V4EB`xQqYS(X3gQXWno}h(-`(xWmXGUCW9h|OqgkE}vCnm@#RiD+@h88zB zzdSqBaF?37-k#!r5593xLiD~D_Mkj*@3V|wB{ZMDHL!8Zj>g*N;x_-?xt)P>pZDGk z3jt4lUVfF?fd!|nbk2RVz1~B(`_J3?>s)W{p4jznk6LeOalL0TkF?11&U#B9*SktT zLA-5+KCn&qGEQ}iE!nx!!v9fLIlY=mWBO7xp}snWh`xJMwyi$(upQIa+!BuIYi>yp z)Ay5v23VdMJ8bNXB4o3U+GspPNrCA^t-b^Vllw9Z{wGSaZ5pw^S@Pz74b(x2eLDSLjoMPqfwHd|0>935XZ-0Admlt%QSG+zkLcI^pFpExbu5KswG;G` z498@+RPaKAHoJv3bQH$OorvJdR1b6-L)^(xs_sutE_er%0ac}Z) zEhJ)c6sxzVa77gqtH#O6BtTZFTvA_m5?2i;u19dJM(kMG|9K=U+PM|V6?02d!?Y6o zE9Rjti^YsXu()c2ZGMbJxEe}ne?@^@rMQ`BCyvCp8ntV;(og#PM7iQEMd4ZTmO{KM zL21gh&ozb8BrOM}iP%`-yGcy#r#NR%-2K4iU50=4niM!67F-7cD;4&(O|udAKZS!e zZl5e%;Xf1-7IUH%;uUkEoz)f;EVbGzV`2#^88w0BF`RK$J}zVPq_<6F4no#vlCw1s zvi^R2JPIT$70w1omho)fC+Po-#mU-hQ{Z=plywaVdAB&)6D__e{v}~dzHde);XgxkY9t)(kZMQYGV$#U8Dk)pIM3O#W>Z8x+@e*{u|@Q%F4|0 ziTC)hr-Hs$4!mTyw+ztcZsY1b_gsDPy+-Sctq;G`XuZQ|+4b(7$SyoKcO|dS@6Yqy zGjOyaJu@e-zW19KuPxnho%P1w;ve&=260bgovCuf32$`Wij`q3GXHKj+LFcR#$RgS zF9kY1{({UW@Q=^na~VE!pV#SUomJ`6eZ(vq)U83ZMs$nFHS0wJ@UM-VS=9hAgrtjQ zoPV3qxH)vU|BnkY{l$IWqk~6s%d&5^zMXX8PF%FUv+>S}+Pb0PTfJRH{>;MXZtc%7 zGmK9qT19*94!fU=wF^Q!o^ibqYd3>+kvdT`N$NzY@nm(P827H8bt1R7>Ar1PP2v&P z+C01mt%JIyGTCetvM}0J%8`C4t@*!=&G}yOU$sS^jLMP=QWNSx!@)jpMMhS7R_B7$ zgc?#cp{%*2v^dgwGKiW`)nm2cnouX|2a7z}xdpy-U%->z(`9&npld=IcO)c`EvE;O zn|_DA_d8%GB?9e?>pP$n@gCZ+TIuL*TekmIANN6neu6Ti1{_aRvwGcIk5;E{b)wa$ zTMo{^I^DMpvoL>LVo%m%zV&!#lOErM)^^<@Zuc(TA~H-{SYngX>UYvd+JOCd5VIXb zMnod%VyqkBW-4w_g^a_}#t7Ga5}Y7}rZh|8C$~Qo>|fW?ke)~c8INY94;hba@Uq&I zF->`7`B?PHU*=9LD9CT==<@f3!d0L8`+IYGR+drLXY+p1eUFS>L~)fkLLFH0_}{@a|eCcVaER_@UcB;65Vz_K$5Sv}3Q6LA?l ztN>AIC~Y&*BT=YMmT{Txqx`PbElRH`-BL(YxIu!m>M`FGxJ;swA?d)0 z%+!>6WV9xzvyNFk>N|tnj5uyi;BY8&G_w%FVoTktaCa121g@ZL1g1%4sk7@Q01T59M{AYzY@~8XezUvtV9N z#uYfSlhqSb({&f>Dw=mRo-gS3m*n~G?A>3BQ`B4kE4zYInkTw`)0Mxvc&|W_K|kLK z4054I8}Qe5Aj|mYpa>(TxW6;eBUa!@il{zPq(?tNJ{GBicd<%>Ixe3TReI2`u;bhG zo0M-Iy48VsdO$H^Bt%ve*o4052=Y<=&M0QstXo7#*``~LZIu#<_93YpvJX^@kAD+E z#ne!%6h&=}vLqBWZ@T=?-EEgAmj3GiNvFp3jR&*~@^dN<`PA)+M90 z%NT!FOYros+fhQoEXntmd%V81w7zcRk3e66s)9~Q`aa*@Z$pS-oVWMeJXVZ>;*$ub@pObwE`VV3qYS-I7r3CY0J@;iV`-8Jj1AR|9u= z^NO=eOG`3#^lm{(fn1Lm-Y-#pDVAn|t*_hH(K$ZxC;5E^8K?o2bJO-aqyckN7sW%)QaRR?yP^Bh7 zJOE( z_<#|5Ft=wfiu452+pX&opS0$ar1C>uU9k~J?;1M(Z{4~~&-Dq8+YSoeFxJ#g=<`>? z`*j+p4$+3G&+i6xcs^yKZ}T$QtNLWmsuuU`e*HY-&uIy9_UwM_vE_Sq-7Ge=|NWCy#-J1)Gc~rh$xM}0kcyoKkV9oZ(jgKS<7`ff=dLcmP_d6VMI2v zlsZmfymv=9%aUy3V{d({QT^t;*3ID}JQrAmXP-A{ymiQXc>jSJV?7C66b&hr=#>5W z^5Q!~wdKc;m)A}nI%M1hVn@MA(S9@Uei3NijC|?s(4<(Ef~c;7f3!Uc|46ms;UB>^ ziZxZJM>{c>*f+TPb@rNbT=2!H>8o+2>65mqkDAe>ZcU=KRkyZcKFOaZ_L2BqQo}w< zes>6?9+~;|T@^W3123{`?*xi7cJ^*#?VX<;yE1#(v^FHYR#>yMD8AD;Ikly&u4ZiP zb{>#fW>(JiTS7P>S$(Jc=uzvjG~=Z!T|9ianLYK515>QJ!~55~``MsTC)Q!FU1yir zPrN^Q(XO|5B%_l&;Ar}n>#@?+_*@UhJf}AxKpq#-M@S4?y_@$=n1^MAlF~q<2_kE(VCTIpjxZ<$i{{I zYJA?GbjcSt-L<)~sekZT@A-B3@4zj@=J6C>uH8_XnPzz0{+o9UW~Jxk)ETc_Y0YWA z!*$ozTg3KM154U8IPW3s3F1hTWtbuv%na!C9LiKh=IO0u%jv8MNh3+a6S(7Pt2kj|wu zhbpZ5%?cLMSsF^^h)MzOr9R0aWh1?CFNnR_im8sB^>o2`2|h!d7xjKFD3NVb zq8Q&H=tsrqW94L4JyLy5phJglb)eO&TPh-BnO89t+n@O%)XVu+n$g61IfLfzt4ps* zx&r{}a^5gJedn#WCNZwsHl3aDA=0Lkk9fBMyOsm%&58$cAP$y`>Wh!%qDD)xN+tFx zwP9BA1@flcqgy>_t_Sx> z;~hyDPGkXXU)$_;qK$LV_2=L?+Bd}$7>bM6A~${|jal(i@+U=;^kP3#l9XUR@!yqT z75w(9HS0cBs-xvodHBTgDJ`Yd%6zJJh!Z2PkXlkW@u-1rKH<5v^un9c&fl4o$*dRN zci(5v+%DyBZa;G(kt}`coA=nZnjP*btY0B4w~VCSW}{WoPAix!>k?qHs4+)cj)HeY zTC$dECsvX+;h^s2y{=!kh>015mN101#XTOMh)c=%5)~um25ppOY?+U4IR;Av3pVwK zeAM}3VML8hC~OHTq{?-`$d3SSjPfv4mH~exZPwE0U z#-Al%(_h?cO}_76@7C3c0?xgfY)Jt3UJD-vvr07 z@Es$%S@l?H4AjCiRFX_vF`pWU+M#~lJ z{SO#jcNp90uQTop&NgJ`lvZUo9zHVLjH2(sv%wdj=zCF?-}u4Oum9=dXFW?lH+@S- zue09sBmCpp&)CYV;8#{?+k{h=m^HNZiq~#DWv^WaEJUIK6FXIGOygJ$b(+&^E91&) zD=lTUWz9+T#02l1Tm!9ph4Cb8HLD>};9gPWVxE7%=-xbfcj2qWi+6tTG`)CrDJ<*a zMeBQ`w@frO5A@z5ZoEI5UJo~(S)1Ati!ALz4A@Jtwyg4b7-8V|VQpuzwo=JvHc2HL zHJ-eZ%>*oQQlW;}hJw2^i?x^gJh8;p_&)IOjBYW9j`_!|=Bl2U!`j0b7xwTi^Cu6= zbjv@h%{LtE4g2_xiH~oC^6`B*1xg)hJ=zW@ z-};fAxg90`yu!uW!NN!%-_!r-xcI)6GVvTNk1E{Vm{~&Wz%e^3oq7Xxp8}lf9Z_3vzRTg;PX?H9%x!G8Y){$YGd zk58esN4Mz9-LG4$V#Vww+6JxxiAH_H0{UqIR+fTv!@xMs zzYJw3=)lB@rQ3M^dgGCij7)j}9}7#mi*y0Dr!VsWmRD4imsg~h1`^3X>+6-JhYsbI zdpGXh?cQePd!g|6To2YYl^6)m?(%miW)8l zh$EFFDlf8%j2US^>I}hxu$D!Xl+jaqm zzCYXlrqk9%_gz-sCobOWvD%EUMq+Jv5Q`wU{k^WQfS*|th`s<9R?3C7NyF+$g`+gI zN_5N7-J5iuV2deyj26tm`bKG3_f~vv#pfo_u*0Sys~Iul2z3B4Ceb|Vn~0FK1#gKj zf^iILL}Z(4DNi!(WU7xiA>DXa&ODr9Ye&&A9Kw~^CbE!uBXKl-o{(7Ifd{JlJ$dCj z!~TiFo`K=Y1>=W8y{X(c2!6(fmC5ymc=#FaA%}ia)QItdf}@cQF9ofbyK##D8Z@Lw zn6{E`_*KX39Y^Frp(sYMIwsbf=*s-8b{$tO1O2?=?bUDYg>H}qIuR>U&F0)o+I1gu zaJoU$PMfCf_|$8EVr_Y%58}MT+yj_YF+BxhFMUecTPww;a3?f#>%b`p5!zXnFnh5RIJg;l9eyupe zC1#6zO(ZDunN%-xXBu^jnhEQ^)Aq*m{t;M~_=#R(@#pt~F1>hXTEC+ZnDL!@?XRJp zhWds>czRy9=D|C&nDZJko7EFXMXwC!o7tLyf~IY5X&!`g3Dk&9b4U14Mp(6s8!Z}1 zJF{xT;MLrm+w=4MS*2xx%ORUkv3GOts3&O`6;DAO=vRklHiK66 z_{> z6(#o{^W;z-X8LMa#YjBJVzX1#=Ny||LT_@5m`jrGd7_>q#I*QmLhexee7vtO)}j3F z!Q(&g(GKPJtjrye8(aL!f@kq6dv6b5NAl)4<2q^I9mxkg;|j1^;#pQUDcYe_AMFD( zx}|REPPEnxR#)xo8tmdGdl!e6?dM)S2c`LlZmBqFXx!MxjM0vzwfr^}DYX0rWR7>KTxNJoyz_tb?sprl_vf|l4ttuPLr?Qj?>ggc zLm8Qe4jw%8O4<46tzR2i50#bL|0_!*2mWTct9iJ#^7wIYm2Yxp#yxILy@z`CsPU<# zhfiAHFR!U7$3L-8&b#jhKeXU}z65c3RdD_7Fo{7 zEA+CH?d~C<+^JLti$9JH$SGTBTGun~#RWmT^ zMtPlKe~Yz&QZzziatg$xY6p1FmR&K$Va`A6CYzd(LcY*_ zCe+j%8hnnFg?VoCc$r-n<~gmC(AroR=4Xi(-myoAZ7h=8%xrREDsYF;2Q8IhrV~_# zxd!Wi8qdb+7U`DqL5oMzxxMu2CzPE9-vw%kG!)OXyu;fRJTtiP=*v%9Rk zDC52Kt|2 z)PQ>5i5jTEtyFeM4dhvsefBV>R8X^Mk5J>?pi4-%l>h7+&MWoA0QOUCjTj+I{FKdz z4P?gVBwLqL*e~nz%?pSl=(&Jhma=yzGACL5124xKuRWrm7Aqjp1GQMeYI_BF=Zf?b z$hh(oNGsY;Abo?BNHMv`iEx1;A+a-E3c-EtJRcN^lC~UZIUJ^Ava;H zEN-BY^>1{bOgIFR=&DKl8cNB==L_d>K~H$tf-h$03YE z9=;7cO21J)R@j5JR0u7q!kV%IHtI3u1DCay+8Ery>fI1#8qzJLc`|oiJt5V-RBIg6 z9J8rO+!l#ycVl&TJVEOvc7B9cNf297HUBKD3o})C(L8rLGrM-f{$Oz5hFW(@tn9Zw zZjAr7ueGhOudTJu+faVuL|%=reXOmxxNXe%r-c0N=>LCn0%^mQl?@GLWiD{9is5R7 zBxF`Bt#n;Bm$$mQY+aHTcN5kaX_;twb&GK$<+@dl6)d$^kSIiqG$mS^dQ+jLF_uR4 zb>a}ZC0Q5;916j#zj~=ECOtSmB4p;qKmOxCzIxRPng_1_ z=+(tB$-&twRA%3vp)=1}I(O0fOYo%=&&IV_XXm;8&#Xpd)eGf|09C+?A@HK@YfE{x zB7!zjTC<4k>ZA+juAMa)H)jF;{#fEyYLDQhX$>mH0?Tqxnes z6dxhN1*;_98}TGeV8y~Q8>#V^9p(~yu?Yuvq{4JocijB!q>K6N6|%GKJt{G7LmjKt^~>3p8ls^nE32?>X#8I+?9#4x8P8k>NokRnKItTXC)-a; zU%l``@1+H-gIni!w}a<)*xrA7ap{S5K~tEFSS8isD&^@h-Xkk?OW9SZCqIIy0`g_6 z9(AJpJ9QspShwkx^75+N4y7BU9r(Bhzlt@f7%`3Chfjj6JA|7bfRs3)1HE~nGji0>E zD80jIx|rWs5Sj9w6%pdPeJFV5^wRU#c1Uq#kNFI zOj?R!(oz(Y)=CtUQAII{#pu9VGd8J5e-C9@P`8+kz)bL+HjUQdX~sJ9tm?<-=!oPk zcupdcm8EU7o@X=OVwTz-ytN1ND`g70?Ld#FcyxrNw70>*kLdSoaH$qES;w75q zjOV66$EW_t4)S<9cq%s2wCwRu!w>ZpD>VX}WZ^8AzUU@I?C zx_>c)I4E}|&%Yfu6$Sg|hKP;X1XzDN)L+%P{ckclem!GeRX-_|h;v>px+IP2t6Snd% z!)G~p#T(4s{X5`=Wk><3azI=O?mz{ku$@WtSP`zl0yK>UC*XkVun_=_4`3xE#^b=M zQ3BK(IoMZz@Qh^VCq@ZSPo;_y(5B~QhFXVi@pK>1E#8zi>z4AZNW3`DcxDr*Z{7#a z+G9&{#(PLao>)r{gEJ2E7NV`C3FAF@SxHGNo zUqqq*%t+^{E%Q4Xy4vM?@vg*tFkV;3e56Xo<A#RaK6EDu10A1FhH{Gj>(8KZK=@HVCoQG1_NTw}>1e zk+_Wd6`d^lB;Ti><&NHN?`WR%%G#uGBvxZpSQa!w^Imk!NQ=aRfT+pM%+^07!YH^E z_ybAJ2oEI(DCiIb0X}N|~N7zUVuzE_1y!5hx6WiKfo|p4~o=X>9?;Y1+4Ag`d>wylcZ+lok6VheCBf8Q3l4y>ox-iTF3 zU#i?^lzm35{EXaD&y8T+H|v%<`Bt&|?&ZrKiD#b*o0qTK@xjuZ?Cge;r}jOtr?k|K z5Rl-7)ARM#J57H{X?jjlGtUe9dx9CA73C#a7n+B>o}yfDReF9~_qy^6MHMx+ZYp-} zb~|t2bK$d!cniBB?}zQPijir?6ZnT-Q};4&fDvVR7*QvdJipS3C8N%X)vf1ZUcxZu z5*vY7%BY2?UqJ4lbw_5{h}N`jO=G8Rwq?|AoI=z|R-tRsohW;wrHP)~mS)>9gmWfX zZKSvGyh+VeP?r=b;)RUsNJZD2@;4V1N$khY+BU|1l)1C&nws)YfMm}*1tr4XLxKa* ziW@lb82=D^h%!m`5G%zin?W1srgEH#*4Jm#LRk^|Fsh;!`t|#)5ydlTRlBLd)6xVd zME@$Bkufk5$#%&2>xeM;%V zlsa+}@J<8zK0zAG=Mj7!S&i?cNMCORf`aH-DV?<03WDNa@4GJ#wX6@1~mF>#B9W`qoEvd^QlAxC; ze+R?m#Od2YsC{1pGKGD{Sm&iN8)@R;SbNrA8|^@v@J`Om&(Gg-%XF3CO&EPvgL(4m z)mx0)`ey2*P$tft-+f^0%neJwes#HkO+0+jdawIsgqol{aO$VD;n%aiAW@7cTj|3o z05=USTP4*Oxk{?fS*7-<+Mo+xXc@KhY0Fpk{%QRSrdPp_8T7ct4+^mtIfaGoj|=!={3I2o zy>A7`56#GKSKHH<+|2Fjgr>UQ^)hfVPmV5o%?HD=Th5x7f$t=qi%5}Gx>W@ptbjDY z+gP)jC-4vBwR*f3bCyARiYGOw`{`-xLO=PJQFm(gp}1>IJ$KorH=A3GIus*ict;)5 z=zPXt$AyjIo!^%AF{24PKeN5zn7#G)H{|CO<&>5dXBeMf`nScqyvEmkw-`5sX6t18 zA3eE9kePMQ8ajM*?92<6?)=YM?EmaMcY3zP%I;N~;X2J$!By14?1N~&yrVl^Nt#!M>QZ@o2j92NI=TePQxrUz`? z>Nd#qQQP`?$}m7##+XuXF2F7kJvNfEsxOkVs?VV;bIBaas&S#LYDLG|s9yS~8GkC@ z%=pudxDPSq`vMRyu>MoEL^q^(Y9H-ATby zs!X7#aNnPGABW6rgWMW+sVI5kmJvTExa{OteUaRu`W)_{J;&h=HBRp6(6bVUN@D7W ziAGd{Ymk}hSw_jHx|1^^E>WrO(Z6s&SIh&c?7;mt?25a~-dk?u-l&>q+*|jCcNOoS zjNEqF>&CjKS-O>lzgG}bSP3)7=5QB2iRM|WpHngMjN(u;1@W%b1nkm%&N{BvDbVFJE5O|tPrns_Hg{Yx z-kg+HUyKiT!&Wd~k?|Xf^Mf3z>qKMaBEY0jeY!u#Pd=#StrDl(V%ODvhM1oec zG9r)2C-NOcKH*LjKdY8rNvT@2a)1=k6|nijC^tqbq(z9-=+gCZv2M)QT$##Efwa~- ziIR#7cQZ=b3eXKUDrqcOH*Mg3X420ZIiN8!ly}%P-s9S_jK-=jlE$jfp)sQ%92%=} z?$q`0+sUldWQ5xIK0L4Np8TwKD`_Ip@T{Vw-aLq1O^YY3+NzJ)P3uAVA$zwoidQ0l zci@v)O(c?D@D}73kduk6Ag#TafnL1XCx|4NIuE2)A_Zc&$PSlFi4%-Tfyr6=VL0F> z3J3?x01TWIxM4`a2_ zbNJvm*3;nwHBLU*uV-b{wX$k&(Y=hn+^t*mn(PN91^1s?Cb1PI()+OeX&zLY$2%wV zJ115_L)<4;kDg&!&k>_?y5OXwgPRa-PSCir9 zq@}_ENsx116G?Bu%wYu0yio&s|8I|`8rD%z3NeQ$4=OUsshBja`y9XJ0Z?3G=NM(9 z-r?Qzpl*>58C4~bR1#Gs@&i6J?RH2QRRx_mBfZ;5svy|vH$4}}x-y2X*P=8_Xk?;h z@nat|Mz7`e%%e0*e|p!aQc(M#jwglEc~?@+PqcJZqoorz24d;70qM@>4%b=R#z6jH zgjE4nZ0|C8p!y=^f$DSQ0qNjKel;$-x@u8ZpV!|p4>>Sv%W@?L<}rto1CFjv^tOJE;Aqfog)m!@D>=khmT5a_mdh=3sA1WTyB-#@wPgyY#OqxM)6nOOEwd-Zv~f zZQW~@C-u^ZPvNQWzT~pk_R&Z_ejBvbL7Z0f(eS3i*unzva%apQtJ8gvmKyb(W2xau z=U8ggxL9gbixE0XgC5rNQm)eXEeQAW{mds}v^p~lwDubT46%ZzE99%gB`8!}#{wuUN^fT>tEpPdjm%9y^z zdIY#oDUix~V+z<&&`C+iFfx?*G3MRp!n)~J+Xuu|9kVGp6^{Fhq@?PLq@?O|C>iT_ zljuNFk~w zz1_vX427cv&DX`Zb8d!n$TBYHh;!I_XYuIt&ZfGS_STo?b_U9Q-oM;%wAhoMmtXDP zx%4;Ykn$JJxo@`D`4F;PnaN4}J8xVC&=Dn5EpnYzU*tNgK4+a73GGNDHO_TrWo((1 z*}2Nvd06){nmtw7jWST`rWWhZv^PK`dRMYVSN`{3BuDQuKN5faqn-2CU!)A+<(`Z5 z;qM6BOC{!n-cNc{7&%w~4~s;EL{dccMN&ldITRu0w?h#%PKxyCS(yhaemh1Ds<;wn z9qw3_Jjz(N(F_HvO%+pOue}1LZ>UdCB!3k1@2uZ6H#9WAslI;G{Ls+crh3!7#j-~F zf+HirzLB_cCz}6%-L)lDQ4!kG)wPxX-Rkx({a>?jsiv#5v#YD4Lu8C#p|#<5AedX* zu>#^z+aAZGrurgRTJ^mJPE^RQ;t)4Z88+K;#79YI}@R(nJ;$sg~CV^TJ5v5`baH_ZP~so zwxu3xBe5uvcN5j;+)YR==We3Lc{gD#L7Ab8--GAGs;r_1`}H{UHAyXbT2V_{(bSSY zT2%Mx=T&x(reN}mB&6HQ!L_#T1>aC=#>H19g;%S*Vk4)eU}CiXGZDI)`6%rWf}Iu_ z&&AlqPeID@JdnLN9B1#TzR10&`kcKt9JTkV`>7b%_C0_sk$h z)d@9#lS_8v0CYIsIcdLEed|}T|BUpgfZLQeTpxmNKbvN3WbL+U^IU2nV%8@e*tKwk zO{~vTp;hIAD-HZjx%Lgjz+WkO7W9KkU%VP^^moc=w7*mOqWzuHx3a%e#+AQQTJ(3O zhO!nJh2!`;W0BT|Q?svVsI_mUXh)Izhq~L*mptxz1YAwe26afrXb7G~w*O3;hA_EALn*J}X=YdX?ojF;|@<<4^Fmq$N@E8=tn2 zNnoyh(!<1+=!93AmhsS8&y7o$Z%(`3yyF(@$8Udo+(SKDsoLt`w3$I34g$kw`>%Gm z588SxSAGie^+QQCr+TgTM4k{zGjdJ{uAXy3sBxYUk(!f=fl&ABF+KYjo}AJxbsmU@ zwaune7rsI6f_mkXo&oNNs1}Lb<=QVpXG_Jjv_A&H&GcT0hG&Z}`lBpK)+eGN+}tg; z?I;qUEe&yfr`?y$uOT{Ds>gj26siR0QQL95D#O*|+-PO%RyO2Nnk{W}bYBkM$;O&_ z!L5v8_v;ZqMu@0fZog5l`$^$OyRSv}v35!$W@*JNt(YaGM-*PBlZz3;bLz~XrA1B% zp;qKc48UNUayWj2%&nxUuOIf1$a-_;m;575kNCZ~p%+`f*!$qV!VV+MS138V}Fhb#Muf@UUO%# z{6cB5H(>2Mb?K7zpVwJ`^Em$5v4CyxrDz{B&I@M<$si>tlCmh)=0r4_x}(id;F zWh8pFoAjJbSZzjCvL21{@(9+2NFMpT9_!8;b))*dQM^b0Eb9lU-!}m&Ir)^yS9~SN zvzFopJ7fmLNPz&>*$){**?Oh6D5J+ zfunhSMgBD3vGLa20*`Ssh!m#H;V^9u!rJpsVcO91M%svvOwmSK(X^4ic(jp`Xxg;u zIaNlC_`{qC7xkTtaA^hA1kapLsZ7;fpw}+^zC(JhL!cKuuC&~%_vi8cVZ46?Pag@N zB#CxN3NUH*9X|plZ8dcKv4Exd(=)0{E=nQ1!}a@BA-n}Cgg2xL;Ta!EmB2NvN1IR% zuY7&=4ylKCw00n>9^QX_*{O#&ViP?b^6!9_e?xXO)PhkIraUw8NO{QvQJ}p`7@0xez3`9xqWKhfMoU#Ed4++UKvXLU1y%7dT0ln)CST}!crZPru=kblwI;LI z8IKI*EF3(z_`%Gqo=^$WL<35Ev-%_53D1Lkj-x@^&dW5 zR5re4ixK!@Ms~XC_aW;y&*$-UcQ1_|`e~rBFi=`hD0aCv#B+-5W*y}R!dybzB)OzL zN_I;tnoFcF9+${SG?z5!IUBI2rOpNKLlUdlqeqFK$UH>aD%7u72TIbKEjgwsNN6X@ zv$=m2dwJ$Dv8cnfP^70T}{%(zK0S zSV3O2SGFQ*|EX5w%BsHDl`TT9fpBmUW~;#3mD%f5r~B*h4V!gKy-LOv ziq8ubNbr7(y{ouKq;8blQ>mw@Zz3x2ux``lqf7RkPxPSL8% za_9*7z_F(^#q2ba2J?%7;fBAe$j{7dDzW~3_X9I68EHOW@cb$0G7p;GlB%Wmh9TQd zgzL41UOcv7elJYDpD|9+ytTO1U+ZbCsVdGmT-%+KR_7~A%c*JVDmxP>u2}j^^QnKS z&h@03zCwS6$6M@4UohrQ9XRld)7Fc*S3IEUEcOa%O2ns~uKh+E_6w;>&yO3cA>I{{ zs;U)DRe2&FRb?cas=azn%E?+#kTHw&|J36%>p=0dqAb0cE$DB-ui35N+zooMelP8U z>Nj=bP3BTc9z|ljDD@7rwx{$AykBgwXWg#*XeT3ni1?!fQ)oYakE#?Ec|J#Tfjbot zFtvx>c1&ARj@XwF2JBzLobjCrZ(_c%_F8wc?py20*0vKrs$+4m;(ULZ$LmW=>+3cS zfhuQN@po2&TM=$<;?QiPaTR>S>%b-1YWy&Vq--dEu**P^% z4Y_V3DTSBb`QU>_*ZXo>wy+9ZT2Vo8F}P?x8K$gtyt1t#@2c-MRY7iB*=QYV(&Ty) z6MX5@9mjvzAVuI%M%JziXUvk!!OG!@T|GU$<3qQo0&=Gt2U$QarX5&Ut&;{WLR0|OGbr?kc*W0kRzb7+@6@JrZDqGx-0)po#q6_J}C|)!VrBqB8P-4 z8Be(bPe)oH*1$JS!0V5!9yb`i`X=X=cZH*zC&DL0=JxDGTwExleJP2a z@k%9Ke%jUbwWDv!%RAPX;YrWVL^1irH+C$3tKKd$mtF9tqsBWDsT}GR6AW%*>GSXB#rJ4)57BV?Fq` zw;9!M$=kKnA28GF`!22T>M?&AW|)`!^r!DADK0MIza$6Hfx;^9{JgiSaPyu$549ir zZnYP8IB#o~x5$&$*<~xGUprt~<&~A?WtElGO?mdr+xIwDaVARHFTg*vX|bZV2m7(u zmN|@`E7Yw*P(IU^JH=StGORA8g$JLN9eSUBmfk~&nd7*eE7$BOPMKLyuGIJR;%VL{ zuHhD^`WU%H4OP6G^lGUQ`YveyA<8UcDOEpXDT!Xj+r8>zPSHg8UGHuI);21XiL)$TXPuAIDVKAF0G^%o~m z+ivS!TMCQTkD~ajRJOZRKUx;9Y?lUE@b_uv*OQoDkI?k`;$34bYX_;&2Fw7tyYIz* zV1ys7+`li|9_`j*^9$iy+OYnl`99rC4mn^`Yex4m#)nb4hw-$ExQP_fvCFTNL4*!C zF*nh<)=r^3wQEzbwJg1^Ay}7xcXsBp+FI|<%XxVL>alkhoUYy__3{?0_jGxyvU1#I zN(V?{1YfGG*f=>^TV4_93Y_aX-CJH!7A$|B6wZ5I^Mn-6yWBQiO5L#0*g?Y_=_P)N zeC�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

B?Ux}mH`OI{S?@|r&1~7$S3GC#k1Q#l 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 z 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%0A?=jB%=EW)9Ch2BDbAuVnfLl1uw`Xs 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%0A}?S6}wt>RdBDsD4+6 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ʼnF6 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 z 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%0DTp?I?!Ko7e4AS-NGKGklr~-@1N8hqXNayN%3L6 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
BWYP15x>ZPT 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

1nuAU=5Z6c*>!8}# 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 z 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

_bME9xZoK}_anO0R8y~HyvUhZD-i1snpp8-76 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

-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 z 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 z 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

T468?m3(oeB{8+$w2l{F^5F` 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�`whOLN(h9m~5x* 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

6x0vzN`>D2&oRL~Tl$RGv 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 eLQ->`B5@Twr$8(zpahT%;Z#t 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

1oJAg-30r4CdlqBGAT)yG)F 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