Volně spojený kód:Babylon vs Three.js

Ahoj! :)

Před chvílí jsem spustil port Three.js z JavaScriptu do AssemblyScript (úžasný kompilátor TypeScript do WebAssembly):

GLAS

WebGL v WebAssembly s A montážS kript.

Motivace

Bylo by milé mít vysoce výkonný WebGL engine, který běží na webu přes WebAssembly a je napsán v jazyce, který weboví vývojáři již znají s JavaScriptem ve formě TypeScriptu (superset JavaScriptu s typy).

Vstupte do AssemblyScript, atoolchain, který nám umožňuje psát přísně typizovanou podmnožinu kódu TypeScript a kompilovat ji do WebAssembly (anaassembly podobný jazyk reprezentující strojový kód) kvůli rychlosti.

Stav

Projekt je v současné době ve velmi rané fázi alfa. Máme úžasnou skupinu programátorů, kteří vytvářejí počátečníASWebGLue knihovna. Tato knihovna umožňuje programům AssemblyScript volat základní rozhraní WebGL prohlížeče. To je nutné, než budeme schopni cokoliv vykreslit na obrazovku. A…

Zobrazit na GitHubu

Původně jsem se zajímal o portování Babylonu, protože je již napsán v TypeScriptu, takže portování by bylo snazší ve srovnání s převzetím kódové základny JavaScriptu a přidáním typů do ní po refaktorování dynamických částí, které TypeScript nezvládá.

Když jsem však začal přenášet třídy Babylon, brzy jsem si uvědomil, že třídy v knihovně jsou velmi propojené:importování Babylonu Scene třída znamená prakticky importovat celou knihovnu Babylon a vytvořit instanci mnoha částí knihovny (new This , new That , atd.), i když tyto části vaše aplikace nikdy nepoužije.

S Babylonem v podstatě chcete banán (např. Scene ) a získáte Gorilu a celou džungli (zbytek Babylonské knihovny).

Vysoká vazba je něco, čemu je třeba se vyhnout, pokud je to možné..

Chcete-li porozumět tomuto problému s ohledem na kódovou základnu Babylonu, podívejte se na příkazy o importu v Babylonském scene.ts :

import { Nullable } from "./types";
import { Tools } from "./Misc/tools";
import { IAnimatable } from './Animations/animatable.interface';
import { PrecisionDate } from "./Misc/precisionDate";
import { Observable, Observer } from "./Misc/observable";
import { SmartArrayNoDuplicate, SmartArray, ISmartArrayLike } from "./Misc/smartArray";
import { StringDictionary } from "./Misc/stringDictionary";
import { Tags } from "./Misc/tags";
import { Vector2, Vector3, Matrix, TmpVectors, Vector4 } from "./Maths/math.vector";
import { Geometry } from "./Meshes/geometry";
import { TransformNode } from "./Meshes/transformNode";
import { SubMesh } from "./Meshes/subMesh";
import { AbstractMesh } from "./Meshes/abstractMesh";
import { Mesh } from "./Meshes/mesh";
import { IParticleSystem } from "./Particles/IParticleSystem";
import { Bone } from "./Bones/bone";
import { Skeleton } from "./Bones/skeleton";
import { MorphTargetManager } from "./Morph/morphTargetManager";
import { Camera } from "./Cameras/camera";
import { AbstractScene } from "./abstractScene";
import { BaseTexture } from "./Materials/Textures/baseTexture";
import { Texture } from "./Materials/Textures/texture";
import { RenderTargetTexture } from "./Materials/Textures/renderTargetTexture";
import { ImageProcessingConfiguration } from "./Materials/imageProcessingConfiguration";
import { Effect } from "./Materials/effect";
import { UniformBuffer } from "./Materials/uniformBuffer";
import { MultiMaterial } from "./Materials/multiMaterial";
import { Light } from "./Lights/light";
import { PickingInfo } from "./Collisions/pickingInfo";
import { ICollisionCoordinator } from "./Collisions/collisionCoordinator";
import { PointerEventTypes, PointerInfoPre, PointerInfo } from "./Events/pointerEvents";
import { KeyboardInfoPre, KeyboardInfo } from "./Events/keyboardEvents";
import { ActionEvent } from "./Actions/actionEvent";
import { PostProcessManager } from "./PostProcesses/postProcessManager";
import { IOfflineProvider } from "./Offline/IOfflineProvider";
import { RenderingGroupInfo, RenderingManager, IRenderingManagerAutoClearSetup } from "./Rendering/renderingManager";
import { ISceneComponent, ISceneSerializableComponent, Stage, SimpleStageAction, RenderTargetsStageAction, RenderTargetStageAction, MeshStageAction, EvaluateSubMeshStageAction, PreActiveMeshStageAction, CameraStageAction, RenderingGroupStageAction, RenderingMeshStageAction, PointerMoveStageAction, PointerUpDownStageAction, CameraStageFrameBufferAction } from "./sceneComponent";
import { Engine } from "./Engines/engine";
import { Node } from "./node";
import { MorphTarget } from "./Morph/morphTarget";
import { Constants } from "./Engines/constants";
import { DomManagement } from "./Misc/domManagement";
import { Logger } from "./Misc/logger";
import { EngineStore } from "./Engines/engineStore";
import { AbstractActionManager } from './Actions/abstractActionManager';
import { _DevTools } from './Misc/devTools';
import { WebRequest } from './Misc/webRequest';
import { InputManager } from './Inputs/scene.inputManager';
import { PerfCounter } from './Misc/perfCounter';
import { IFileRequest } from './Misc/fileRequest';
import { Color4, Color3 } from './Maths/math.color';
import { Plane } from './Maths/math.plane';
import { Frustum } from './Maths/math.frustum';
import { UniqueIdGenerator } from './Misc/uniqueIdGenerator';
import { FileTools, LoadFileError, RequestFileError, ReadFileError } from './Misc/fileTools';
import { IClipPlanesHolder } from './Misc/interfaces/iClipPlanesHolder';
import { IPointerEvent } from "./Events/deviceInputEvents";
import { WebVRFreeCamera } from "./Cameras/VR/webVRCamera";

To je poměrně dlouhý seznam na to, co „scéna“ představuje, a celý seznam vidím na obrazovce svého počítače bez posouvání.

Na rozdíl od toho je kódová základna Three.js mnohem volněji spojena, což je pro mě velmi atraktivní z hlediska tvorby kódu, takže jsem nakonec zvolil Three.js a přijal jsem, že bych provedl více portování z JavaScriptu místo z TypeScript, protože Cítil jsem, že konečný výsledek bude čistší.

Jako příklad ztráty spojení Three je zde několik prvních řádků Scene.js Three :

import { Object3D } from '../core/Object3D.js';

class Scene extends Object3D {

    constructor() {

        super();

        this.type = 'Scene';

        this.background = null;
        this.environment = null;
        this.fog = null;

Prozkoumejte základnu kódu Three a uvidíte, že třídy se snaží být minimální a dělat dobře jen jednu věc (nebo dobře reprezentovat pouze jeden koncept).

Po spuštění portu pomocí Babylonu byl návrat k Three.js příjemný díky volnému propojení. Kódová základna Three.js je čistá.

Pokud bych se měl rozhodnout vyvíjet s jednou nebo druhou kódovou základnou nebo ji rozšířit, zvolil bych Three.js, protože volně propojená organizace v rámci knihovny usnadňuje údržbu a rozšiřování kódu a zároveň umožňuje určitým částem knihovny Three být používán bez stahování nepotřebných závislostí do aplikace.

Chtěl jsem se zeptat komunity Babylonu, jestli má někdo pocit, že části Babylonu jsou příliš těsně propojené ve srovnání například s Three.js, ale můj příspěvek byl okamžitě skryt jako „spam“:

https://forum.babylonjs.com/t/high-coupling-in-the-bablyon-codebase-compared-to-three-js/21156/3

(Pokud jej trvale smaže, možná jej neuvidíte.

V tom vlákně jsem se ptal

Doufal jsem, že otevřu diskusi na toto téma a doufal jsem, že by to mohlo zapálit oheň pro zlepšení Babylonu, ku prospěchu všech (mít alternativy je vždy skvělé).