TypeScript에서 3D 장면 그래픽을 통과하는 방법

TypeScript에서 3D 장면 그래픽을 통과하는 방법

Aspose.3D FOSS for TypeScript의 장면 그래픽은 나무입니다. Node 뿌리 잡힌 물체들에 대하여 scene.rootNode.여행은 반복적입니다 : 각 노드는 A를 표시합니다. childNodes 이탈리어 및 선택적 entity 이 가이드는 전체 나무를 걷고, 단체 유형을 식별하고, 메시 통계를 수집하는 방법을 보여줍니다.

원칙들

  • Node.js 18 또는 이후의 경우
  • TypeScript 5.0 또는 이후의 경우
  • @aspose/3d 설치된

단계별 가이드

단계 1 : 설치 및 수입

패키지를 설치하십시오 :

npm install @aspose/3d

이 가이드에서 사용되는 수업을 가져오십시오 :

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';

Scene 그리고 Mesh 그들은 핵심 클래스입니다. ObjLoadOptions 로드 예제에서 사용; 다른 형식으로 해당 옵션 클래스를 대체합니다.


단계 2: 파일에서 장면을 업로드합니다.

A를 만드는 것 Scene 그리고 전화 scene.open() 형식 탐지는 바이너리 마법 번호에서 자동으로, 그래서 당신은 GLB, STL 또는 3MF 파일의 형식을 지정할 필요가 없습니다 :

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

console.log(`Root node: "${scene.rootNode.name}"`);
console.log(`Top-level children: ${scene.rootNode.childNodes.length}`);

또한 A에서 충전할 수 있습니다. Buffer 기억에 사용하는 것 scene.openFromBuffer(buffer, options);• 디스크 I/O가 사용할 수 없는 서버없는 파이프라인에서 유용합니다.


단계 3: 재발 여행 기능을 작성합니다.

회전 위에 childNodes 기본 패턴입니다.이 기능은 각 노드 깊이를 먼저 방문합니다 :

function traverse(node: any, depth = 0): void {
    const indent = '  '.repeat(depth);
    const entityType = node.entity ? node.entity.constructor.name : '-';
    console.log(`${indent}[${entityType}] ${node.name}`);
    for (const child of node.childNodes) {
        traverse(child, depth + 1);
    }
}

traverse(scene.rootNode);

한 마스 이름을 가진 장면에 대하여 Cube, 생산은 다음과 같이 보일 것입니다 :

[-] RootNode
  [Mesh] Cube

<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”

<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>

node.entity 이건 null 그룹 노드, 뼈 및 로커를 위해. constructor.name 모든 유형의 단체에 대한 작업을 확인하십시오 : Mesh, Camera, Light,그리고 등등.


단계 4: 각 노드에 Entity Type를 액세스하십시오.

단체 유형에 따라 행동하려면, 하나의 instanceof 0 경비원 후 확인:

import { Mesh } from '@aspose/3d/entities';

function visitWithTypeCheck(node: any, depth = 0): void {
    const indent = '  '.repeat(depth);
    if (node.entity instanceof Mesh) {
        const mesh = node.entity as Mesh;
        console.log(`${indent}MESH "${node.name}": ${mesh.controlPoints.length} vertices`);
    } else if (node.entity) {
        console.log(`${indent}${node.entity.constructor.name} "${node.name}"`);
    } else {
        console.log(`${indent}GROUP "${node.name}"`);
    }
    for (const child of node.childNodes) {
        visitWithTypeCheck(child, depth + 1);
    }
}

visitWithTypeCheck(scene.rootNode);

instanceof Mesh 가장 안전한 방법은 액세스하기 전에 엔티트가 폴리곤 메시지인지 확인하는 것입니다. controlPoints, polygonCount,또는 Vertex 요소.


단계 5: 엔티티 타입에 따라 노드를 필터링합니다.

전체 나무를 인쇄하지 않고 단지 을 가진 노드를 수집하려면 재발성 배터리를 사용합니다.:

import { Mesh } from '@aspose/3d/entities';

function collectMeshes(
    node: any,
    results: Array<{ name: string; mesh: Mesh }> = []
): Array<{ name: string; mesh: Mesh }> {
    if (node.entity instanceof Mesh) {
        results.push({ name: node.name, mesh: node.entity as Mesh });
    }
    for (const child of node.childNodes) {
        collectMeshes(child, results);
    }
    return results;
}

const meshNodes = collectMeshes(scene.rootNode);
console.log(`Found ${meshNodes.length} mesh node(s)`);

기능은 선택적 인 기능을 받아 들일 수 있습니다. results 아레아 그래서 호출자는 여러 지하철을 통해 결합 결과를 위해 그것을 사전에 인기를 얻을 수 있습니다.


단계 6: 모든 메시지를 수집하고 Vertex 계산을 인쇄합니다.

컬렉터를 확장하여 per-mesh 통계를 인쇄하십시오 :

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';

function collectMeshes(node: any, results: Array<{name: string, mesh: Mesh}> = []) {
    if (node.entity instanceof Mesh) {
        results.push({ name: node.name, mesh: node.entity as Mesh });
    }
    for (const child of node.childNodes) {
        collectMeshes(child, results);
    }
    return results;
}

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

const meshes = collectMeshes(scene.rootNode);
for (const { name, mesh } of meshes) {
    console.log(`${name}: ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
}

2 메시지 장면에 대한 예제 출력 :

Cube: 8 vertices, 6 polygons
Sphere: 482 vertices, 480 polygons

<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”

<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>

팁과 최고의 관행

  • 항상 0 체크 node.entity 많은 노드는 단체를 운반하지 않는 순수한 그룹 노드입니다.
  • 사용하기 instanceof 위에 constructor.name 논리적 경로에서 유형 체크를 위해. instanceof 은 안전한; 스트리트 비교에 대한 constructor.name 미니화와 함께 끊어지게 됩니다.
  • 통과하여 for...of 위에 childNodes: 이탈 가능한 모든 궤도 크기를 안전하게 처리합니다.전환 호환성을 위해 수표 인덱스를 피하십시오.
  • 트레일링 중에 나무를 돌리지 마십시오.: 재구성 호출 내부에 노드를 추가하거나 제거하지 마십시오.처음 결과를 수집하고 그 다음을 수정합니다.
  • 결과를 파라미터로 표시하는 방법: 이것은 각 회복 전화에 새로운 순서를 할당하는 것을 피하고 잠수함 결과를 결합하기 쉽습니다.

일반적인 문제들

증상원인은고정
childNodes 0 길이를 가지고 있는 것 rootNode모델이 충전되지 않음보안 scene.open() 실수 없이 완료되기 전에 통과
node.entity instanceof Mesh 결코 진실하지 않음잘못된 Mesh 수입 경로수입 Mesh 에서부터 @aspose/3d/entities,하지만, 아니에서 @aspose/3d 뿌리
여행자들은 망가진 마스크를 놓치고 있다.모든 아이들을 끌어들이지 않는다.반복적인 전화가 각 항목을 커버하는지 확인하십시오. node.childNodes
mesh.controlPoints.length 0이야말로메쉬는 충전되지만 지질이 포함되지 않습니다.빈 그룹을 위한 OBJ 출처를 확인; 사용하기 mesh.polygonCount 초기 체크로서의 경우
깊은 히어로시를 위하여 과도한 흐름을 쌓아라.매우 깊은 장면 나무 (수백 레벨)뚜렷한 스택을 사용하여 회전을 대체합니다. Array.push / Array.pop

자주 묻는 질문들

는 하는 scene.rootNode 그 자체가 단체를 가지고 있는 것일까? No. 뿌리 노드는 도서관에 의해 자동으로 만들어진 컨테이너입니다. 그것은 단체가 없습니다. 당신의 지질 및 다른 장면 개체는 아래의 하나 이상의 레벨을 어린이 노드에 살고 있습니다. rootNode.

그 사이의 차이점은 무엇인가 node.entity 그리고 node.entities? node.entity 일부 오래된 FBX 및 COLLADA 파일은 여러 연결된 단체와 노드를 생성할 수 있습니다.이 경우에는 node.entities (플루러) 전체 목록을 제공합니다.

깊이 첫 번째 대신 넓은 첫 순서로 통과 할 수 있습니까? 예. 반복 전화 대신 꼬리를 사용하십시오 : push scene.rootNode 한 줄로 이동하고 각 노드를 밀어 넣는 동안 노드를 옮기고 처리합니다. childNodes 에 들어가서.

이건 scene.open() 동기화 하는가? 예요 ᄒᄒ. scene.open() 그리고 scene.openFromBuffer() 두 개 모두 파일이 완전히 파시 될 때까지 전화 스트립을 차단합니다. 이벤트 루프를 응답하게 유지해야하는 경우 작업 스트림에 그들을 삽입하십시오.

어떻게 노드에서 세계 공간 위치를 얻을 수 있습니까? 읽기 node.globalTransform;[읽기] 다시 읽는 것만으로도 반환한다. GlobalTransform 세계-공간 매트릭스, 모든 조상 변형으로 구성. 명시적인 매드릭스를 위해, 전화 node.evaluateGlobalTransform(false).

어떤 종류의 단체가 가능하다고 할 수 있음 Mesh? Camera, Light, 그리고 사용자 지정 척추/골체 단체. 확인 node.entity.constructor.name 또는 사용하기 instanceof 특정 클래스에서 수입된 @aspose/3d.

또한 보기

 한국어