How model_width Controls STL Output Dimensions in MCP 3D Relief
The model_width parameter directly sets the physical X-axis width of the generated STL file in millimeters, automatically scaling the Y-axis proportionally to preserve the source image's aspect ratio.
The bigchx/mcp_3d_relief repository converts depth maps into 3D printable STL files. Understanding how the model_width parameter translates digital pixels into physical millimeters is essential for producing accurately sized 3D relief models.
How model_width Maps Pixels to Millimeters
Inside relief.py, the code calculates a scaling factor called pixel_size that bridges the gap between image resolution and physical dimensions:
pixel_size = model_width / width # relief.py, line 57
widthrepresents the number of pixels in the depth map's horizontal axis.pixel_sizedetermines exactly how many millimeters each pixel occupies in the final STL geometry.
This single calculation drives all dimensional scaling for the X and Y axes, ensuring the output matches your specified model_width exactly.
X and Y Axis Scaling Behavior
X-Axis Dimensions
The X-coordinates of the generated mesh vertices are multiplied by pixel_size during STL generation. The outermost X-coordinates span from 0 to (width - 1) * pixel_size, resulting in a total X-axis span that equals model_width millimeters exactly.
Y-Axis Dimensions
The Y-axis uses the same pixel_size factor to maintain the source image's aspect ratio:
y0 = (height - y - 1) * pixel_size
y1 = (height - (y + 1) - 1) * pixel_size
The resulting Y-extent calculates to height * pixel_size, which simplifies to height * model_width / width. This preserves the original image proportions while fitting the larger dimension to your specified model_width.
Z-Axis Independence
The Z-axis (height/thickness) operates independently of model_width. The depth map values (0-255) are scaled by model_thickness (default 5mm) to determine relief height, while base_thickness adds a constant flat base below the relief surface. These parameters control vertical dimensions without affecting the X-Y plane scaling.
Practical Code Examples
Generate a 100mm Wide Model
import asyncio
from relief import relief
async def run():
result = await relief(
input_image_path="uploads/demo.png",
model_width=100.0, # Request exactly 100mm width
model_thickness=5.0,
base_thickness=2.0,
)
print(result)
asyncio.run(run())
For an 800×600 pixel source image, this produces an STL file measuring 100mm wide by approximately 75mm tall (600/800 × 100), preserving the 4:3 aspect ratio.
Verify Output Dimensions Programmatically
import trimesh
import pathlib
stl_path = pathlib.Path("output/abcd1234.stl")
mesh = trimesh.load_mesh(stl_path)
x_size = mesh.bounds[1][0] - mesh.bounds[0][0]
y_size = mesh.bounds[1][1] - mesh.bounds[0][1]
z_size = mesh.bounds[1][2] - mesh.bounds[0][2]
print(f"X: {x_size:.2f}mm (should match model_width)")
print(f"Y: {y_size:.2f}mm (scaled by aspect ratio)")
print(f"Z: {z_size:.2f}mm (model_thickness + base_thickness)")
Summary
model_widthsets the exact physical width (X-axis) of the STL output in millimeters via the calculationpixel_size = model_width / widthinrelief.py.- Aspect ratio preservation occurs automatically because the same
pixel_sizescales the Y-axis, resulting inheight * model_width / width. - Z-axis dimensions remain independent, controlled by
model_thicknessandbase_thicknessrather thanmodel_width. - Validation confirms that setting
model_width=100.0produces an STL with exactly 100mm X-axis span regardless of source image resolution.
Frequently Asked Questions
Does model_width affect the height of the relief?
No, model_width only controls the horizontal X and Y dimensions. The relief height (Z-axis) is determined by model_thickness, which scales the depth map values, and base_thickness, which adds a flat foundation. These parameters operate independently of the width scaling logic in relief.py.
How do I maintain the aspect ratio when setting model_width?
The aspect ratio is preserved automatically. When you specify model_width, the code calculates pixel_size = model_width / width and applies this same factor to the Y-axis coordinates. This ensures the Y-dimension becomes height * model_width / width, maintaining the original image proportions without manual calculation.
What happens if I don't specify model_width?
The repository requires model_width as a mandatory parameter in the relief() function signature. If omitted, the function call will raise a TypeError. There is no default value, ensuring users explicitly define the desired physical scale for every generated STL file.
Can I set different widths for X and Y dimensions?
No, the current implementation in relief.py uses a single pixel_size factor derived from model_width to scale both axes uniformly. This design enforces proportional scaling to prevent distortion of the relief pattern. To achieve non-uniform scaling, you would need to modify the source code to accept separate model_width and model_height parameters.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →