Fonctionnalités et capacités
Aspose.3D FOSS for TypeScript est une bibliothèque Node.js sous licence MIT pour charger, construire et exporter des scènes 3D. Elle est fournie avec des définitions de types TypeScript complètes, une seule dépendance d’exécution (xmldom).
Installation et configuration
Installez le paquet depuis npm en utilisant une seule commande :
npm install @aspose/3dLe paquet cible CommonJS et nécessite Node.js 18 ou une version ultérieure. Après l’installation, vérifiez que votre tsconfig.json inclut les options de compilateur suivantes pour une compatibilité totale :
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Importez le principal Scene classe depuis la racine du paquet. Les classes d’options spécifiques à chaque format sont importées depuis leurs sous‑chemins respectifs :
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';Fonctionnalités et capacités
Prise en charge des formats
Aspose.3D FOSS for TypeScript lit et écrit six formats de fichiers 3D majeurs. La détection du format est automatique à partir des nombres magiques binaires lors du chargement, vous n’avez donc pas besoin de spécifier explicitement le format source.
| Format | Lire | Écrire | Notes |
|---|---|---|---|
| OBJ (Wavefront) | Oui | Oui | Lit/écrit .mtl matériaux; utilisez ObjLoadOptions.enableMaterials pour l’importation |
| glTF 2.0 | Oui | Oui | format texte JSON; matériaux PBR |
| GLB | Oui | Oui | glTF binaire ; défini GltfSaveOptions.binaryMode = true |
| STL | Oui | Oui | Binaire et ASCII ; aller-retour complet vérifié |
| 3MF | Oui | Oui | 3D Manufacturing Format with color and material metadata |
| FBX | Non* | Non* | Importateur/exportateur existent mais la détection automatique du format n’est pas câblée |
| COLLADA (DAE) | Oui | Oui | Échelle d’unité, géométrie, matériaux et clips d’animation |
Chargement d’OBJ avec matériaux :
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
options.flipCoordinateSystem = false;
options.scale = 1.0;
options.normalizeNormal = true;
scene.open('model.obj', options);Enregistrement au format GLB (glTF binaire) :
import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
// ... build or load scene content
const opts = new GltfSaveOptions();
opts.binaryMode = true;
scene.save('output.glb', GltfFormat.getInstance(), opts);Graphe de scène
Tout le contenu 3D est organisé sous forme d’arbre de Node objets enracinés à scene.rootNode. Chaque nœud peut contenir un Entity (un Mesh, Camera, Light, ou autre SceneObject) et un Transform qui le positionne par rapport à son parent.
Classes clés du graphe de scène :
Scene: le conteneur de niveau supérieur ; contientrootNodeetanimationClipsNode: un nœud d’arbre nommé avecchildNodes,entity,transform, etmaterialsEntity: classe de base pour les objets attachables (Mesh,Camera,Light)SceneObject: classe de base partagée parNodeetEntityA3DObject: classe de base racine avecnameet sac de propriétésTransform: translation locale, rotation (Euler et Quaternion), et mise à l’échelle
Parcourir le graphe de scène :
import { Scene, Node, Mesh } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
function visit(node: Node, depth: number = 0): void {
const indent = ' '.repeat(depth);
console.log(`${indent}Node: ${node.name}`);
if (node.entity) {
console.log(`${indent} Entity: ${node.entity.constructor.name}`);
}
for (const child of node.childNodes) {
visit(child, depth + 1);
}
}
visit(scene.rootNode);Création d’une hiérarchie de scène par programme :
import { Scene, Node } from '@aspose/3d';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('chassis');
const wheel = parent.createChildNode('wheel_fl');
wheel.transform.translation.set(0.9, -0.3, 1.4);Géométrie et maillage
Mesh est le type de géométrie principal. Il étend Geometry et expose les points de contrôle (sommets), les indices de polygones et les éléments de sommet pour les normales, les UV et les couleurs de sommet.
Classes de géométrie clés :
Mesh: maillage polygonal aveccontrolPointsetpolygonCountGeometry: classe de base avec gestion des éléments de sommetVertexElementNormal: normales par sommet ou par sommet de polygoneVertexElementUV: coordonnées de texture (un ou plusieurs canaux UV)VertexElementVertexColor: données de couleur par sommetMappingMode: contrôle la façon dont les données d’élément sont mappées aux polygones (CONTROL_POINT,POLYGON_VERTEX,POLYGON,EDGE,ALL_SAME)ReferenceMode: contrôle la stratégie d’indexation (DIRECT,INDEX,INDEX_TO_DIRECT)VertexElementType: identifie la sémantique d’un élément de sommetTextureMapping: énumération des canaux de texture
Lecture des données de maillage à partir d’une scène chargée :
import { Scene, Mesh, VertexElementType } from '@aspose/3d';
const scene = new Scene();
scene.open('model.stl');
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
const normals = mesh.getElement(VertexElementType.NORMAL);
if (normals) {
console.log(` Normal mapping: ${normals.mappingMode}`);
}
}
}Système de matériaux
Aspose.3D FOSS pour TypeScript prend en charge trois types de matériaux couvrant l’ensemble du spectre, du rendu Phong hérité au rendu physiquement basé :
LambertMaterial: couleur diffuse et couleur ambiante ; correspond aux matériaux simples OBJ/DAEPhongMaterial: ajoute la couleur spéculaire, la brillance et l’émissif ; le type de matériau OBJ par défautPbrMaterial: modèle physiquement basé de rugosité/métallique ; utilisé pour l’importation et l’exportation glTF 2.0
Lecture des matériaux depuis une scène OBJ chargée :
import { Scene, PhongMaterial, LambertMaterial } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.open('model.obj', options);
for (const node of scene.rootNode.childNodes) {
for (const mat of node.materials) {
if (mat instanceof PhongMaterial) {
const phong = mat as PhongMaterial;
console.log(` Phong: diffuse=${JSON.stringify(phong.diffuseColor)}, shininess=${phong.shininess}`);
} else if (mat instanceof LambertMaterial) {
console.log(` Lambert: diffuse=${JSON.stringify((mat as LambertMaterial).diffuseColor)}`);
}
}
}Application d’un matériau PBR lors de la construction d’une scène glTF :
import { Scene, Node, PbrMaterial } from '@aspose/3d';
import { Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('sphere');
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.8, 0.2, 0.2); // red-tinted albedo; albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.5;
node.material = mat;
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), opts);Utilitaires mathématiques
La bibliothèque fournit un ensemble complet de types mathématiques 3D, tous entièrement typés :
Vector3:vecteur à 3 composantes ; prend en chargeminus(),times(),dot(),cross(),normalize(),length,angleBetween()Vector4:vecteur à 4 composantes pour les coordonnées homogènesMatrix4:matrice de transformation 4×4 avecconcatenate(),transpose,decompose,setTRSQuaternion:quaternion de rotation avecfromEulerAngle()(statique, singulier),eulerAngles()(méthode d’instance),slerp(),normalize()BoundingBox:boîte englobante alignée sur les axes avecminimum,maximum,center,size,mergeFVector3:variante simple précision deVector3utilisé dans les données d’éléments de sommet
Calcul d’une boîte englobante à partir des sommets du maillage :
import { Scene, Mesh, Vector3, BoundingBox } from '@aspose/3d';
const scene = new Scene();
scene.open('model.obj');
let box = new BoundingBox();
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
for (const pt of (node.entity as Mesh).controlPoints) {
box.merge(new Vector3(pt.x, pt.y, pt.z));
}
}
}
console.log('Center:', box.center);
console.log('Extents:', box.size);Construction d’une transformation à partir d’angles d’Euler :
import { Quaternion, Vector3, Matrix4 } from '@aspose/3d';
const rot = Quaternion.fromEulerAngle(0, Math.PI / 4, 0); // 45° around Y
const mat = new Matrix4();
mat.setTRS(new Vector3(0, 0, 0), rot, new Vector3(1, 1, 1));Système d’animation
L’API d’animation modélise les clips, les nœuds, les canaux et les séquences d’images clés :
AnimationClip:collection nommée de nœuds d’animation ; accédée viascene.animationClips; exposeanimations: AnimationNode[]AnimationNode:groupe nommé deBindPoints ; créé viaclip.createAnimationNode(name), accessible viaclip.animationsBindPoint: lie unAnimationNodeà une propriété spécifique d’un objet de scène ; exposepropertyetchannelsCountAnimationChannel: étendKeyframeSequence; contient un séparékeyframeSequence; accessible viabindPoint.getChannel(name)KeyFrame: une paire temps/valeur unique ; porte par image-cléinterpolation: InterpolationKeyframeSequence: liste ordonnée deKeyFrameobjets viakeyFrames; possèdepreBehavioretpostBehavior(Extrapolation)Interpolation: enum:LINEAR,CONSTANT,BEZIER,B_SPLINE,CARDINAL_SPLINE,TCB_SPLINEExtrapolation: classe avectype: ExtrapolationTypeetrepeatCount: numberExtrapolationType: enum:CONSTANT,GRADIENT,CYCLE,CYCLE_RELATIVE,OSCILLATE
Lecture des données d’animation à partir d’une scène chargée :
import { Scene, AnimationNode, BindPoint } from '@aspose/3d';
const scene = new Scene();
scene.open('animated.dae'); // COLLADA animation import is supported
for (const clip of scene.animationClips) {
console.log(`Clip: "${clip.name}"`);
for (const animNode of clip.animations) { // clip.animations, not clip.nodes
console.log(` AnimationNode: ${animNode.name}`);
for (const bp of animNode.bindPoints) { // animNode.bindPoints, not animNode.channels
console.log(` BindPoint: property="${bp.property.name}", channels=${bp.channelsCount}`);
}
}
}Prise en charge des flux et des tampons
Utiliser scene.openFromBuffer() pour charger une scène 3D directement depuis la mémoire Buffer. C’est le modèle recommandé pour les fonctions serverless, les pipelines de streaming et le traitement des ressources récupérées via HTTP sans écrire sur le disque.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import * as fs from 'fs';
// Load file into memory, then parse from buffer
const buffer: Buffer = fs.readFileSync('model.obj');
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.openFromBuffer(buffer, options);
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(node.name, node.entity.constructor.name);
}
}La détection automatique du format à partir des nombres magiques binaires s’applique lors du chargement depuis un tampon, de sorte que les fichiers GLB, STL binaires et 3MF sont reconnus sans spécifier de paramètre de format.
Exemples d’utilisation
Exemple 1 : charger un OBJ et exporter en GLB
Cet exemple charge un fichier Wavefront OBJ avec ses matériaux, puis réexporte la scène sous forme de fichier glTF binaire (GLB) adapté à une utilisation sur le web et dans les moteurs de jeu.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
function convertObjToGlb(inputPath: string, outputPath: string): void {
const scene = new Scene();
const loadOpts = new ObjLoadOptions();
loadOpts.enableMaterials = true;
loadOpts.flipCoordinateSystem = false;
loadOpts.normalizeNormal = true;
scene.open(inputPath, loadOpts);
// Report what was loaded
for (const node of scene.rootNode.childNodes) {
if (node.entity) {
console.log(`Loaded: ${node.name} (${node.entity.constructor.name})`);
}
}
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // write .glb instead of .gltf + .bin
scene.save(outputPath, GltfFormat.getInstance(), saveOpts);
console.log(`Exported GLB to: ${outputPath}`);
}
convertObjToGlb('input.obj', 'output.glb');Exemple 2 : aller-retour STL avec validation des normales
Cet exemple charge un fichier STL binaire, affiche les informations de normales par sommet, puis réexporte la scène en STL ASCII et vérifie le cycle complet.
import { Scene, Mesh, VertexElementNormal, VertexElementType } from '@aspose/3d';
import { StlLoadOptions, StlSaveOptions } from '@aspose/3d/formats/stl';
const scene = new Scene();
const loadOpts = new StlLoadOptions();
scene.open('model.stl', loadOpts);
let totalPolygons = 0;
for (const node of scene.rootNode.childNodes) {
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
totalPolygons += mesh.polygonCount;
const normElem = mesh.getElement(VertexElementType.NORMAL) as VertexElementNormal | null;
if (normElem) {
console.log(` Normals: ${normElem.data.length} entries, mapping=${normElem.mappingMode}`);
}
}
}
console.log(`Total polygons: ${totalPolygons}`);
// Re-export as ASCII STL
const saveOpts = new StlSaveOptions();
saveOpts.binaryMode = false; // ASCII output
scene.save('output_ascii.stl', saveOpts);Exemple 3 : Construire une scène programmatiquement et l’enregistrer au format glTF
Cet exemple construit une scène avec un matériau PBR à partir de zéro et l’enregistre sous forme de fichier glTF JSON.
import { Scene, Mesh, PbrMaterial, Vector4, Vector3 } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const node = scene.rootNode.createChildNode('floor');
// Build a simple quad mesh (two triangles)
// controlPoints are Vector4 (x, y, z, w) where w=1 for positions
const mesh = new Mesh();
mesh.controlPoints.push(
new Vector4(-1, 0, -1, 1),
new Vector4( 1, 0, -1, 1),
new Vector4( 1, 0, 1, 1),
new Vector4(-1, 0, 1, 1),
);
mesh.createPolygon([0, 1, 2]);
mesh.createPolygon([0, 2, 3]);
node.entity = mesh;
// Apply a PBR material
const mat = new PbrMaterial();
mat.albedo = new Vector3(0.6, 0.6, 0.6); // albedo starts null, must assign
mat.metallicFactor = 0.0;
mat.roughnessFactor = 0.8;
node.material = mat;
// Save as JSON glTF
const opts = new GltfSaveOptions();
opts.binaryMode = false;
scene.save('floor.gltf', GltfFormat.getInstance(), opts);
console.log('Scene written to floor.gltf');Conseils et bonnes pratiques
- Utiliser
ObjLoadOptions.enableMaterials = truechaque fois que vous avez besoin des données de matériau à partir des fichiers .mtl. Sans cela, la liste des matériaux sur chaque nœud sera vide. - Préférez
binaryMode = truepour GLB lors de la production d’actifs pour le web ou les moteurs de jeu. Le GLB binaire est un fichier autonome unique et se charge plus rapidement dans les navigateurs et les moteurs que la séparation JSON + .bin. - Utilisez
openFromBuffer()dans les environnements serverless pour éviter les entrées/sorties de fichiers temporaires. Récupérez l’actif, passez leBufferdirectement, et écrivez la sortie dans un flux ou un autre tampon. - Vérifiez
node.entityavant de caster: tous les nœuds ne portent pas d’entité. Protégez toujours avec uninstanceofvérifier avant d’accéderMesh-spécifiques propriétés telles quecontrolPoints. - Définir
normalizeNormal = truedansObjLoadOptionslorsque vos fichiers OBJ source proviennent de sources non fiables. Cela empêche les normales dégénérées de se propager dans les étapes de rendu ou de validation en aval. - Conserver
strict: truedans tsconfig.json: la bibliothèque est écrite avecnoImplicitAnyetstrictNullChecks. Désactiverstrictmasque les véritables erreurs de type et annule la valeur de l’API typée. - Parcourir via
childNodes, pas une boucle d’index: lechildNodesla propriété renvoie un itérable; évitez de vous fier à l’indexation numérique pour assurer la compatibilité future.
Problèmes courants
| Symptôme | Cause probable | Correction |
|---|---|---|
| Liste des matériaux vide après le chargement OBJ | enableMaterials non défini | Définir options.enableMaterials = true |
| Le fichier GLB contient un sidecar .bin séparé | binaryMode par défaut à false | Définir opts.binaryMode = true |
| Normales de sommet manquantes dans la sortie STL | Le mode ASCII STL omet les normales par face | Passer à binaryMode = true ou calculer les normales avant l’exportation |
node.entity est toujours null | Parcourir uniquement rootNode, pas ses enfants | Récursivement dans node.childNodes |
| Erreur TypeScript : la propriété n’existe pas | Ancien @types cache | Exécuter npm install @aspose/3d encore ; pas de séparé @types le package est nécessaire |
openFromBuffer lance une erreur de format | Le format n’est pas détectable automatiquement à partir du magic | Passez la classe d’option de format explicite comme deuxième argument |
Foire aux questions
La bibliothèque nécessite-t-elle des modules natifs ou des packages système ? Non. Aspose.3D FOSS pour TypeScript a une seule dépendance d’exécution : xmldom, qui est du JavaScript pur et installé automatiquement par npm. Il n’y a pas de .node modules natifs et aucun paquet système à installer.
Quelles versions de Node.js sont prises en charge ? Node.js 18, 20 et 22 LTS. La bibliothèque cible une sortie CommonJS et utilise les fonctionnalités du langage ES2020 en interne.
Puis-je utiliser la bibliothèque dans un bundle navigateur (webpack/esbuild) ? La bibliothèque cible Node.js et utilise le Node.js fs et Buffer API. L’empaquetage pour navigateur n’est pas officiellement pris en charge. Pour une utilisation dans le navigateur, chargez la scène côté serveur et transmettez le résultat (par ex., en GLB) au client.
Quelle est la différence entre GltfSaveOptions.binaryMode = true et false? binaryMode = false produit un .gltf fichier JSON plus un séparé .bin sidecar de tampon binaire. binaryMode = true produit un seul autonome .glb fichier. Utilisez true pour la livraison d’actifs en production.
Puis-je charger un fichier à partir d’une réponse HTTP sans l’enregistrer sur le disque ? Oui. Récupérez la réponse en tant que Buffer (par ex., en utilisant node-fetch ou le intégré fetch dans Node 18+), puis appelez scene.openFromBuffer(buffer, options).
Le support FBX est‑il complet ? Non. Des classes d’importateur et d’exportateur FBX existent dans la bibliothèque, mais FBX n’est pas intégré à Scene.open() ou Scene.save() détection automatique. Appeler scene.open('file.fbx') ne déclenchera pas l’importateur FBX ; le fichier sera traité par le chemin de secours STL. Utilisez directement les classes importateur/exportateur spécifiques à FBX si vous avez besoin d’E/S FBX. Consultez le tableau de prise en charge des formats ci‑dessus qui indique FBX comme No*.
La bibliothèque prend‑elle en charge TypeScript 4.x ? TypeScript 5.0+ est recommandé. TypeScript 4.7+ devrait fonctionner en pratique, mais la bibliothèque est testée et développée pour la version 5.0+.
Résumé de la référence API
| Classe | Module | Objectif |
|---|---|---|
Scene | @aspose/3d | Conteneur de scène de niveau supérieur ; open(), openFromBuffer(), save(), rootNode, animationClips |
Node | @aspose/3d | Nœud du graphe de scène ; childNodes, entity, transform, materials, createChildNode() |
Entity | @aspose/3d | Classe de base pour les objets pouvant être attachés à la scène |
SceneObject | @aspose/3d | Classe de base partagée par Node et Entity |
A3DObject | @aspose/3d | Base racine avec name et property bag |
Transform | @aspose/3d | Translation, rotation et mise à l’échelle locales |
Mesh | @aspose/3d | Maillage polygonal; controlPoints, polygonCount, createPolygon(), éléments de sommet |
Geometry | @aspose/3d | Classe de base pour les types de géométrie |
Camera | @aspose/3d | Entité caméra avec champ de vision et paramètres de projection |
Light | @aspose/3d | Entité lumière (ponctuelle, directionnelle, spot) |
LambertMaterial | @aspose/3d | Modèle d’ombrage diffus + ambiant |
PhongMaterial | @aspose/3d | Ombrage Phong avec spéculaire et émissif |
PbrMaterial | @aspose/3d | Modèle physiquement basé de rugosité/métallique pour glTF |
Vector3 | @aspose/3d | 3-component double-precision vector |
Vector4 | @aspose/3d | 4-component vector for homogeneous math |
Matrix4 | @aspose/3d | 4×4 transformation matrix |
Quaternion | @aspose/3d | Quaternion de rotation |
BoundingBox | @aspose/3d | Boîte englobante alignée sur les axes |
FVector3 | @aspose/3d | Variante simple précision de Vector3 |
VertexElementNormal | @aspose/3d | Normales par sommet ou par sommet de polygone |
VertexElementUV | @aspose/3d | Élément de sommet de coordonnées de texture |
VertexElementVertexColor | @aspose/3d | Élément de sommet de couleur par sommet |
MappingMode | @aspose/3d | Énumération : CONTROL_POINT, POLYGON_VERTEX, POLYGON, ALL_SAME |
ReferenceMode | @aspose/3d | Énumération : DIRECT, INDEX, INDEX_TO_DIRECT |
AnimationClip | @aspose/3d | Animation nommée ; expose animations: AnimationNode[]; créé via scene.createAnimationClip(name) |
AnimationNode | @aspose/3d | Groupe nommé de BindPoints; créé via clip.createAnimationNode(name) |
BindPoint | @aspose/3d | Lie un AnimationNode à une propriété d’objet de scène ; expose property et channelsCount |
AnimationChannel | @aspose/3d | Étend KeyframeSequence; contient un keyframeSequence; accessible via bindPoint.getChannel(name) |
KeyFrame | @aspose/3d | Paire d’images-clés temps/valeur unique ; porte interpolation: Interpolation |
KeyframeSequence | @aspose/3d | Ordonné keyFrames liste; preBehavior/postBehavior sont Extrapolation objets |
Interpolation | @aspose/3d | Enum: LINEAR, CONSTANT, BEZIER, B_SPLINE, CARDINAL_SPLINE, TCB_SPLINE |
Extrapolation | @aspose/3d | Classe avec type: ExtrapolationType et repeatCount: number |
ExtrapolationType | @aspose/3d | Enum: CONSTANT, GRADIENT, CYCLE, CYCLE_RELATIVE, OSCILLATE |
ObjLoadOptions | @aspose/3d/formats/obj | Options d’importation OBJ: enableMaterials, flipCoordinateSystem, scale, normalizeNormal |
GltfSaveOptions | @aspose/3d/formats/gltf | Options d’exportation glTF/GLB: binaryMode |
GltfFormat | @aspose/3d/formats/gltf | Instance de format pour glTF/GLB; passez à scene.save() |
StlLoadOptions | @aspose/3d/formats/stl | Options d’importation STL |
StlSaveOptions | @aspose/3d/formats/stl | Options d’exportation STL : binaryMode |
StlImporter | @aspose/3d/formats/stl | Lecteur STL de bas niveau |
StlExporter | @aspose/3d/formats/stl | Écrivain STL de bas niveau |