mesh-avatar-studio
일러스트를 코딩 에이전트와 로컬 편집기로 2D 메쉬 애니메이션 아바타로 변환
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기OSM area select → 3D model + vector site plan (Melbourne-friendly MVP)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
CityCut cuts a square out of a city and exports it as a 3D model and a 2D site plan. The default view opens on the Melbourne CBD.
It is a study tool for early architectural work: OpenStreetMap footprints, estimated heights, and a terrain heightfield. It is not a survey. Turn Terrain off and the ground is a flat surface.
The production build is set up to publish to https://kchaisor.github.io/citycut/.README 전문 보기 ↗CityCut cuts a square out of a city and exports it as a 3D model and a 2D site plan. The default view opens on the Melbourne CBD.
It is a study tool for early architectural work: OpenStreetMap footprints, estimated heights, and a terrain heightfield. It is not a survey. Turn Terrain off and the ground is a flat surface.
The production build is set up to publish to https://kchaisor.github.io/citycut/.
Pushes to main build dist and deploy it with GitHub Actions (.github/workflows/pages.yml). Vite’s base is /citycut/, so the built HTML, scripts, styles, and favicon resolve under that project path. The app has no client-side router, so there is no extra basename to set.
Choose a block. A MapLibre map fills the screen. A fixed frame stays centered while you pan and zoom. The frame is a true square on the ground, from 0.25 km to 1.4 km on a side (about 2 km² at the top of the slider).
Search. Nominatim pans the map to a place. The frame still marks the area that will be exported.
Choose layers. Buildings, roads and rail, water and green, and terrain are on by default. Buildings come from Overture Maps building PMTiles (z14); roads and rail from Overture transportation PMTiles (z14); water and green from Overture base PMTiles (z13). Trees is off until you turn it on. It then places four vector tiers, deduplicated, as instanced archetype silhouettes: City of Melbourne urban-forest trees, Overture base point trees (OSM-sourced tags), Vicmap Vegetation Tree Urban points, and a canopy infill from Overture land cover and land use. Contours is on by default. Inside Victoria the lines are Vicmap Elevation: the metro 1–5 m contours where that layer has features, otherwise the statewide 1:25,000 10 m contours. If that service fails or the frame is outside Victoria, the site plan keeps the lines marched from the terrain. Satellite image only switches the basemap.
Create model. CityCut fetches Overture PMTiles for the frame, clips every feature to the square, and opens the result. Tree tiers, Vicmap contours, and the terrain are fetched in parallel. Trees, when that layer is on, are drawn as instanced massing forms rather than one mesh per tree. Terrain, when that layer is on, fetches Mapterhorn tiles for the square and builds a heightfield in the same local metre frame. The 3D terrain mesh stays that heightfield.
Review. The model opens with a fixed sidebar on the left, on Model details: the place, counts, how many building heights are measured, and every data source with its status (a failed source keeps its note). The icon rail switches the sidebar between Model details, Buildings, Trees, Drawing, Sun, Wind, and Export; the button at the foot of the rail collapses the panel. Three views of the same block:
Download. PNG, Rhino (.3dm), and Illustrator (.ai). glTF (.glb), SVG, DXF, DAE, and JPG are not offered.
Building height, in order:
height (feet are converted to meters)building:levels × 3 mBuilding colour follows a cascade, stopping at the first match: OSM tags already on the building (building, building:use, and amenity, shop, office, or landuse on that element), then Vicmap planning zones. Anything left is unclassified. Categories are residential, commercial, retail, mixed use, industrial, civic, recreation, outbuilding, and unclassified. The 3D view counts each category and each source tier, and can recolour by source so a zone guess is hatched and lighter than an observed OSM tag. A uniform off-white is still available. glTF keeps one material per category. The Rhino file puts each category on a sublayer such as Buildings::Residential, and each building object stores use and typology_source (osm_tag, zone, or none). A frame can open on ?lat=&lon=&km=.
Roads are asphalt, #3a3a3a, with local streets and footways a step lighter. The ribbon faces upward whichever way the OSM way was drawn. On a heightfield it is split so a long run follows the surface, and it sits a few centimetres above the terrain, parks, and water. Roads do not use a depth bias: a large one clips the ribbon when the camera is low, and the street disappears.
Heights are capped between 3 m and 420 m. With Terrain off, the ground is a flat surface and exports match that flat model. With Terrain on, buildings are extruded from the lowest DEM sample on the footprint, trees sit on the sample at the trunk, and roads, rail, parks, and water are draped a few centimetres above the surface. Multipolygon buildings, parks, and water bodies are stitched when the relation is small enough to assemble (80 members or fewer).
Terrain is on by default. The tiles are Mapterhorn Terrarium WebP, 512 px, from https://tiles.mapterhorn.com/{z}/{x}/{y}.webp (TileJSON, encoding: terrarium). Height is R * 256 + G + B / 256 − 32768 metres. The host sends Access-Control-Allow-Origin: *. The TileJSON does not publish a max zoom; data access describes planet tiles through z12 and regional archives through z17 where a finer source exists.
CityCut asks for about 5 m per pixel (zoom 14 at Melbourne’s latitude, about 3.8 m on the ground) and steps down while a zoom returns 404. A square is resampled onto a grid of at most 193 samples on a side. Around Melbourne, z15 is 404 and z14 is served, which is the zoom that resolves Geoscience Australia’s 5 m lidar DEM (CC BY 4.0). Where that coverage is missing, Mapterhorn uses Copernicus GLO-30 (about 30 m). Attribution for the whole mosaic is © Mapterhorn.
Elevations in the viewport, the glTF mesh named Terrain, and the Rhino Terrain layer are those DEM metres (AHD for the Geoscience Australia lidar, geoid height for Copernicus). They are not a survey, and they share the file with buildings and trees: a 12 m building on a 30 m sample runs from Z 30 to Z 42. The terrain mesh is that surface only: no skirt, side walls, or base. With Terrain off, the ground export is the same flat surface, not a thick slab. If the tiles fail, the model keeps the flat surface and shows “Terrain tiles could not be loaded, so the ground is flat.”
Contours on the site plan, the site-plan Illustrator file, and the Rhino file come from Vicmap Elevation when the frame meets Victoria. The metro layer is EL_CONTOUR_1TO5M (1 m, with 5 m in places). A frame it does not cover uses EL_CONTOUR, the 1:25,000 contours at 10 m and 20 m. Both are queried by bounding box from the browser, paged at 2,000 features, and clipped to the square. On the site plan and in the site-plan Illustrator file, metro 1 m contours thin to 5 m at 1:2500 and smaller scales, so every 5th drawn line is 25 m. 1:500 and 1:1000 keep every 1 m line, with index lines every 5 m. The statewide 10 m and 20 m lines, and the DEM fallback, are not thinned. The Rhino file keeps every contour at its true elevation. Every 5th drawn interval is slightly heavier. If the service errors or does not answer within about 8 seconds, or the frame is outside Victoria, the plan falls back to marching squares on the Mapterhorn grid. That interval is 1 m when the relief is under 8 m, 2 m under 25 m, 5 m under 80 m, and 10 m otherwise. The Rhino Contours layer is polylines at the contour elevation. The 3D terrain mesh is unchanged.
The 3D terrain is still the Mapterhorn heightfield. A Victorian DEM was not added. These endpoints were checked from the browser’s point of view (no server, no API key):
https://vicmap.land.vic.gov.au/agsimage/rest/services/elevation/vicmap_dem10m_v5m_ahd_epsg7844/ImageServer returns HTTP 404 (Service not found). The parent elevation folder lists no services. The catalogue page still describes a 10 m AHD raster, but there is no live raster to sample. Even a working exportImage would be a float GeoTIFF or LERC, which needs a decoder this app does not carry.datashare.maps.vic.gov.au search pages for ECW, GeoTIFF, and JPEG 2000 downloads of the state grid. That is a file portal, not a tile URL, and the host did not send Access-Control-Allow-Origin.*, not a WCS coverage document.https://services-ap1.arcgis.com/P744lA0wf4LlBZ84/ArcGIS/rest/services/Vicmap_Elevation_METRO_1_to_5_metre/FeatureServer/1, layer EL_CONTOUR_1TO5M) and the statewide 10–20 m contours (…/Vicmap_Elevation_STATEWIDE_10_to_20_metre/FeatureServer/6, layer EL_CONTOUR) both send CORS *. Those polylines are what the site plan uses. The elevation field is altitude. maxRecordCount is 2000. They are not a height grid: building a terrain mesh from the lines would be a separate interpolation, and the metro layer has holes. The same organisation’s Vicmap_1m_DEM_Footprints layer is the footprint of 1 m rasters, not the elevations. The City of Melbourne open-data catalogue does not expose a DEM tile the page can read as heights.Mapterhorn’s Melbourne tiles already use the 5 m Geoscience Australia lidar, which is finer than the Vicmap 10 m DEM, so the 3D terrain stays on Mapterhorn. A direct Vicmap surface is a follow-up if a CORS-friendly height grid appears.
Trees are placed in four tiers. A later tier is skipped when an earlier tree is already within 3 m. Every tier is clamped: height 2–40 m, crown diameter 1–25 m, and crown at most 1.4 times the height. A crown thinner than half the archetype’s own proportion is lifted so the instance does not become a needle. Trunk diameter stays between 0.05 m and 2 m. Missing, NaN, zero, and negative measurements are dropped and the count is logged. The combined set is capped at 8,000 instances. Canopy infill is trimmed first, then Vicmap.
scientific_name, genus, common_name), diameter_breast_height in centimetres, and age_description. There is no crown-spread field and no height field, so crown and height follow the species archetype from DBH and age. The request runs only when the frame meets the council extent; the dataset itself contains only that inventory.land layer, class tree), where tier 1 has no tree within 3 m. Tags come from Overture source_tags (OpenStreetMap contributors). Size uses the same rules as OSM trees: height or est_height, crown diameter, trunk girth or diameter, then species archetype, then the generic tree (10 m tall, 6 m across, 0.35 m trunk).height_m. Crown diameter is canopy_radius_m × 2 when that radius is a positive number, otherwise it is derived from height. dense_canopy picks the broader round-broadleaf archetype; anything else uses the generic broadleaf. The query is the frame envelope only, paged with resultOffset at 2,000 rows. A failed fetch is noted and the model still opens.land_cover (forest, wood, scrub) and matching land use. Scrub uses the smaller shrub archetype. Points are a Poisson disc at 7 m. Roads (plus a 2 m buffer), buildings, water, and any sample within 4 m of a tree already placed are left empty.The Tree sizes panel lists the four counts. Each instance is scaled vertically by height and horizontally by crown. The archetype is one mesh, so the trunk thickens with the crown; the trunk diameter is still stored on the tree. glTF and Rhino exports include every tier, still as instanced silhouettes.
Pre-baked trees. The first three tiers are read from trees.pmtiles (Greater Melbourne, z15, about 76 MB), built monthly by the build-trees job in .github/workflows/building-enrichment-weekly.yml (scripts/build-trees-pmtiles.mjs) and published as the trees-latest release, which the Pages build copies into the site. The job skips when the Vicmap and City of Melbourne last-edit dates and the Overture release are unchanged (trees-manifest.json records them), and fails without publishing on an ArcGIS error body, a count mismatch, or a file of 100 MB or more. Vicmap height and crown are stored to the nearest 0.5 m. OSM points come from the file only when it was baked from the same Overture release as the base tiles. When the file is missing, fails, or does not cover the cut, the live servers are used and the Trees panel and Model details say so. Model details shows the file's data dates.
A natural=tree area uses its centre. A natural=tree_row is sampled about one crown apart (6–14 m).
Genus, species, taxon, leaf_type, and leaf_cycle pick a massing archetype for OpenStreetMap and for City of Melbourne names. Matching is case-insensitive: spaces and underscores are the same, and a hybrid × is ignored. A species or taxon name is tried first, then the genus, then leaf type, then leaf cycle. Anything still unknown uses the generic broadleaf. The forms are a curated glTF library in src/assets/trees/ (see that folder’s README). The viewport instances one mesh per form and scales it by the tree’s height and crown diameter. glTF and Rhino exports keep that silhouette; the SVG plan stays a circle per crown.
npm install
npm run dev
Vite serves the app at http://localhost:5173/citycut/ (port 5173, same /citycut/ base as Pages). Open that URL, leave the frame on Melbourne or search for a place, then press Create model. npm run preview serves the production build at http://localhost:4173/citycut/.
npm test
npm run build
npm run preview
No API key is required for the defaults.
npm test runs offline. Tests that read live Overture, City of Melbourne, or Vicmap data are skipped unless you set CITYCUT_NETWORK_TESTS=1 (for example CITYCUT_NETWORK_TESTS=1 npx vitest run src/lib/buildingHeightSourceGuard.test.ts).
Copy .env.example if you want to override the public endpoints. Both variables are optional.
| Variable | Default | Role |
|---|---|---|
VITE_NOMINATIM_URL | https://nominatim.openstreetmap.org | Place search. |
Map tiles:
https://tiles.openfreemap.org/styles/positron). No key.Nominatim’s usage policy asks for an identifying User-Agent. Browsers set that themselves and will not let the page replace it. Fine for light use; put a small proxy in front of Nominatim if you expect real traffic.
| Feature | Status |
|---|---|
| Map, search, square frame, area slider | Real |
| Buildings, roads and rail, water and green | Real, from Overture Maps PMTiles, clipped to the frame |
| 3D orbit view | Real. Studio gradient backdrop, soft fill light, a baked contact shadow under the plinth, and SMAA. The High/Fast toggle in the top bar sets quality: High adds N8AO ambient occlusion when the camera is at rest, Fast leaves it off. The choice is kept in citycut.view3d.quality. The PNG download keeps its flat backdrop and has no ambient occlusion |
| Drawing tab (SVG, pan/zoom) | Real |
glTF .glb download | Not offered |
Rhino .3dm download | Real. Meshes in GDA2020 / MGA metres, Z-up |
| SVG download | Not offered |
| Satellite basemap and satellite tab | Real preview. Not embedded in the glTF or SVG |
| Trees | Real when the toggle is on. City of Melbourne urban forest, Overture base point trees, Vicmap Tree Urban, and canopy infill. Instanced massing archetypes in the 3D view, glTF, and Rhino; circles on the SVG plan |
| Terrain | Real when the toggle is on (the default). Mapterhorn Terrarium tiles, heightfield mesh named Terrain in the glTF and on a Terrain layer in the 3DM. Off falls back to a flat ground surface |
| Contours | Real on the site plan, the site-plan Illustrator file, and the Rhino Contours layer. Vicmap Elevation inside Victoria (metro 1–5 m, otherwise 10 m). Metro 1 m lines draw at 5 m from 1:2500. The terrain DEM is the fallback. The Rhino file keeps every contour |
| Relief / terrain stats | The model page shows the DEM elevation range when terrain loaded |
| DXF, DAE, JPG | Not in this version. No placeholder downloads |
| Site lidar, detected trees | Not in this version. Terrain is the Mapterhorn DEM, not a scan of this block |
height tag, so many blocks use levels × 3 m or the 9 m default.building:part outlines are skipped so they do not paint through the block.Map data © OpenStreetMap contributors. Vector tiles © OpenFreeMap / OpenStreetMap. Satellite imagery © Esri, Vantor, Earthstar Geographics, and the GIS User Community. Terrain © Mapterhorn, including Geoscience Australia’s 5 m DEM (CC BY 4.0) and Copernicus GLO-30 where the 5 m grid is absent. City of Melbourne urban forest © City of Melbourne, CC BY 4.0. Vicmap Vegetation Tree Urban © State of Victoria (Department of Transport and Planning), CC BY 4.0. Vicmap Elevation contours © State of Victoria (Department of Transport and Planning), Creative Commons Attribution 4.0 (CC-BY).
CityCut is an original interface. Kelvin Chai, Melbourne.
src/App.tsx — select screen and model screensrc/lib/overpass.ts — query and endpoint fallbacksrc/lib/parseOsm.ts — footprints, roads, water, green, treessrc/lib/trees.ts — tree height, crown, and trunk, and where each size came fromsrc/lib/treeTiers.ts — dedupe, canopy infill, and the instance capsrc/lib/comTrees.ts — City of Melbourne urban-forest treessrc/lib/vicmapTrees.ts — Vicmap Vegetation Tree Urban pointssrc/lib/buildingUse.ts — building program and colourssrc/lib/surfaceLayers.ts — draped layer stacksrc/lib/footprints.ts — duplicate footprintssrc/lib/treeMap.ts — OSM genus, species, taxon, and leaf tags to an archetype idsrc/lib/treeForms.ts — low-poly archetype meshes and their glTFsrc/assets/trees/ — curated archetype glTF librarysrc/lib/treeArchetypes.ts — InstancedMesh groups scaled by height and crownsrc/lib/buildCity.ts — Three.js group shared by the viewport, the glTF export, and the Rhino exportsrc/lib/crs.ts — MGA zone and proj4 projection for the .3dmsrc/lib/rhinoExport.ts — Rhino .3dm meshessrc/lib/svgPlan.ts — drawing tab and SVG downloadsrc/lib/terrain.ts — Terrarium decode, height sampling, contours, terrain meshsrc/lib/fetchTerrain.ts — Mapterhorn tile fetchsrc/colours.css — every fill, read through getColoursrc/drawing-style.css — site-plan line weights, dashes, and line colourssrc/lib/aiPlan.ts — site-plan and figure-ground Illustrator .aisrc/lib/aiView.ts — 3D-view Illustrator .aisrc/lib/aiDocument.ts — layered PDF written out as .aisrc/lib/capturePng.ts — PNG of the 3D view