Kaip programiškai sukurti 3D tinklelį TypeScript

Kaip programiškai sukurti 3D tinklelį TypeScript

Aspose.3D FOSS for TypeScript leidžia kurti 3D geometriją visiškai kode be jokio failo įkėlimo. Jūs apibrėžiate viršūnių pozicijas kaip valdymo taškus, nurodote daugiakampių veidus pagal indeksą ir pridedate pasirenkamus viršūnių elementus, tokius kaip normalių vektoriai, UV koordinatės arba viršūnių spalvos. Rezultatas gali būti išsaugotas bet kuriame įrašomame formate: glTF, GLB, STL, FBX arba COLLADA.

Būtinosios sąlygos

  • Node.js 18 arba vėlesnė
  • TypeScript 5.0 arba vėlesnė
  • @aspose/3d įdiegta (žr. 1 žingsnį)

Žingsnis po žingsnio vadovas

Žingsnis 1: Įdiekite @aspose/3d

npm install @aspose/3d

Nereikia jokių natūralių papildinių ar sistemos bibliotekų. Paketas apima TypeScript tipų apibrėžimus.

Minimumas tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true
  }
}

Žingsnis 2: Sukurkite sceną ir mazgą

Scene yra aukščiausio lygio konteineris. Visa geometrija turi būti prijungta prie Node scenos medyje:

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

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

createChildNode(name) sukuria pavadintą mazgą ir prijungia jį kaip esamo mazgo vaiką. Grąžintas Node objektas yra vieta, kurioje 7 žingsnyje prijungsite tinklą.


3 žingsnis: sukurti tinklelio objektą

Mesh saugo viršūnių pozicijas ir daugiakampių apibrėžimus. Sukurkite vieną su pasirenkamu pavadinimu:

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

const mesh = new Mesh('triangle');

Tinklas pradžioje tuščias: nėra viršūnių ir nėra veidų. Jūs juos pridėsite tolesniuose žingsniuose.


Žingsnis 4: Pridėti kontrolinius taškus (viršūnes)

Kontroliniai taškai yra viršūnių pozicijos vietinėje erdvėje. Įdėkite Vector4 reikšmes į mesh.controlPoints. Ketvirta komponentė (w) yra 1 pozicijoms:

import { Vector4 } from '@aspose/3d/utilities';

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0)); // index 0
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0)); // index 1
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0)); // index 2

Jūs šias pozicijas nurodote pagal jų nulio pagrindo indeksą, kai apibrėžiate daugiakampio veidus.


Žingsnis 5: Sukurti daugiakampio paviršius

createPolygon() apibrėžia veidą išvardindama viršūnių indeksus tvarka. Trys indeksai sudaro trikampį:

mesh.createPolygon(0, 1, 2);

Taip pat galite apibrėžti kvadratus (keturis indeksus) arba bet kokius daugiakampius formatams, kurie juos palaiko. glTF atveju biblioteka automatiškai sueksportuodama suskaidys kvadratus ir n‑kampus į trikampius.


Žingsnis 6: Pridėti viršūnių normalės

Normalės pagerina atvaizdavimo kokybę. Naudokite mesh.createElement(), kad sukurtumėte VertexElementNormal, surinktumėte normalės vektorius į masyvą, tada iškvieskite setData(), kad juos išsaugotumėte. data gaunamasis metodas grąžina apsauginę kopiją — į ją įdėti (push) neturi jokio poveikio. Naudokite FVector3 (viengubo tikslumo slankiojo kablelio) normalės duomenims, o ne Vector4.

import { VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { FVector3 } from '@aspose/3d/utilities';

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// Build the normal array, then call setData() — do NOT push to normals.data
normals.setData([
    new FVector3(0, 0, 1), // normal for vertex 0 (pointing +Z)
    new FVector3(0, 0, 1), // normal for vertex 1
    new FVector3(0, 0, 1), // normal for vertex 2
]);

MappingMode.CONTROL_POINT reiškia vieną normalią per viršūnę. ReferenceMode.DIRECT reiškia, kad duomenų masyvas indeksuojamas tiesiogiai pagal daugiakampio viršūnės indeksą.


Žingsnis 7: Prisegti tinklelį ir išsaugoti į glTF

Priskirkite tinklelį mazgui per node.entity, tada išsaugokite sceną:

import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

Norėdami vietoj to sukurti vieną savarankišką .glb failą, nustatykite saveOpts.binaryMode = true ir pakeiskite išvesties failo plėtinį į .glb.

Pilnas pavyzdys

Toliau pateikiamas visas scenarijus, apjungiantis visus aukščiau nurodytus žingsnius:

import { Scene } from '@aspose/3d';
import { Mesh, VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { Vector4, FVector3 } from '@aspose/3d/utilities';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

const mesh = new Mesh('triangle');

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0));

mesh.createPolygon(0, 1, 2);

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// setData() is the correct API — normals.data returns a defensive copy; pushing to it has no effect
normals.setData([
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
]);

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

Paleisti su ts-node:

npx ts-node triangle.ts

Dažnos problemos

ProblemaPriežastisSprendimas
mesh.controlPoints.length yra 0 po pushTinklas nėra susietas su jokių mazguPush prieš priskiriant node.entity; tvarka nesvarbi, bet patikrinkite nuorodą
Eksportas sukuria tuščią geometrijąnode.entity nepriskirtaUžtikrinkite node.entity = mesh prieš iškviečiant scene.save()
Normalų skaičiaus neatitikimasMasyvas, perduotas setData(), trumpesnis nei controlPointsPridėkite po vieną FVector3 įrašą kiekvienam valdymo taškui naudojant MappingMode.CONTROL_POINT
glTF peržiūros programa rodo juodą tinkląNormalės rodo į vidųApverskite vėjimo tvarką createPolygon (pvz., 0, 2, 1) arba neigti normalų vektorius
TypeScript: savybės ’normals.data’ nerastaNeteisingas importo keliasImportuokite VertexElementNormal@aspose/3d/entities, o ne iš @aspose/3d šaknies

Dažnai užduodami klausimai

Ar galiu kurti kvadratus vietoje trikampių? Taip. Perduokite keturis indeksus createPolygon(0, 1, 2, 3). Biblioteka kvadratus trianguliuoja eksportuojant į formatus, kuriems reikalingi trikampiai (glTF, STL).

Kuo skiriasi MappingMode.CONTROL_POINT ir MappingMode.POLYGON_VERTEX?
CONTROL_POINT saugo vieną reikšmę kiekvienam unikaliam viršūnei. POLYGON_VERTEX saugo vieną reikšmę kiekvienam daugiakampio‑viršūnės porai, leidžiant skirtingus normalus toje pačioje viršūnėje, kai ji priklauso keliems daugiakampiams (kieti kraštai).

Ar reikia trikampuoti tinklelį prieš išsaugant į STL?
Ne. Biblioteka automatiškai tvarko trikampavimą eksportuojant į formatus, kuriems reikalingi trikampiai. Galite tinklelyje apibrėžti keturkampius ir n‑kampius ir tiesiogiai išsaugoti į STL.

Kaip pridėti UV koordinates?
Naudokite mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT), kad sukurtumėte VertexElementUV, tada iškvieskite setData([...]) su FVector2 arba FVector3 reikšmių masyvu — po vieną kiekvienam valdymo taškui. data gaunamasis metodas grąžina kopiją; neįdėkite į ją tiesiogiai.

Ar galiu sukurti kelis meshes vienoje scenoje?
Taip. Sukurkite kelis mazgus po scene.rootNode ir priskirkite atskirą Mesh kiekvieno mazgo entity savybei.

Žr. taip pat

 Lietuvių