Reshape the sack so it stops being an amphora
The profile put its widest point a quarter of the way up and narrowed from there all the way to the neck, which is the silhouette of a vase. A filled sack does close to the opposite: it SPREADS where it meets the ground, because the grain settles and cloth has no stiffness of its own, then runs nearly parallel up most of its height, and gathers in sharply only where the cord is tied. Almost the entire difference between the two shapes lives in the bottom level and in where the taper starts. With the body right, the collar was what still read as a vessel: it opened out to 0.46 of the radius over a fifth of the sack's height, which is the mouth of a bottle. Above the tie there should be a hand's width of gathered cloth and no flare to speak of. 27 models, 18481 triangles, all checks pass, 0 floating cases.
This commit is contained in:
parent
6bae10f593
commit
82844abc3e
3 changed files with 76 additions and 50 deletions
|
|
@ -67,7 +67,7 @@
|
||||||
"address": "@medieval-kit/wooden-barrel",
|
"address": "@medieval-kit/wooden-barrel",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.787Z",
|
"installedAt": "2026-08-22T07:04:36.921Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-barrel\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-barrel\\model.ts",
|
||||||
|
|
@ -82,7 +82,7 @@
|
||||||
"address": "@medieval-kit/core",
|
"address": "@medieval-kit/core",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.769Z",
|
"installedAt": "2026-08-22T07:04:36.903Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\core\\geometry.ts",
|
"path": "src\\models\\medieval-kit\\core\\geometry.ts",
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
"address": "@medieval-kit/wooden-crate",
|
"address": "@medieval-kit/wooden-crate",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.791Z",
|
"installedAt": "2026-08-22T07:04:36.925Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-crate\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-crate\\model.ts",
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
"address": "@medieval-kit/kit",
|
"address": "@medieval-kit/kit",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.797Z",
|
"installedAt": "2026-08-22T07:04:36.931Z",
|
||||||
"files": [],
|
"files": [],
|
||||||
"dependencies": []
|
"dependencies": []
|
||||||
},
|
},
|
||||||
|
|
@ -152,7 +152,7 @@
|
||||||
"address": "@medieval-kit/iron-anvil",
|
"address": "@medieval-kit/iron-anvil",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.776Z",
|
"installedAt": "2026-08-22T07:04:36.910Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\iron-anvil\\model.ts",
|
"path": "src\\models\\medieval-kit\\iron-anvil\\model.ts",
|
||||||
|
|
@ -167,7 +167,7 @@
|
||||||
"address": "@medieval-kit/wooden-bucket",
|
"address": "@medieval-kit/wooden-bucket",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.789Z",
|
"installedAt": "2026-08-22T07:04:36.924Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-bucket\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-bucket\\model.ts",
|
||||||
|
|
@ -182,7 +182,7 @@
|
||||||
"address": "@medieval-kit/wooden-fence",
|
"address": "@medieval-kit/wooden-fence",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.792Z",
|
"installedAt": "2026-08-22T07:04:36.926Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-fence\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-fence\\model.ts",
|
||||||
|
|
@ -197,7 +197,7 @@
|
||||||
"address": "@medieval-kit/wooden-hoe",
|
"address": "@medieval-kit/wooden-hoe",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.793Z",
|
"installedAt": "2026-08-22T07:04:36.928Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-hoe\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-hoe\\model.ts",
|
||||||
|
|
@ -212,7 +212,7 @@
|
||||||
"address": "@medieval-kit/wooden-ladder",
|
"address": "@medieval-kit/wooden-ladder",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.794Z",
|
"installedAt": "2026-08-22T07:04:36.929Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-ladder\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-ladder\\model.ts",
|
||||||
|
|
@ -227,7 +227,7 @@
|
||||||
"address": "@medieval-kit/wooden-pitchfork",
|
"address": "@medieval-kit/wooden-pitchfork",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.795Z",
|
"installedAt": "2026-08-22T07:04:36.930Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-pitchfork\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-pitchfork\\model.ts",
|
||||||
|
|
@ -242,7 +242,7 @@
|
||||||
"address": "@medieval-kit/wooden-shovel",
|
"address": "@medieval-kit/wooden-shovel",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.796Z",
|
"installedAt": "2026-08-22T07:04:36.930Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-shovel\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-shovel\\model.ts",
|
||||||
|
|
@ -257,7 +257,7 @@
|
||||||
"address": "@medieval-kit/wooden-stool",
|
"address": "@medieval-kit/wooden-stool",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.797Z",
|
"installedAt": "2026-08-22T07:04:36.931Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-stool\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-stool\\model.ts",
|
||||||
|
|
@ -272,7 +272,7 @@
|
||||||
"address": "@medieval-kit/cart-wheel",
|
"address": "@medieval-kit/cart-wheel",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.772Z",
|
"installedAt": "2026-08-22T07:04:36.906Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\cart-wheel\\model.ts",
|
"path": "src\\models\\medieval-kit\\cart-wheel\\model.ts",
|
||||||
|
|
@ -287,7 +287,7 @@
|
||||||
"address": "@medieval-kit/log-pile",
|
"address": "@medieval-kit/log-pile",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.779Z",
|
"installedAt": "2026-08-22T07:04:36.915Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\log-pile\\model.ts",
|
"path": "src\\models\\medieval-kit\\log-pile\\model.ts",
|
||||||
|
|
@ -302,7 +302,7 @@
|
||||||
"address": "@medieval-kit/trestle-table",
|
"address": "@medieval-kit/trestle-table",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.784Z",
|
"installedAt": "2026-08-22T07:04:36.919Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\trestle-table\\model.ts",
|
"path": "src\\models\\medieval-kit\\trestle-table\\model.ts",
|
||||||
|
|
@ -317,7 +317,7 @@
|
||||||
"address": "@medieval-kit/wooden-chest",
|
"address": "@medieval-kit/wooden-chest",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.790Z",
|
"installedAt": "2026-08-22T07:04:36.924Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-chest\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-chest\\model.ts",
|
||||||
|
|
@ -332,7 +332,7 @@
|
||||||
"address": "@medieval-kit/hay-bale",
|
"address": "@medieval-kit/hay-bale",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.775Z",
|
"installedAt": "2026-08-22T07:04:36.909Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\hay-bale\\model.ts",
|
"path": "src\\models\\medieval-kit\\hay-bale\\model.ts",
|
||||||
|
|
@ -347,7 +347,7 @@
|
||||||
"address": "@medieval-kit/pitch-torch",
|
"address": "@medieval-kit/pitch-torch",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.782Z",
|
"installedAt": "2026-08-22T07:04:36.917Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\pitch-torch\\model.ts",
|
"path": "src\\models\\medieval-kit\\pitch-torch\\model.ts",
|
||||||
|
|
@ -362,7 +362,7 @@
|
||||||
"address": "@medieval-kit/wooden-bench",
|
"address": "@medieval-kit/wooden-bench",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.788Z",
|
"installedAt": "2026-08-22T07:04:36.923Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wooden-bench\\model.ts",
|
"path": "src\\models\\medieval-kit\\wooden-bench\\model.ts",
|
||||||
|
|
@ -377,11 +377,11 @@
|
||||||
"address": "@medieval-kit/linen-sack",
|
"address": "@medieval-kit/linen-sack",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.779Z",
|
"installedAt": "2026-08-22T07:04:36.914Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\linen-sack\\model.ts",
|
"path": "src\\models\\medieval-kit\\linen-sack\\model.ts",
|
||||||
"sourceHash": "f35b564de100d3038cc8c26ca9a8c08bc40c0fa2bab823006b0a0f72e647ffd7"
|
"sourceHash": "b92a9b075c2b702598a6c8cb5eff76941356cd5f38c7ffd01de621aea10c368a"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
@ -392,7 +392,7 @@
|
||||||
"address": "@medieval-kit/oak-tankard",
|
"address": "@medieval-kit/oak-tankard",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.781Z",
|
"installedAt": "2026-08-22T07:04:36.915Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\oak-tankard\\model.ts",
|
"path": "src\\models\\medieval-kit\\oak-tankard\\model.ts",
|
||||||
|
|
@ -407,7 +407,7 @@
|
||||||
"address": "@medieval-kit/straw-broom",
|
"address": "@medieval-kit/straw-broom",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.783Z",
|
"installedAt": "2026-08-22T07:04:36.918Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\straw-broom\\model.ts",
|
"path": "src\\models\\medieval-kit\\straw-broom\\model.ts",
|
||||||
|
|
@ -422,7 +422,7 @@
|
||||||
"address": "@medieval-kit/bronze-bell",
|
"address": "@medieval-kit/bronze-bell",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.771Z",
|
"installedAt": "2026-08-22T07:04:36.905Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\bronze-bell\\model.ts",
|
"path": "src\\models\\medieval-kit\\bronze-bell\\model.ts",
|
||||||
|
|
@ -437,7 +437,7 @@
|
||||||
"address": "@medieval-kit/iron-lantern",
|
"address": "@medieval-kit/iron-lantern",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.777Z",
|
"installedAt": "2026-08-22T07:04:36.912Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\iron-lantern\\model.ts",
|
"path": "src\\models\\medieval-kit\\iron-lantern\\model.ts",
|
||||||
|
|
@ -452,7 +452,7 @@
|
||||||
"address": "@medieval-kit/tavern-sign",
|
"address": "@medieval-kit/tavern-sign",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.784Z",
|
"installedAt": "2026-08-22T07:04:36.919Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\tavern-sign\\model.ts",
|
"path": "src\\models\\medieval-kit\\tavern-sign\\model.ts",
|
||||||
|
|
@ -467,7 +467,7 @@
|
||||||
"address": "@medieval-kit/coin-pouch",
|
"address": "@medieval-kit/coin-pouch",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.773Z",
|
"installedAt": "2026-08-22T07:04:36.907Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\coin-pouch\\model.ts",
|
"path": "src\\models\\medieval-kit\\coin-pouch\\model.ts",
|
||||||
|
|
@ -482,7 +482,7 @@
|
||||||
"address": "@medieval-kit/glass-phial",
|
"address": "@medieval-kit/glass-phial",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.774Z",
|
"installedAt": "2026-08-22T07:04:36.908Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\glass-phial\\model.ts",
|
"path": "src\\models\\medieval-kit\\glass-phial\\model.ts",
|
||||||
|
|
@ -497,7 +497,7 @@
|
||||||
"address": "@medieval-kit/leather-book",
|
"address": "@medieval-kit/leather-book",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.778Z",
|
"installedAt": "2026-08-22T07:04:36.913Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\leather-book\\model.ts",
|
"path": "src\\models\\medieval-kit\\leather-book\\model.ts",
|
||||||
|
|
@ -512,7 +512,7 @@
|
||||||
"address": "@medieval-kit/wicker-basket",
|
"address": "@medieval-kit/wicker-basket",
|
||||||
"source": "file:my-registry/dist/registry.json",
|
"source": "file:my-registry/dist/registry.json",
|
||||||
"version": "workspace",
|
"version": "workspace",
|
||||||
"installedAt": "2026-08-22T07:01:18.785Z",
|
"installedAt": "2026-08-22T07:04:36.920Z",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "src\\models\\medieval-kit\\wicker-basket\\model.ts",
|
"path": "src\\models\\medieval-kit\\wicker-basket\\model.ts",
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ export const linenSackDefaults: LinenSackConfig = {
|
||||||
height: 0.52,
|
height: 0.52,
|
||||||
radius: 0.16,
|
radius: 0.16,
|
||||||
fill: 0.85,
|
fill: 0.85,
|
||||||
collar: 0.14,
|
// A hand's width of gathered cloth above the cord, not a fifth of the sack.
|
||||||
|
collar: 0.1,
|
||||||
ears: 4,
|
ears: 4,
|
||||||
seed: 53,
|
seed: 53,
|
||||||
}
|
}
|
||||||
|
|
@ -72,15 +73,24 @@ export function createModel(overrides: Partial<LinenSackConfig> = {}) {
|
||||||
// silhouette means one model can produce both a full and a half-empty
|
// silhouette means one model can produce both a full and a half-empty
|
||||||
// sack.
|
// sack.
|
||||||
const wide = config.radius * (0.72 + fill * 0.36)
|
const wide = config.radius * (0.72 + fill * 0.36)
|
||||||
|
// A sack, not an amphora.
|
||||||
|
//
|
||||||
|
// The old profile put its widest point a quarter of the way up and then
|
||||||
|
// narrowed all the way to the neck, which is the silhouette of a vase.
|
||||||
|
// A filled sack does the opposite: it SPREADS where it meets the ground,
|
||||||
|
// because the grain settles and the cloth has no stiffness, then runs
|
||||||
|
// close to parallel up most of its height, and only gathers in sharply
|
||||||
|
// where the cord is tied. Nearly the whole difference between the two
|
||||||
|
// shapes is in the bottom level and in where the taper begins.
|
||||||
const profile: Level[] = [
|
const profile: Level[] = [
|
||||||
{ y: -half, radius: wide * 0.72 },
|
{ y: -half, radius: wide * 0.93 },
|
||||||
{ y: -half + config.height * 0.05, radius: wide * 0.95 },
|
{ y: -half + config.height * 0.07, radius: wide },
|
||||||
{ y: -half + config.height * 0.26 * fill, radius: wide },
|
{ y: -half + config.height * 0.44 * fill, radius: wide },
|
||||||
{ y: -half + config.height * 0.52 * fill, radius: wide * 0.93 },
|
{ y: -half + config.height * 0.72 * fill, radius: wide * 0.9 },
|
||||||
{ y: bodyTop - config.height * 0.16, radius: wide * 0.7 },
|
{ y: bodyTop - config.height * 0.09, radius: wide * 0.52 },
|
||||||
{ y: bodyTop, radius: config.radius * 0.34 },
|
{ y: bodyTop, radius: config.radius * 0.25 },
|
||||||
]
|
]
|
||||||
const body = latheGeometry(profile, 9, [0, 0, 0], tint('cloth', -0.06, 1.3), {
|
const body = latheGeometry(profile, 11, [0, 0, 0], tint('cloth', -0.06, 1.3), {
|
||||||
colourTop: tint('cloth', 0.05, 1.3),
|
colourTop: tint('cloth', 0.05, 1.3),
|
||||||
})
|
})
|
||||||
// Cloth is not rigid: here the surface break-up is the texture itself.
|
// Cloth is not rigid: here the surface break-up is the texture itself.
|
||||||
|
|
@ -123,8 +133,11 @@ export function createModel(overrides: Partial<LinenSackConfig> = {}) {
|
||||||
{ y: bodyTop - config.height * 0.03, radius: config.radius * 0.36 },
|
{ y: bodyTop - config.height * 0.03, radius: config.radius * 0.36 },
|
||||||
{ y: neckY - config.height * 0.02, radius: config.radius * 0.3 },
|
{ y: neckY - config.height * 0.02, radius: config.radius * 0.3 },
|
||||||
{ y: neckY + config.height * 0.03, radius: config.radius * 0.27 },
|
{ y: neckY + config.height * 0.03, radius: config.radius * 0.27 },
|
||||||
{ y: half - config.height * 0.02, radius: config.radius * 0.46 },
|
// The tuft above the tie opens only a little. Flaring to 0.46 of the
|
||||||
{ y: half, radius: config.radius * 0.4 },
|
// radius turned the top of a sack into the mouth of a bottle, which is
|
||||||
|
// the last thing left reading as a vessel once the body was fixed.
|
||||||
|
{ y: half - config.height * 0.02, radius: config.radius * 0.33 },
|
||||||
|
{ y: half, radius: config.radius * 0.27 },
|
||||||
]
|
]
|
||||||
const collar = latheGeometry(flare, 9, [0, 0, 0], tint('cloth', 0.02, 1.3), {
|
const collar = latheGeometry(flare, 9, [0, 0, 0], tint('cloth', 0.02, 1.3), {
|
||||||
colourTop: tint('cloth', 0.1, 1.3),
|
colourTop: tint('cloth', 0.1, 1.3),
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ export const linenSackDefaults: LinenSackConfig = {
|
||||||
height: 0.52,
|
height: 0.52,
|
||||||
radius: 0.16,
|
radius: 0.16,
|
||||||
fill: 0.85,
|
fill: 0.85,
|
||||||
collar: 0.14,
|
// A hand's width of gathered cloth above the cord, not a fifth of the sack.
|
||||||
|
collar: 0.1,
|
||||||
ears: 4,
|
ears: 4,
|
||||||
seed: 53,
|
seed: 53,
|
||||||
}
|
}
|
||||||
|
|
@ -72,15 +73,24 @@ export function createModel(overrides: Partial<LinenSackConfig> = {}) {
|
||||||
// silhouette means one model can produce both a full and a half-empty
|
// silhouette means one model can produce both a full and a half-empty
|
||||||
// sack.
|
// sack.
|
||||||
const wide = config.radius * (0.72 + fill * 0.36)
|
const wide = config.radius * (0.72 + fill * 0.36)
|
||||||
|
// A sack, not an amphora.
|
||||||
|
//
|
||||||
|
// The old profile put its widest point a quarter of the way up and then
|
||||||
|
// narrowed all the way to the neck, which is the silhouette of a vase.
|
||||||
|
// A filled sack does the opposite: it SPREADS where it meets the ground,
|
||||||
|
// because the grain settles and the cloth has no stiffness, then runs
|
||||||
|
// close to parallel up most of its height, and only gathers in sharply
|
||||||
|
// where the cord is tied. Nearly the whole difference between the two
|
||||||
|
// shapes is in the bottom level and in where the taper begins.
|
||||||
const profile: Level[] = [
|
const profile: Level[] = [
|
||||||
{ y: -half, radius: wide * 0.72 },
|
{ y: -half, radius: wide * 0.93 },
|
||||||
{ y: -half + config.height * 0.05, radius: wide * 0.95 },
|
{ y: -half + config.height * 0.07, radius: wide },
|
||||||
{ y: -half + config.height * 0.26 * fill, radius: wide },
|
{ y: -half + config.height * 0.44 * fill, radius: wide },
|
||||||
{ y: -half + config.height * 0.52 * fill, radius: wide * 0.93 },
|
{ y: -half + config.height * 0.72 * fill, radius: wide * 0.9 },
|
||||||
{ y: bodyTop - config.height * 0.16, radius: wide * 0.7 },
|
{ y: bodyTop - config.height * 0.09, radius: wide * 0.52 },
|
||||||
{ y: bodyTop, radius: config.radius * 0.34 },
|
{ y: bodyTop, radius: config.radius * 0.25 },
|
||||||
]
|
]
|
||||||
const body = latheGeometry(profile, 9, [0, 0, 0], tint('cloth', -0.06, 1.3), {
|
const body = latheGeometry(profile, 11, [0, 0, 0], tint('cloth', -0.06, 1.3), {
|
||||||
colourTop: tint('cloth', 0.05, 1.3),
|
colourTop: tint('cloth', 0.05, 1.3),
|
||||||
})
|
})
|
||||||
// Cloth is not rigid: here the surface break-up is the texture itself.
|
// Cloth is not rigid: here the surface break-up is the texture itself.
|
||||||
|
|
@ -123,8 +133,11 @@ export function createModel(overrides: Partial<LinenSackConfig> = {}) {
|
||||||
{ y: bodyTop - config.height * 0.03, radius: config.radius * 0.36 },
|
{ y: bodyTop - config.height * 0.03, radius: config.radius * 0.36 },
|
||||||
{ y: neckY - config.height * 0.02, radius: config.radius * 0.3 },
|
{ y: neckY - config.height * 0.02, radius: config.radius * 0.3 },
|
||||||
{ y: neckY + config.height * 0.03, radius: config.radius * 0.27 },
|
{ y: neckY + config.height * 0.03, radius: config.radius * 0.27 },
|
||||||
{ y: half - config.height * 0.02, radius: config.radius * 0.46 },
|
// The tuft above the tie opens only a little. Flaring to 0.46 of the
|
||||||
{ y: half, radius: config.radius * 0.4 },
|
// radius turned the top of a sack into the mouth of a bottle, which is
|
||||||
|
// the last thing left reading as a vessel once the body was fixed.
|
||||||
|
{ y: half - config.height * 0.02, radius: config.radius * 0.33 },
|
||||||
|
{ y: half, radius: config.radius * 0.27 },
|
||||||
]
|
]
|
||||||
const collar = latheGeometry(flare, 9, [0, 0, 0], tint('cloth', 0.02, 1.3), {
|
const collar = latheGeometry(flare, 9, [0, 0, 0], tint('cloth', 0.02, 1.3), {
|
||||||
colourTop: tint('cloth', 0.1, 1.3),
|
colourTop: tint('cloth', 0.1, 1.3),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue