npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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

Install

npm install @carbonenginejs/format-obj

Public 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-obj because 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 CjsFormatObj itself, not on hydrated CarbonClass instances.
  • src/CjsFormatObj.js is the public format boundary. Read and future write commands belong on this class; parser and geometry helpers live under src/core.
  • Read / static read return the shared JSON schema. emit: "raw" is not exposed yet because this package's parser state is intentionally internal.
  • ToJSON / static toJSON converts format output to JSON-compatible data. It is not an OBJ or GR2 writer and does not return JSON text.
  • packTangents is a conversion option. It builds any missing basis channels it needs, packs them into a four-component tangent channel, and clears normal / binormal so the mesh matches the packed GR2-style tangent shape.
  • uvHandedness controls 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-types package.
  • Normal and tangent rebuild helpers are local for now. They are expected to move to a future shared @carbonenginejs/core-math package 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 z
  • vt u v
  • vn x y z
  • f v, f v/vt, f v//vn, and f v/vt/vn
  • positive and negative OBJ indices
  • o, g, and usemtl names for mesh and index-group naming

Comments and unsupported statements are ignored.

Options

  • emit: "json" default. Other values currently throw.
  • source: default "memory". Written to grannyFileSource and used in error messages.
  • packTangents: default false. true converts explicit normal/tangent/ binormal data into a packed four-component tangent channel 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 as normal x tangent; "left" flips generated binormals for V-flipped or opposite-handed shader paths. This affects rebuildMissingBiNormals and the basis generated for packTangents; it does not mutate vertex.texcoord0.
  • rebuildMissingNormals: default false. true generates missing normal channels from vertex.position and triangle indices.
  • rebuildMissingTangents: default false. true generates missing tangent channels from vertex.position, vertex.normal, vertex.texcoord0, and triangle indices.
  • rebuildMissingBiNormals: default false. true generates missing binormal channels from vertex.normal and vertex.tangent.
  • Missing-channel rebuild options also accept rule functions. They receive { format, options, raw, json, mesh, meshIndex, feature, channel } and must return true or false.
  • packTangents also accepts the same rule-function shape.
  • classes: optional for new CjsFormatObj(options), Read, and static read. Accepted keys are Root, Mesh, and IndexGroup, exposed as CjsFormatObj.CLASS_KEYS.

Tests

npm test

Tests 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.