@carbonenginejs/format-obj
v0.1.2
Published
CarbonEngineJS OBJ format package. Exposes CjsFormatObj for Wavefront OBJ mesh text and the shared CarbonEngineJS JSON mesh schema.
Maintainers
Readme
@carbonenginejs/format-obj
Pure-JavaScript CarbonEngineJS-facing package for the Wavefront OBJ format. No native tooling, no build step; it runs in Node and the browser.
The package currently exposes a read path. OBJ is only the import source; it emits the shared CarbonEngineJS JSON mesh schema: deinterleaved vertex channels, triangle-index groups, and empty root arrays for schema branches OBJ cannot represent.
CarbonEngine and Fenris Creations (CCP Games) are named in this package for interoperability and target-ecosystem context only. OBJ itself is not a CCP format, and this package contains no CarbonEngine or Fenris Creations (CCP Games) source code.
Package
- npm: https://www.npmjs.com/package/@carbonenginejs/format-obj
- package:
@carbonenginejs/format-obj - version:
0.1.0 - license:
MIT - runtime: Node
>=18, modern browsers - module: ESM, package root exports
CjsFormatObj
Install
npm install @carbonenginejs/format-objPublic API
The package root exports one public class: CjsFormatObj. The Cjs prefix
marks this as a CarbonEngineJS format/construction boundary, not an engine
runtime class.
import CjsFormatObj from "@carbonenginejs/format-obj";
const obj = new CjsFormatObj({
emit: "json", // "json" only for now
source: "mesh.obj", // name written to grannyFileSource
packTangents: false, // opt-in: pack generated basis for GR2-style shader inputs
uvHandedness: "right", // "right" (default) | "left"
rebuildMissingNormals: false,
rebuildMissingTangents: false,
rebuildMissingBiNormals: false,
classes: {
Root: CjsGeometryRoot,
Mesh: CjsGeometryMesh,
IndexGroup: CjsGeometryIndexGroup
}
});
const json = obj.Read(objText);
const summary = obj.Inspect(objText);
const text = JSON.stringify(obj.ToJSON(json));The named export is the same class for callers that prefer named imports:
import { CjsFormatObj } from "@carbonenginejs/format-obj";Format Rules
- The package root currently exports one public format class:
CjsFormatObj. - The package name uses
format-objbecause this is the format home. A future writer can live beside the read path without changing the package identity. - Instance methods are PascalCase because format instances can hydrate or sit beside CarbonClasses without colliding with camelCase data fields.
- Static one-shot methods are camelCase because they live on
CjsFormatObjitself, not on hydrated CarbonClass instances. src/CjsFormatObj.jsis the public format boundary. Read and future write commands belong on this class; parser and geometry helpers live undersrc/core.Read/ staticreadreturn the shared JSON schema.emit: "raw"is not exposed yet because this package's parser state is intentionally internal.ToJSON/ statictoJSONconverts format output to JSON-compatible data. It is not an OBJ or GR2 writer and does not return JSON text.packTangentsis a conversion option. It builds any missing basis channels it needs, packs them into a four-componenttangentchannel, and clearsnormal/binormalso the mesh matches the packed GR2-style tangent shape.uvHandednesscontrols the generated bitangent side of tangent-space basis construction. It does not rewrite authored UV coordinates.- Shared schema, registries, hydration utilities, and decorators belong in the
future
@carbonenginejs/core-typespackage. - Normal and tangent rebuild helpers are local for now. They are expected to
move to a future shared
@carbonenginejs/core-mathpackage once that package exists.
JSON Graph
emit: "json" is the only public output mode. Square-bracketed fields are
conditional in the broader shared schema, but this OBJ format always emits the
mesh-side channel keys as arrays. Channels OBJ cannot provide are empty arrays:
Root
|-- grannyFileFormatRevision, grannyFileSource
|-- meshes: Mesh[]
| |-- name, minBounds, maxBounds
| |-- boneBindings: []
| |-- morphTargets: []
| |-- vertex: VertexChannels
| | |-- position, normal, tangent, binormal
| | |-- texcoord0, texcoord1
| | |-- blendIndice, blendWeight
| | `-- all channels are flat numeric arrays
| `-- indices: IndexGroup[]
| `-- name, bytesPerIndex, faces
|-- models: []
`-- animations: []IndexGroup.faces is a flat triangle-index array in groups of three. OBJ
polygons with more than three corners are fan-triangulated.
OBJ Coverage
This is deliberately tiny. It handles the mesh statements needed by the shared JSON mesh schema:
v x y zvt u vvn x y zf v,f v/vt,f v//vn, andf v/vt/vn- positive and negative OBJ indices
o,g, andusemtlnames for mesh and index-group naming
Comments and unsupported statements are ignored.
Options
emit:"json"default. Other values currently throw.source: default"memory". Written togrannyFileSourceand used in error messages.packTangents: defaultfalse.trueconverts explicit normal/tangent/ binormal data into a packed four-componenttangentchannel for GR2-style shader inputs. Missing normals, tangents, and binormals are generated as needed; missing UVs or triangle indices still throw.uvHandedness:"right"default."right"emits generated binormals asnormal x tangent;"left"flips generated binormals for V-flipped or opposite-handed shader paths. This affectsrebuildMissingBiNormalsand the basis generated forpackTangents; it does not mutatevertex.texcoord0.rebuildMissingNormals: defaultfalse.truegenerates missingnormalchannels fromvertex.positionand triangle indices.rebuildMissingTangents: defaultfalse.truegenerates missingtangentchannels fromvertex.position,vertex.normal,vertex.texcoord0, and triangle indices.rebuildMissingBiNormals: defaultfalse.truegenerates missingbinormalchannels fromvertex.normalandvertex.tangent.- Missing-channel rebuild options also accept rule functions. They receive
{ format, options, raw, json, mesh, meshIndex, feature, channel }and must returntrueorfalse. packTangentsalso accepts the same rule-function shape.classes: optional fornew CjsFormatObj(options),Read, and staticread. Accepted keys areRoot,Mesh, andIndexGroup, exposed asCjsFormatObj.CLASS_KEYS.
Tests
npm testTests are fully self-contained and use inline OBJ text. They do not require local asset folders, network access, or game files.
License
MIT (see LICENSE and NOTICE).
This package contains no CarbonEngine or Fenris Creations (CCP Games) code. Its output shape targets the shared CarbonEngineJS JSON mesh schema used for CarbonEngine interoperability. The optional packed tangent conversion targets the CarbonEngineJS/GR2 tangent-frame convention derived from observed shader behavior; shader-path correctness should still be verified against known assets or visual tests where available.
