|
|
|
@@ -0,0 +1,403 @@
|
|
|
|
|
import dedent from 'dedent'
|
|
|
|
|
import { z } from 'zod'
|
|
|
|
|
import { BaseNode, nodeType, objectId } from '../base'
|
|
|
|
|
import { MaterialSchema } from '../material'
|
|
|
|
|
|
|
|
|
|
export const ColumnStyle = z.enum([
|
|
|
|
|
'plain',
|
|
|
|
|
'faceted',
|
|
|
|
|
'fluted',
|
|
|
|
|
'lathe-turned',
|
|
|
|
|
'dravidian-carved',
|
|
|
|
|
'cluster',
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
export const ColumnCrossSection = z.enum([
|
|
|
|
|
'round',
|
|
|
|
|
'square',
|
|
|
|
|
'rectangular',
|
|
|
|
|
'octagonal',
|
|
|
|
|
'sixteen-sided',
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
export const ColumnShaftProfile = z.enum(['straight', 'tapered', 'bulged', 'baluster', 'hourglass'])
|
|
|
|
|
|
|
|
|
|
export const ColumnShaftDetail = z.enum(['none', 'fluted', 'spiral', 'panelled', 'lathe-turned'])
|
|
|
|
|
|
|
|
|
|
export const ColumnPanelShape = z.enum(['rectangle', 'arched', 'diamond'])
|
|
|
|
|
|
|
|
|
|
export const ColumnBaseStyle = z.enum([
|
|
|
|
|
'none',
|
|
|
|
|
'simple-square',
|
|
|
|
|
'round-rings',
|
|
|
|
|
'square-plinth',
|
|
|
|
|
'stepped-square',
|
|
|
|
|
'lotus',
|
|
|
|
|
'ribbed-lotus',
|
|
|
|
|
'panelled-pedestal',
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
export const ColumnCapitalStyle = z.enum([
|
|
|
|
|
'none',
|
|
|
|
|
'simple',
|
|
|
|
|
'simple-slab',
|
|
|
|
|
'rounded',
|
|
|
|
|
'stepped',
|
|
|
|
|
'doric',
|
|
|
|
|
'volute',
|
|
|
|
|
'ionic-volute',
|
|
|
|
|
'leaf-carved',
|
|
|
|
|
'corinthian-leaf',
|
|
|
|
|
'south-indian-bracket',
|
|
|
|
|
'wood-bracket',
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
export const ColumnRingPlacement = z.enum(['ends', 'even', 'top', 'bottom'])
|
|
|
|
|
|
|
|
|
|
export const ColumnCarvingPlacement = z.enum(['shaft', 'base', 'capital', 'all'])
|
|
|
|
|
|
|
|
|
|
export type ColumnStyle = z.infer<typeof ColumnStyle>
|
|
|
|
|
export type ColumnCrossSection = z.infer<typeof ColumnCrossSection>
|
|
|
|
|
export type ColumnShaftProfile = z.infer<typeof ColumnShaftProfile>
|
|
|
|
|
export type ColumnShaftDetail = z.infer<typeof ColumnShaftDetail>
|
|
|
|
|
export type ColumnPanelShape = z.infer<typeof ColumnPanelShape>
|
|
|
|
|
export type ColumnBaseStyle = z.infer<typeof ColumnBaseStyle>
|
|
|
|
|
export type ColumnCapitalStyle = z.infer<typeof ColumnCapitalStyle>
|
|
|
|
|
export type ColumnRingPlacement = z.infer<typeof ColumnRingPlacement>
|
|
|
|
|
export type ColumnCarvingPlacement = z.infer<typeof ColumnCarvingPlacement>
|
|
|
|
|
|
|
|
|
|
export const ColumnNode = BaseNode.extend({
|
|
|
|
|
id: objectId('column'),
|
|
|
|
|
type: nodeType('column'),
|
|
|
|
|
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
|
|
|
|
|
rotation: z.number().default(0),
|
|
|
|
|
style: ColumnStyle.default('plain'),
|
|
|
|
|
crossSection: ColumnCrossSection.default('round'),
|
|
|
|
|
height: z.number().positive().default(2.8),
|
|
|
|
|
radius: z.number().positive().default(0.22),
|
|
|
|
|
width: z.number().positive().default(0.44),
|
|
|
|
|
depth: z.number().positive().default(0.44),
|
|
|
|
|
edgeSoftness: z.number().min(0).max(0.12).default(0.025),
|
|
|
|
|
baseHeight: z.number().min(0).default(0.18),
|
|
|
|
|
capitalHeight: z.number().min(0).default(0.18),
|
|
|
|
|
shaftProfile: ColumnShaftProfile.default('straight'),
|
|
|
|
|
shaftTaper: z.number().min(0).max(0.85).default(0),
|
|
|
|
|
shaftBulge: z.number().min(-0.5).max(0.8).default(0),
|
|
|
|
|
shaftStartScale: z.number().min(0.2).max(2).default(0.72),
|
|
|
|
|
shaftEndScale: z.number().min(0.2).max(2).default(0.72),
|
|
|
|
|
shaftSegmentCount: z.number().int().min(1).max(64).default(24),
|
|
|
|
|
shaftCornerRadius: z.number().min(0).max(0.3).default(0.035),
|
|
|
|
|
shaftDetail: ColumnShaftDetail.default('none'),
|
|
|
|
|
baseStyle: ColumnBaseStyle.default('round-rings'),
|
|
|
|
|
baseWidthScale: z.number().min(0.4).max(3).default(1.24),
|
|
|
|
|
baseDepthScale: z.number().min(0.4).max(3).default(1.24),
|
|
|
|
|
baseTierCount: z.number().int().min(1).max(8).default(3),
|
|
|
|
|
baseStepSpread: z.number().min(0).max(1).default(0.42),
|
|
|
|
|
basePlinthHeightRatio: z.number().min(0.2).max(0.7).default(0.44),
|
|
|
|
|
baseRoundBandScale: z.number().min(0.5).max(1.2).default(0.92),
|
|
|
|
|
baseNeckScale: z.number().min(0.35).max(1).default(0.72),
|
|
|
|
|
baseRoundBandCount: z.number().int().min(0).max(16).default(3),
|
|
|
|
|
baseRibCount: z.number().int().min(0).max(48).default(0),
|
|
|
|
|
baseCarvingLevel: z.number().int().min(0).max(4).default(0),
|
|
|
|
|
basePanelInset: z.number().min(0).max(0.1).default(0.02),
|
|
|
|
|
capitalStyle: ColumnCapitalStyle.default('simple'),
|
|
|
|
|
capitalWidthScale: z.number().min(0.4).max(3).default(1.46),
|
|
|
|
|
capitalDepthScale: z.number().min(0.4).max(3).default(1.46),
|
|
|
|
|
capitalTierCount: z.number().int().min(1).max(8).default(3),
|
|
|
|
|
capitalStepSpread: z.number().min(0).max(1).default(0.42),
|
|
|
|
|
capitalBandCount: z.number().int().min(0).max(16).default(2),
|
|
|
|
|
voluteSize: z.number().min(0.02).max(0.3).default(0.08),
|
|
|
|
|
voluteCount: z.number().int().min(0).max(8).default(4),
|
|
|
|
|
leafCount: z.number().int().min(0).max(48).default(18),
|
|
|
|
|
leafRows: z.number().int().min(0).max(4).default(2),
|
|
|
|
|
bracketDepth: z.number().min(0).max(1.5).default(0.35),
|
|
|
|
|
bracketTierCount: z.number().int().min(0).max(8).default(3),
|
|
|
|
|
pendantCount: z.number().int().min(0).max(16).default(0),
|
|
|
|
|
capitalCarvingLevel: z.number().int().min(0).max(4).default(0),
|
|
|
|
|
ringCount: z.number().int().min(0).max(16).default(0),
|
|
|
|
|
ringPlacement: ColumnRingPlacement.default('ends'),
|
|
|
|
|
ringThickness: z.number().min(0.01).max(0.14).default(0.055),
|
|
|
|
|
ringSpread: z.number().min(0.04).max(0.45).default(0.16),
|
|
|
|
|
fluteCount: z.number().int().min(0).max(32).default(0),
|
|
|
|
|
fluteDepth: z.number().min(0.005).max(0.08).default(0.02),
|
|
|
|
|
fluteWidth: z.number().min(0.005).max(0.1).default(0.02),
|
|
|
|
|
spiralTwist: z.number().min(-3).max(3).default(0),
|
|
|
|
|
spiralRibCount: z.number().int().min(0).max(32).default(0),
|
|
|
|
|
panelCount: z.number().int().min(0).max(24).default(0),
|
|
|
|
|
panelInsetDepth: z.number().min(0).max(0.1).default(0.02),
|
|
|
|
|
panelShape: ColumnPanelShape.default('rectangle'),
|
|
|
|
|
latheRingCount: z.number().int().min(0).max(32).default(0),
|
|
|
|
|
latheRingSpacing: ColumnRingPlacement.default('ends'),
|
|
|
|
|
carvingLevel: z.number().int().min(0).max(4).default(0),
|
|
|
|
|
carvingPlacement: ColumnCarvingPlacement.default('capital'),
|
|
|
|
|
lowerBandEnabled: z.boolean().default(false),
|
|
|
|
|
lowerBandHeight: z.number().min(0).max(1).default(0.24),
|
|
|
|
|
lowerBandCarvingLevel: z.number().int().min(0).max(4).default(0),
|
|
|
|
|
dentilCount: z.number().int().min(0).max(48).default(0),
|
|
|
|
|
beadCount: z.number().int().min(0).max(64).default(0),
|
|
|
|
|
material: MaterialSchema.optional(),
|
|
|
|
|
materialPreset: z.string().optional(),
|
|
|
|
|
}).describe(dedent`
|
|
|
|
|
Column node - used to represent structural or decorative pillars/columns.
|
|
|
|
|
- style: visual approach such as plain, lathe-turned, carved, or cluster
|
|
|
|
|
- crossSection: plan shape used by the procedural renderer
|
|
|
|
|
- height/radius/width/depth: primary dimensions in meters
|
|
|
|
|
- edgeSoftness: bevel radius for square/plinth/block edges
|
|
|
|
|
- shaftProfile/shaftDetail: profile and surface treatment of the shaft
|
|
|
|
|
- shaftCornerRadius: rounded-corner radius for square/rectangular shaft cross-sections
|
|
|
|
|
- baseStyle/capitalStyle: procedural base and top treatment with tier/detail controls
|
|
|
|
|
- baseHeight/capitalHeight: bottom and top block proportions
|
|
|
|
|
- ring/flute/spiral/panel/lathe/carving fields: procedural detail controls
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
|
|
export const COLUMN_PRESETS = {
|
|
|
|
|
basicPillar: {
|
|
|
|
|
label: 'Straight Round',
|
|
|
|
|
style: 'plain',
|
|
|
|
|
crossSection: 'round',
|
|
|
|
|
height: 2.9,
|
|
|
|
|
radius: 0.22,
|
|
|
|
|
width: 0.44,
|
|
|
|
|
depth: 0.44,
|
|
|
|
|
edgeSoftness: 0.025,
|
|
|
|
|
baseHeight: 0.22,
|
|
|
|
|
capitalHeight: 0.2,
|
|
|
|
|
shaftProfile: 'straight',
|
|
|
|
|
shaftTaper: 0,
|
|
|
|
|
shaftBulge: 0,
|
|
|
|
|
shaftStartScale: 0.72,
|
|
|
|
|
shaftEndScale: 0.72,
|
|
|
|
|
shaftSegmentCount: 1,
|
|
|
|
|
shaftCornerRadius: 0.035,
|
|
|
|
|
shaftDetail: 'none',
|
|
|
|
|
baseStyle: 'square-plinth',
|
|
|
|
|
baseWidthScale: 1.26,
|
|
|
|
|
baseDepthScale: 1.26,
|
|
|
|
|
baseTierCount: 1,
|
|
|
|
|
baseStepSpread: 0.34,
|
|
|
|
|
basePlinthHeightRatio: 0.44,
|
|
|
|
|
baseRoundBandScale: 0.92,
|
|
|
|
|
baseNeckScale: 0.72,
|
|
|
|
|
baseRoundBandCount: 0,
|
|
|
|
|
baseRibCount: 0,
|
|
|
|
|
baseCarvingLevel: 0,
|
|
|
|
|
capitalStyle: 'simple-slab',
|
|
|
|
|
capitalWidthScale: 1.22,
|
|
|
|
|
capitalDepthScale: 1.22,
|
|
|
|
|
capitalTierCount: 1,
|
|
|
|
|
capitalStepSpread: 0.34,
|
|
|
|
|
capitalBandCount: 0,
|
|
|
|
|
capitalCarvingLevel: 0,
|
|
|
|
|
ringCount: 0,
|
|
|
|
|
ringSpread: 0.16,
|
|
|
|
|
fluteCount: 0,
|
|
|
|
|
spiralTwist: 0,
|
|
|
|
|
spiralRibCount: 0,
|
|
|
|
|
panelCount: 0,
|
|
|
|
|
latheRingCount: 0,
|
|
|
|
|
carvingLevel: 0,
|
|
|
|
|
lowerBandEnabled: false,
|
|
|
|
|
dentilCount: 0,
|
|
|
|
|
beadCount: 0,
|
|
|
|
|
},
|
|
|
|
|
squarePillar: {
|
|
|
|
|
label: 'Square Block',
|
|
|
|
|
style: 'faceted',
|
|
|
|
|
crossSection: 'square',
|
|
|
|
|
height: 2.9,
|
|
|
|
|
radius: 0.24,
|
|
|
|
|
width: 0.48,
|
|
|
|
|
depth: 0.48,
|
|
|
|
|
edgeSoftness: 0.035,
|
|
|
|
|
baseHeight: 0.22,
|
|
|
|
|
capitalHeight: 0.2,
|
|
|
|
|
shaftProfile: 'straight',
|
|
|
|
|
shaftTaper: 0,
|
|
|
|
|
shaftBulge: 0,
|
|
|
|
|
shaftStartScale: 0.72,
|
|
|
|
|
shaftEndScale: 0.72,
|
|
|
|
|
shaftSegmentCount: 1,
|
|
|
|
|
shaftCornerRadius: 0.045,
|
|
|
|
|
shaftDetail: 'none',
|
|
|
|
|
baseStyle: 'simple-square',
|
|
|
|
|
baseWidthScale: 1.18,
|
|
|
|
|
baseDepthScale: 1.18,
|
|
|
|
|
baseTierCount: 1,
|
|
|
|
|
baseStepSpread: 0.34,
|
|
|
|
|
basePlinthHeightRatio: 0.44,
|
|
|
|
|
baseRoundBandScale: 0.92,
|
|
|
|
|
baseNeckScale: 0.72,
|
|
|
|
|
baseRoundBandCount: 0,
|
|
|
|
|
baseRibCount: 0,
|
|
|
|
|
baseCarvingLevel: 0,
|
|
|
|
|
capitalStyle: 'simple-slab',
|
|
|
|
|
capitalWidthScale: 1.18,
|
|
|
|
|
capitalDepthScale: 1.18,
|
|
|
|
|
capitalTierCount: 1,
|
|
|
|
|
capitalStepSpread: 0.34,
|
|
|
|
|
capitalBandCount: 0,
|
|
|
|
|
capitalCarvingLevel: 0,
|
|
|
|
|
ringCount: 0,
|
|
|
|
|
ringSpread: 0.16,
|
|
|
|
|
fluteCount: 0,
|
|
|
|
|
spiralTwist: 0,
|
|
|
|
|
spiralRibCount: 0,
|
|
|
|
|
panelCount: 0,
|
|
|
|
|
latheRingCount: 0,
|
|
|
|
|
carvingLevel: 0,
|
|
|
|
|
lowerBandEnabled: false,
|
|
|
|
|
dentilCount: 0,
|
|
|
|
|
beadCount: 0,
|
|
|
|
|
},
|
|
|
|
|
taperedPillar: {
|
|
|
|
|
label: 'Tapered Round',
|
|
|
|
|
style: 'plain',
|
|
|
|
|
crossSection: 'round',
|
|
|
|
|
height: 3,
|
|
|
|
|
radius: 0.23,
|
|
|
|
|
width: 0.46,
|
|
|
|
|
depth: 0.46,
|
|
|
|
|
edgeSoftness: 0.025,
|
|
|
|
|
baseHeight: 0.23,
|
|
|
|
|
capitalHeight: 0.2,
|
|
|
|
|
shaftProfile: 'tapered',
|
|
|
|
|
shaftTaper: 0.14,
|
|
|
|
|
shaftBulge: 0,
|
|
|
|
|
shaftStartScale: 0.82,
|
|
|
|
|
shaftEndScale: 0.72,
|
|
|
|
|
shaftSegmentCount: 32,
|
|
|
|
|
shaftCornerRadius: 0.035,
|
|
|
|
|
shaftDetail: 'none',
|
|
|
|
|
baseStyle: 'square-plinth',
|
|
|
|
|
baseWidthScale: 1.26,
|
|
|
|
|
baseDepthScale: 1.26,
|
|
|
|
|
baseTierCount: 1,
|
|
|
|
|
baseStepSpread: 0.34,
|
|
|
|
|
basePlinthHeightRatio: 0.44,
|
|
|
|
|
baseRoundBandScale: 0.92,
|
|
|
|
|
baseNeckScale: 0.72,
|
|
|
|
|
baseRoundBandCount: 0,
|
|
|
|
|
baseRibCount: 0,
|
|
|
|
|
baseCarvingLevel: 0,
|
|
|
|
|
capitalStyle: 'simple-slab',
|
|
|
|
|
capitalWidthScale: 1.22,
|
|
|
|
|
capitalDepthScale: 1.22,
|
|
|
|
|
capitalTierCount: 1,
|
|
|
|
|
capitalStepSpread: 0.34,
|
|
|
|
|
capitalBandCount: 0,
|
|
|
|
|
capitalCarvingLevel: 0,
|
|
|
|
|
ringCount: 0,
|
|
|
|
|
ringSpread: 0.16,
|
|
|
|
|
fluteCount: 0,
|
|
|
|
|
spiralTwist: 0,
|
|
|
|
|
spiralRibCount: 0,
|
|
|
|
|
panelCount: 0,
|
|
|
|
|
latheRingCount: 0,
|
|
|
|
|
carvingLevel: 0,
|
|
|
|
|
lowerBandEnabled: false,
|
|
|
|
|
dentilCount: 0,
|
|
|
|
|
beadCount: 0,
|
|
|
|
|
},
|
|
|
|
|
bulgedPillar: {
|
|
|
|
|
label: 'Soft Bulged',
|
|
|
|
|
style: 'plain',
|
|
|
|
|
crossSection: 'round',
|
|
|
|
|
height: 2.9,
|
|
|
|
|
radius: 0.22,
|
|
|
|
|
width: 0.44,
|
|
|
|
|
depth: 0.44,
|
|
|
|
|
edgeSoftness: 0.025,
|
|
|
|
|
baseHeight: 0.22,
|
|
|
|
|
capitalHeight: 0.2,
|
|
|
|
|
shaftProfile: 'bulged',
|
|
|
|
|
shaftTaper: 0,
|
|
|
|
|
shaftBulge: 0.12,
|
|
|
|
|
shaftStartScale: 0.68,
|
|
|
|
|
shaftEndScale: 0.68,
|
|
|
|
|
shaftSegmentCount: 32,
|
|
|
|
|
shaftCornerRadius: 0.035,
|
|
|
|
|
shaftDetail: 'none',
|
|
|
|
|
baseStyle: 'square-plinth',
|
|
|
|
|
baseWidthScale: 1.24,
|
|
|
|
|
baseDepthScale: 1.24,
|
|
|
|
|
baseTierCount: 1,
|
|
|
|
|
baseStepSpread: 0.34,
|
|
|
|
|
basePlinthHeightRatio: 0.44,
|
|
|
|
|
baseRoundBandScale: 0.92,
|
|
|
|
|
baseNeckScale: 0.72,
|
|
|
|
|
baseRoundBandCount: 0,
|
|
|
|
|
baseRibCount: 0,
|
|
|
|
|
baseCarvingLevel: 0,
|
|
|
|
|
capitalStyle: 'simple-slab',
|
|
|
|
|
capitalWidthScale: 1.2,
|
|
|
|
|
capitalDepthScale: 1.2,
|
|
|
|
|
capitalTierCount: 1,
|
|
|
|
|
capitalStepSpread: 0.34,
|
|
|
|
|
capitalBandCount: 0,
|
|
|
|
|
capitalCarvingLevel: 0,
|
|
|
|
|
ringCount: 0,
|
|
|
|
|
ringSpread: 0.16,
|
|
|
|
|
fluteCount: 0,
|
|
|
|
|
spiralTwist: 0,
|
|
|
|
|
spiralRibCount: 0,
|
|
|
|
|
panelCount: 0,
|
|
|
|
|
latheRingCount: 0,
|
|
|
|
|
carvingLevel: 0,
|
|
|
|
|
lowerBandEnabled: false,
|
|
|
|
|
dentilCount: 0,
|
|
|
|
|
beadCount: 0,
|
|
|
|
|
},
|
|
|
|
|
hourglassPillar: {
|
|
|
|
|
label: 'Hourglass',
|
|
|
|
|
style: 'plain',
|
|
|
|
|
crossSection: 'round',
|
|
|
|
|
height: 2.9,
|
|
|
|
|
radius: 0.22,
|
|
|
|
|
width: 0.44,
|
|
|
|
|
depth: 0.44,
|
|
|
|
|
edgeSoftness: 0.025,
|
|
|
|
|
baseHeight: 0.22,
|
|
|
|
|
capitalHeight: 0.2,
|
|
|
|
|
shaftProfile: 'hourglass',
|
|
|
|
|
shaftTaper: 0,
|
|
|
|
|
shaftBulge: 0.12,
|
|
|
|
|
shaftStartScale: 0.84,
|
|
|
|
|
shaftEndScale: 0.84,
|
|
|
|
|
shaftSegmentCount: 32,
|
|
|
|
|
shaftCornerRadius: 0.035,
|
|
|
|
|
shaftDetail: 'none',
|
|
|
|
|
baseStyle: 'square-plinth',
|
|
|
|
|
baseWidthScale: 1.24,
|
|
|
|
|
baseDepthScale: 1.24,
|
|
|
|
|
baseTierCount: 1,
|
|
|
|
|
baseStepSpread: 0.34,
|
|
|
|
|
basePlinthHeightRatio: 0.44,
|
|
|
|
|
baseRoundBandScale: 0.92,
|
|
|
|
|
baseNeckScale: 0.72,
|
|
|
|
|
baseRoundBandCount: 0,
|
|
|
|
|
baseRibCount: 0,
|
|
|
|
|
baseCarvingLevel: 0,
|
|
|
|
|
capitalStyle: 'simple-slab',
|
|
|
|
|
capitalWidthScale: 1.2,
|
|
|
|
|
capitalDepthScale: 1.2,
|
|
|
|
|
capitalTierCount: 1,
|
|
|
|
|
capitalStepSpread: 0.34,
|
|
|
|
|
capitalBandCount: 0,
|
|
|
|
|
capitalCarvingLevel: 0,
|
|
|
|
|
ringCount: 0,
|
|
|
|
|
ringSpread: 0.16,
|
|
|
|
|
fluteCount: 0,
|
|
|
|
|
spiralTwist: 0,
|
|
|
|
|
spiralRibCount: 0,
|
|
|
|
|
panelCount: 0,
|
|
|
|
|
latheRingCount: 0,
|
|
|
|
|
carvingLevel: 0,
|
|
|
|
|
lowerBandEnabled: false,
|
|
|
|
|
dentilCount: 0,
|
|
|
|
|
beadCount: 0,
|
|
|
|
|
},
|
|
|
|
|
} as const satisfies Record<string, { label: string } & Partial<z.input<typeof ColumnNode>>>
|
|
|
|
|
|
|
|
|
|
export type ColumnPresetId = keyof typeof COLUMN_PRESETS
|
|
|
|
|
|
|
|
|
|
export type ColumnNode = z.infer<typeof ColumnNode>
|