Table of Contents

WeChat mini program Mega 플러그인 예제 프로젝트 설명

이 글은 예제 프로젝트에서 보여주는 각 기능의 사용 방법, 구현 방식 및 주의 사항을 상세히 설명합니다.

시작하기 전에

How to display models at annotation positions

  1. 유니티 에디터에서 정확히 배치하고 업로드하여 어노테이션 기록, 어노테이션 이름과 ID 기록

    Unity 어노테이션 위치

  2. Gltf 모델 리소스 추가

    miniprogram/components/sample-easyar-mega/index.tssampleAssets에 모델 리소스를 추가합니다.

    const sampleAssets = {
        your_model_name: {
            assetId: "your_model_asset_id",
            type: "gltf",
            src: "url/model.glb",
            options: {}
        }
    }
    
  3. 추가된 모델 리소스 로드

    miniprogram/components/sample-easyar-mega/index.tsloadAsset() 함수에서 모델을 로드합니다.

    async loadAsset() {
        try {
            await scene.assets.loadAsset(sampleAssets.your_model_name);
        } catch (err) {
            console.error(`Failed to load assets: ${err.message}`);
        }
    }
    
  4. 교체할 어노테이션 구성

    miniprogram/components/sample-data/annotation-metadata.ts에서 교체할 어노테이션을 구성합니다. 여러 개를 교체하려면 쉼표로 구분합니다.

    export const AnnotationMetaData: Record<string, any> = {
        "aaaaaaaa-bbbb-cccc-dddd-123456789012": {
            assetId: "panda",
            scale: "0.5 0.5 0.5"
        },
        "aaaaaaaa-bbbb-cccc-dddd-123456789013": {
            assetId: "your_model_asset_id",
            scale: "1 1 1"
        }
    };
    
  5. 어노테이션 교체 및 모델 로드

    EMA 로드 콜백에서 xr-frame의 "팩토리 메서드" scene.createElement(xrFrameSystem.XRGLTF, options)를 사용해 모델 노드를 생성합니다.

    • 파라미터:
      • xrFrameSystem.XRGLTF: 생성할 요소 유형을 Gltf 모델로 지정.
      • options: 초기화 구성 항목, 컴포넌트 속성에 대응.
    • 코드 내 주요 속성:
      • "model": 필수, 로드된 리소스 ID(asset-id) 지정.
      • "anim-autoplay": 선택, 로드 후 자동 재생할 애니메이션 이름.
      • "scale": 선택, assetInfo.scale 또는 "1 1 1".
      • name: 필수, 어노테이션 이름.
    주의

    속성 Key의 문자열/비문자열 구분에 주의. 예시와 동일하게 작성.

    모델을 어노테이션 노드 아래에 마운트 xrNode.addChild(child).

    Gltf 모델이 플랫폼별 로더에서 동일한 결과를 보장하려면, 로드 후 모델을 로컬 Y축 기준으로 180도 회전시켜야 합니다.

    if (assetInfo && assetInfo.assetId && assetInfo.assetId.trim().length > 0) {
        model = scene.createElement(
            xrFrameSystem.XRGLTF,
            {
                /** 앞 단계의 assetId */
                "model": assetInfo.assetId,
                /** 모델 애니메이션 재생 지정 가능 */
                "anim-autoplay": assetInfo.animation ? assetInfo.animation : "",
                "scale": assetInfo.scale ? assetInfo.scale : "1 1 1",
                name: emaName
            }
        );
        xrNode.addChild(model);
        /**
         * Gltf 로더 동작 차이로 인해, xr-frame 상의 모델 방향이 Unity 렌더 결과와 완전히 일치하도록
         * 로드된 모델을 로컬 Y축 기준 180도 회전
         */
        let modelTransform = model.getComponent(xrFrameSystem.Transform);
        let currentRotation = modelTransform.quaternion.clone();
        let targetRotation = currentRotation.multiply(new xrFrameSystem.Quaternion().setValue(0, 1, 0, 0));
        modelTransform.quaternion.set(targetRotation);
    }
    
  6. 실기기 실행

    • 실기기 실행 결과는 다음과 같으며, 1단계의 Unity 에디터 위치와 비교 가능:

    • 왼쪽 투명 비디오 버튼 활성화 시, 월드 좌표계 원점((0, 0, 0))에 투명 비디오 재질의 큐브가 나타남.

      참고

      원점 위치는 공간 내 임의의 위치일 수 있음. 어노테이션을 이용해 오클루전 모델을 원하는 위치에 배치 가능. 자세한 내용은 Unity 에디터로 어노테이션 생성 및 업로드 참조.

    • 왼쪽 오클루전 버튼 활성화 시, 월드 좌표계 원점((0, 0, 0))에 판다 모델과 상하로 겹쳐진 큐브가 나타남. 중간 큐브는 오클루전 재질을 가지며, 반대편에는 오클루전 재질의 정적 판다 모델이 있음.

      참고

      원점 위치는 공간 내 임의의 위치일 수 있음. 어노테이션을 이용해 오클루전 모델을 원하는 위치에 배치 가능. 자세한 내용은 Unity 에디터로 어노테이션 생성 및 업로드 참조.

      모델 및 오클루전

How to play transparent videos at annotation locations

  1. video-texture 타입의 비디오 에셋 로드.

    async loadAsset() {
        const videoTexture = {
            assetId: "fireball",
            type: "video-texture",
            // 비디오 에셋 URL
            src: "url/video-resource.mp4",
            options: {
                autoPlay: true,
                loop: true,
            }
        };
        try {
            // video-texture 타입 에셋 로드
            await scene.assets.loadAsset(videoTexture);
        } catch (err) {
            console.error(`Failed to load video texture: ${err.message}`);
        }
    }
    
  2. EMA 로드 콜백 수정

    EMA 로드 콜백에서 scene.createElement(xrFrameSystem.XRMesh,options)를 사용해 간단한 기하체를 생성하고 easyar-video-tsbs 머티리얼을 적용하며, uniformu_baseColorMap:video-{$assetId}로 수정합니다.

    • 파라미터:

      • xrFrameSystem.XRMesh: 생성할 요소 타입을 기본 기하체로 지정.
      • options: 컴포넌트 속성에 대응하는 초기화 설정 항목.
    • 코드 내 핵심 속성:

      • "geometry": "cube": xr-frame 내장 큐브 기하 데이터 사용.
      • "material": "easyar-video-tsbs": 사전 정의된 머티리얼 지정(비디오 텍스처를 지원하는 특수 머티리얼로 추정).
      • "uniforms": "u_baseColorMap:video-{$assetId}":
      주의

      속성 Key의 문자열/비문자열 구분에 유의, 예시와 정확히 동일하게 작성.

      이는 머티리얼 파라미터의 동적 바인딩입니다.

      video-{$assetId}로 명명된 비디오 에셋(텍스처)를 머티리얼의 베이스 컬러 맵에 매핑합니다.

      효과: 표면에 비디오가 재생되는 큐브가 생성됩니다.

    model = scene.createElement(xrFrameSystem.XRMesh, {
        geometry: "cube",
        material: "easyar-video-tsbs",
        uniforms: "u_baseColorMap:video-fireball",
    });
    xrNode.addChild(model);
    
    참고

    video-texture 사용 시 콘솔에 wx.createVideoDecoder with type: 'wemedia' is deprecated 경고가 나타나면 무시하십시오.

    WeChat 공식 팀 확인 결과, 해당 경고는 사용에 영향을 주지 않습니다.

  3. 실기 실행

How to place occlusion models aligned with space

  1. 정확한 위치에 오클루전 모델 배치 및 라벨 업로드

    정확한 정렬

  2. xr-frame 미니프로그램에서 오클루전용 GLTF 로드

    scene.assets.loadAsset()을 사용하여 모델 에셋 로드 (수동 언로드 필요).

    const sampleAssets = {
        occlusion1: {
            assetId: "occlusion1",
            type: "gltf",
            src: "url/occlusion1.glb",
            options: {}
        }
    }
    async loadAsset() {
        if (!scene) {console.error("Empty scene"); return;}
        try {
            await scene.assets.loadAsset(sampleAssets.occlusion1);
        } catch (err) {
            console.error(`Failed to load assets: ${err.message}`);
        }
    }
    
  3. 런타임에서 EMA 로드 콜백에 모델 로드 및 오클루전 머티리얼 적용

    EMA 로드 콜백에서 scene.createElement(xrFrameSystem.XRGLTF,options)을 사용하여 모델 노드 생성.

    • 파라미터:

      • xrFrameSystem.XRGLTF: 생성할 엘리먼트 유형을 GLTF 모델로 지정.
      • options: 초기화 구성 항목, 컴포넌트 속성에 대응.
    • 코드 내 주요 속성:

      • "model": 필수, 로드된 리소스 ID(asset-id) 지정.
      • "scale": 선택 사항 assetInfo.scale 또는 "1 1 1".
      • name: 필수, 라벨 이름.
    주의

    속성 키(Key)의 문자열/비문자열 구분에 주의, 예시와 정확히 동일하게 작성.

    모델을 라벨 노드 아래에 마운트: xrNode.addChild(child).

    GLTF 모델이 플랫폼별 로더에서 동일한 결과를 보장하려면, 로드된 모델을 원점 기준 Y축으로 180도 회전.

    최종적으로 model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });}로 GLTF 모델 머티리얼 수정.

    참고

    easyar-occulusion 머티리얼의 로드, 등록, 해제, 언로드는 AR Session이 제어.

    라벨 위치의 모델을 오클루전으로 사용:

    if (...) {
        model = scene.createElement(
            xrFrameSystem.XRGLTF,
            {
                "model": assetInfo.assetId,
                "scale": assetInfo.scale ? assetInfo.scale : "1 1 1",
                name: emaName
            }
        );
        /**
        * GLTF 로더 동작 차이로 인해, xr-frame 상 모델 방향이 Unity 렌더 결과와 완전히 일치하도록
        * 로드된 모델을 원점 기준 Y축으로 180도 회전해야 할 수 있음
        */
        let modelTransform = model.getComponent(xrFrameSystem.Transform);
        let currentRotation = modelTransform.quaternion.clone();
        let targetRotation = currentRotation.multiply(new xrFrameSystem.Quaternion().setValue(0, 1, 0, 0));
        modelTransform.quaternion.set(targetRotation);
        //반드시 Transform 수정 후 머티리얼 수정
        if (assetInfo.assetId == 'occlusion1') {
            //Mega 플러그인 제공 오클루전 머티리얼 획득
            let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
            //오클루전 머티리얼 적용
            model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
                m.setData({ neverCull: true, material: occlusionMaterial });
            });
        }
    }
    
  4. 실기 실행

    Unity 에디터 시뮬레이션 결과와 비교 가능.

관련 주제