Jak zbudować siatkę 3D programowo w TypeScript

Jak zbudować siatkę 3D programowo w TypeScript

Aspose.3D FOSS for TypeScript pozwala tworzyć geometrię 3D całkowicie w kodzie, bez ładowania jakiegokolwiek pliku. Definiujesz pozycje wierzchołków jako punkty kontrolne, określasz ściany wielokątów za pomocą indeksów i dołączasz opcjonalne elementy wierzchołków, takie jak normalne, UV lub kolory wierzchołków. Wynik można zapisać w dowolnym zapisywalnym formacie: glTF, GLB, STL, FBX lub COLLADA.

Wymagania wstępne

  • Node.js 18 lub nowszy
  • TypeScript 5.0 lub nowszy
  • @aspose/3d zainstalowany (zobacz Krok 1)

Przewodnik krok po kroku

Krok 1: Zainstaluj @aspose/3d

npm install @aspose/3d

Nie są wymagane żadne natywne dodatki ani biblioteki systemowe. Pakiet zawiera definicje typów TypeScript.

Minimum tsconfig.json:

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

Krok 2: Utwórz scenę i węzeł

Scene jest kontenerem najwyższego poziomu. Cała geometria musi być dołączona do Node wewnątrz drzewa sceny:

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

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

createChildNode(name) tworzy nazwany węzeł i podłącza go jako dziecko bieżącego węzła. Zwrócony obiekt Node to miejsce, w którym w kroku 7 podłączysz siatkę.


Krok 3: Utwórz Mesh Object

Mesh przechowuje pozycje wierzchołków i definicje wielokątów. Utwórz jeden z opcjonalną nazwą:

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

const mesh = new Mesh('triangle');

Siatka zaczyna się pustą: brak wierzchołków i brak ścian. Dodajesz je w kolejnych krokach.


Krok 4: Dodaj punkty kontrolne (wierzchołki)

Punkty kontrolne to pozycje wierzchołków w przestrzeni lokalnej. Przenieś wartości Vector4 do mesh.controlPoints. Czwarty składnik (w) jest 1 dla pozycji:

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

Odwołujesz się do tych pozycji za pomocą ich indeksu zerowego przy definiowaniu ścian wielokątów.


Krok 5: Utwórz ściany wielokąta

createPolygon() definiuje twarz, wymieniając indeksy wierzchołków w kolejności. Trzy indeksy tworzą trójkąt:

mesh.createPolygon(0, 1, 2);

Możesz także definiować czworokąty (cztery indeksy) lub dowolne wielokąty dla formatów, które je obsługują. Dla glTF biblioteka automatycznie trianguluje czworokąty i n‑kąty podczas eksportu.


Krok 6: Dodaj normale wierzchołków

Normalne poprawiają jakość renderowania. Użyj mesh.createElement(), aby utworzyć VertexElementNormal, zbierz wektory normalnych do tablicy, a następnie wywołaj setData(), aby je zapisać. Getter data zwraca kopię obronną — dodawanie do niej nie ma wpływu. Używaj FVector3 (liczba zmiennoprzecinkowa pojedynczej precyzji) dla danych normalnych, nie 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 oznacza jedną normalną na wierzchołek. ReferenceMode.DIRECT oznacza, że tablica danych jest indeksowana bezpośrednio przez indeks wierzchołka wielokąta.


Krok 7: Dołącz siatkę i zapisz jako glTF

Przypisz siatkę do węzła za pomocą node.entity, a następnie zapisz 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');

Aby zamiast tego wygenerować pojedynczy, samodzielny plik .glb, ustaw saveOpts.binaryMode = true i zmień rozszerzenie pliku wyjściowego na .glb.

Pełny przykład

Poniżej znajduje się pełny skrypt łączący wszystkie powyższe kroki:

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');

Uruchom z ts-node:

npx ts-node triangle.ts

Typowe problemy

IssueCauseFix
mesh.controlPoints.length wynosi 0 po pushSiatka nie jest referencjonowana przez żaden węzełWypchnij przed przypisaniem node.entity; kolejność nie ma znaczenia, ale zweryfikuj odwołanie
Eksport generuje pustą geometrięnode.entity nie przypisanoUpewnij się, że node.entity = mesh jest ustawione przed wywołaniem scene.save()
Niezgodność liczby wektorów normalnychTablica przekazana do setData() jest krótsza niż controlPointsDodaj jeden wpis FVector3 na każdy punkt kontrolny przy użyciu MappingMode.CONTROL_POINT
Podgląd glTF wyświetla czarną siatkęWektory normalne skierowane do wewnątrzOdwróć kolejność wierzchołków w createPolygon (np. 0, 2, 1) lub zaneguj wektory normalne
TypeScript: nie znaleziono właściwości ’normals.data'Nieprawidłowa ścieżka importuImportuj VertexElementNormal z @aspose/3d/entities, a nie z katalogu głównego @aspose/3d

Najczęściej zadawane pytania

Czy mogę tworzyć czworokąty zamiast trójkątów?
Tak. Przekaż cztery indeksy do createPolygon(0, 1, 2, 3). Biblioteka trianguluje czworokąty podczas eksportu do formatów wymagających trójkątów (glTF, STL).

Jaka jest różnica między MappingMode.CONTROL_POINT a MappingMode.POLYGON_VERTEX?
CONTROL_POINT przechowuje jedną wartość na unikalny wierzchołek. POLYGON_VERTEX przechowuje jedną wartość na parę wielokąt‑wierzchołek, co pozwala na różne wektory normalne w tym samym wierzchołku, gdy należy on do wielu wielokątów (twarde krawędzie).

Czy muszę triangulować siatkę przed zapisaniem do STL?
Nie. Biblioteka automatycznie obsługuje triangulację podczas eksportu do formatów wymagających trójkątów. Możesz definiować czworokąty i n‑kąty w siatce i zapisać bezpośrednio do STL.

Jak dodać współrzędne UV?
Użyj mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT), aby utworzyć VertexElementUV, a następnie wywołaj setData([...]) z tablicą wartości FVector2 lub FVector3 — po jednej na punkt kontrolny. Getter data zwraca kopię; nie dodawaj do niej bezpośrednio.

Czy mogę zbudować wiele siatek w jednej scenie? Tak. Utwórz wiele węzłów pod scene.rootNode i przypisz oddzielny Mesh do właściwości entity każdego węzła.

Zobacz także

 Polski