@hraness/slopcamera 3.3.2 → 3.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -25
- package/apps/desktop/application/directing-contract.ts +15 -3
- package/apps/desktop/application/directing-plan.ts +2 -1
- package/apps/desktop/application/operation.ts +1 -1
- package/apps/desktop/cli/args.ts +1 -1
- package/apps/desktop/cli/cinema-renderer.ts +9 -6
- package/apps/desktop/cli/commands.ts +8 -1
- package/apps/desktop/cli/directing-blob.ts +17 -12
- package/apps/desktop/cli/directing-media.ts +14 -4
- package/apps/desktop/cli/directing-quote.ts +29 -11
- package/apps/desktop/cli/directing-service.ts +6 -2
- package/apps/desktop/cli/gateway-media-catalog.ts +57 -0
- package/apps/desktop/cli/gateway-media-service.ts +12 -2
- package/apps/desktop/cli/help.ts +4 -4
- package/apps/desktop/cli/main.ts +1 -1
- package/apps/desktop/cli/project-renderer.ts +23 -9
- package/apps/desktop/cli/spatial-scene-service.ts +1 -1
- package/apps/desktop/dist/cli/main.js +254 -248
- package/apps/desktop/html-overlay/spatial-splat-runtime.ts +6 -0
- package/dist/cli.js +1 -1
- package/dist/code/index.js +4 -4
- package/dist/{index-gs48afpt.js → index-c8jpst4g.js} +2 -2
- package/dist/index-z1kd1x8j.js +3 -0
- package/dist/index.js +1 -1
- package/docs/README.md +6 -3
- package/docs/studio.md +63 -3
- package/package.json +13 -7
- package/skills/slopcamera/references/directing-video.md +3 -3
- package/skills/slopcamera/references/educational-video.md +1 -1
- package/skills/slopcamera/references/install.md +1 -1
- package/skills/slopcamera/references/parametric-design.md +5 -1
- package/skills/slopcamera/references/scene-building.md +2 -0
- package/skills/slopcamera/references/workflows-sdk.md +1 -1
- package/src/spatial-scene/geometry.ts +88 -35
- package/src/spatial-scene/parametric.ts +42 -15
- package/src/version.ts +1 -1
- package/dist/index-zhg36tf9.js +0 -3
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { SpatialAssetFactsV1Schema, SpatialCollisionProxySchema, type SpatialAssetFactsV1, type SpatialCollisionProxy, type SpatialRetainedArtifact } from "./asset-admission.js"
|
|
19
19
|
import { mulberry32 } from "./build.js"
|
|
20
20
|
import {
|
|
21
|
-
SPATIAL_GEOMETRY_PROFILE, SpatialGeometryGraphSchema, emitSpatialGeometryGlb, evaluateSpatialGeometry, estimateSpatialGeometryGraph, parseSpatialGeometryGraph,
|
|
21
|
+
SPATIAL_GEOMETRY_PROFILE, SPATIAL_GEOMETRY_BOOLEAN_COMPILER, SpatialGeometryGraphSchema, emitSpatialGeometryGlb, evaluateSpatialGeometry, estimateSpatialGeometryGraph, parseSpatialGeometryGraph,
|
|
22
22
|
type SpatialGeometryMesh,
|
|
23
23
|
} from "./geometry.js"
|
|
24
24
|
import {
|
|
@@ -68,6 +68,8 @@ const specVec3 = z.tuple([coordinate, coordinate, coordinate])
|
|
|
68
68
|
const editable = z.array(z.enum(["color", "opacity", "transform"])).max(3).optional()
|
|
69
69
|
const partPlacement = { transform: SpatialTransformSchema.optional(), editable, castShadow: z.boolean().optional(), receiveShadow: z.boolean().optional() }
|
|
70
70
|
|
|
71
|
+
/** center is [horizontal center, sill height from the wall base]. Arch height
|
|
72
|
+
* includes the semicircular crown, whose radius is half its width. */
|
|
71
73
|
const opening = z.discriminatedUnion("kind", [
|
|
72
74
|
z.strictObject({ kind: z.literal("rect"), center: specVec2, width: meter, height: meter }),
|
|
73
75
|
z.strictObject({ kind: z.literal("arch"), center: specVec2, width: meter, height: meter }),
|
|
@@ -155,6 +157,9 @@ function boxBounds(bounds: Bounds): SpatialCollisionProxy {
|
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
const LOD1_DISTANCE_M = 25
|
|
160
|
+
// Wall lowering changed while the retained GLB/facts format remains v1. Keep
|
|
161
|
+
// the revision local to this planner so unrelated generators retain identity.
|
|
162
|
+
export const SPATIAL_PARAMETRIC_WALL_COMPILER = "slopcamera.parametric-wall-v2" as const
|
|
158
163
|
|
|
159
164
|
function planWall(spec: Extract<SpatialParametricSpec, { kind: "wall" }>): PartPlan[] {
|
|
160
165
|
const { length, height, thickness } = spec
|
|
@@ -165,19 +170,33 @@ function planWall(spec: Extract<SpatialParametricSpec, { kind: "wall" }>): PartP
|
|
|
165
170
|
if (cx - item.width / 2 < -length / 2 || cx + item.width / 2 > length / 2 || baseY < 0 || baseY + item.height > height) {
|
|
166
171
|
pfail(`Wall opening ${index} must stay inside the wall rectangle.`, "spec.openings")
|
|
167
172
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
const cutterId = `cut${index}`
|
|
174
|
+
// The body is still centered until the final lift. Authored opening Y is
|
|
175
|
+
// measured from its base, so cutters must share the body's local frame.
|
|
176
|
+
let cutterY = baseY + item.height / 2 - height / 2
|
|
172
177
|
if (item.kind === "arch") {
|
|
173
178
|
const radius = item.width / 2
|
|
174
179
|
if (radius > item.height) pfail(`Arch opening ${index} rise exceeds its height.`, "spec.openings")
|
|
175
|
-
const
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
const springline = item.height - radius
|
|
181
|
+
// One extruded cutter has a flat sill and a semicircular crown. A full
|
|
182
|
+
// circle would cut below a shallow opening, while a full-height box
|
|
183
|
+
// would remove the masonry that should remain at the arch shoulders.
|
|
184
|
+
const points: number[][] = [[-radius, 0], [radius, 0]]
|
|
185
|
+
if (springline > 0) points.push([radius, springline])
|
|
186
|
+
for (let segment = 1; segment <= 12; segment++) {
|
|
187
|
+
const angle = Math.PI * segment / 12
|
|
188
|
+
points.push(segment === 12 ? [-radius, springline] : [radius * Math.cos(angle), springline + radius * Math.sin(angle)])
|
|
189
|
+
}
|
|
190
|
+
// At height == radius the arc ends at the first profile point.
|
|
191
|
+
if (springline === 0) points.pop()
|
|
192
|
+
cutterNodes.push({ id: `${cutterId}profile`, kind: "profile", points })
|
|
193
|
+
cutterNodes.push({ id: cutterId, kind: "extrude", profile: `${cutterId}profile`, depth: thickness * 4 })
|
|
194
|
+
cutterY = baseY - height / 2
|
|
195
|
+
} else {
|
|
196
|
+
cutterNodes.push({ id: cutterId, kind: "box", size: [item.width, item.height, thickness * 4] })
|
|
180
197
|
}
|
|
198
|
+
cutterNodes.push({ id: `${cutterId}p`, kind: "transform", input: cutterId, transform: { position: [cx, cutterY, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] } })
|
|
199
|
+
cutterIds.push(`${cutterId}p`)
|
|
181
200
|
}
|
|
182
201
|
const nodes: unknown[] = [{ id: "body", kind: "box", size: [length, height, thickness] }]
|
|
183
202
|
let output = "body"
|
|
@@ -534,6 +553,8 @@ export interface SpatialParametricArtifact { readonly assetId: string; readonly
|
|
|
534
553
|
export interface SpatialParametricFacts { readonly manifest: SpatialAssetManifest; readonly facts: SpatialAssetFactsV1 }
|
|
535
554
|
export interface SpatialParametricReceipt {
|
|
536
555
|
readonly name?: string
|
|
556
|
+
readonly compiler?: typeof SPATIAL_PARAMETRIC_WALL_COMPILER
|
|
557
|
+
readonly booleanCompiler?: typeof SPATIAL_GEOMETRY_BOOLEAN_COMPILER
|
|
537
558
|
readonly kind: "slopcamera.spatial-parametric-receipt"
|
|
538
559
|
readonly schemaVersion: 1
|
|
539
560
|
readonly generatorId: string
|
|
@@ -580,14 +601,19 @@ export function emitSpatialParametric(input: unknown): SpatialParametricOutput {
|
|
|
580
601
|
outputs: [...outputs],
|
|
581
602
|
})
|
|
582
603
|
}
|
|
583
|
-
const sourceSha256 = spatialValueSha256({ domain: "slopcamera.parametric-source.v1", profile: SPATIAL_GEOMETRY_PROFILE, kind: spec.kind })
|
|
584
|
-
const parametersSha256 = spatialGeneratorParametersSha256(spec)
|
|
585
|
-
const specSha256 = spatialValueSha256({ domain: "slopcamera.parametric-spec.v1", spec })
|
|
586
|
-
const seed = request.seed ?? deriveSpatialGeneratorSeed(sourceSha256)
|
|
587
|
-
const runtimeSha256 = spatialValueSha256({ domain: "slopcamera.parametric-runtime.v1", profile: SPATIAL_GEOMETRY_PROFILE })
|
|
588
604
|
const plans = PLANNERS[spec.kind](spec as never)
|
|
589
605
|
if (plans.length > SPATIAL_PARAMETRIC_LIMITS.parts) pfail("Spec expands beyond the part budget.", "spec")
|
|
590
606
|
validatePartMaterials(plans)
|
|
607
|
+
const usesBoolean = plans.some(part => part.lods.some(lod => parseSpatialGeometryGraph(lod.graph).nodes.some(node => node.kind === "boolean")))
|
|
608
|
+
const compiler: Pick<SpatialParametricReceipt, "compiler" | "booleanCompiler"> = {
|
|
609
|
+
...(spec.kind === "wall" ? { compiler: SPATIAL_PARAMETRIC_WALL_COMPILER } : {}),
|
|
610
|
+
...(usesBoolean ? { booleanCompiler: SPATIAL_GEOMETRY_BOOLEAN_COMPILER } : {}),
|
|
611
|
+
}
|
|
612
|
+
const sourceSha256 = spatialValueSha256({ domain: "slopcamera.parametric-source.v1", profile: SPATIAL_GEOMETRY_PROFILE, kind: spec.kind, ...compiler })
|
|
613
|
+
const parametersSha256 = spatialGeneratorParametersSha256(spec)
|
|
614
|
+
const specSha256 = spatialValueSha256({ domain: "slopcamera.parametric-spec.v1", spec })
|
|
615
|
+
const seed = request.seed ?? deriveSpatialGeneratorSeed(sourceSha256)
|
|
616
|
+
const runtimeSha256 = spatialValueSha256({ domain: "slopcamera.parametric-runtime.v1", profile: SPATIAL_GEOMETRY_PROFILE, ...compiler })
|
|
591
617
|
const manifests: SpatialAssetManifest[] = []
|
|
592
618
|
const artifacts: SpatialParametricArtifact[] = []
|
|
593
619
|
const entities: SpatialEntity[] = []
|
|
@@ -682,6 +708,7 @@ export function emitSpatialParametric(input: unknown): SpatialParametricOutput {
|
|
|
682
708
|
generatorId, specSha256, parametersSha256, seed,
|
|
683
709
|
...(request.name === undefined ? {} : { name: request.name }),
|
|
684
710
|
profile: SPATIAL_GEOMETRY_PROFILE,
|
|
711
|
+
...compiler,
|
|
685
712
|
assets: receiptAssets,
|
|
686
713
|
entities: entities.map(entity => entity.entityId).sort(),
|
|
687
714
|
native: retainedArtifacts.map(artifact => ({ requestSha256: artifact.requestSha256, receiptSha256: artifact.receiptSha256 })),
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SLOPCAMERA_VERSION = "3.3.
|
|
1
|
+
export const SLOPCAMERA_VERSION = "3.3.4" as const
|