None of these was run here. The hosted services sell credits; the open models need far more GPU memory than this machine's 4 GB GTX 1650:
| Generator | Access | Terms (26 September 2026) |
|---|---|---|
| Meshy 7.1 20,231 | API on paid plans | 20-35 credits a model; Free plan CC BY 4.0 |
| Tripo 7,870 P1.0 | Pay-as-you-go API credits | 30-50 credits a model; API V2 retired 1 Nov 2026 |
| Rodin 123,738 (Hyper3D) | API on Business plan | From $96 a month, commercial license |
| Stable Fast 3D 1,834 | API, open weights | $0.10 a model; Community License |
| TRELLIS.2 11,387 4B | Open weights | MIT; needs a 24 GB GPU |
| Hunyuan3D 2.1 14,978 | Open weights | Tencent license, not in EU, UK, Korea; 29 GB GPU |
| TripoSR 6,989 | Open weights | MIT; about 6 GB GPU |
Meshy and Tripo compete most directly, with text, image and multi-view input, rigging and plugins. Two former rivals have left: Luma AI 23,910 's Genie page now shows only video and image models, and CSM's csm.ai did not resolve. Hunyuan3D's license also requires a separate license above one million monthly active users.
<!doctype html>
<style>
body { margin: 0; padding: 8px; background: #fafaf7; font: 11px system-ui, sans-serif; color: #263238; }
svg { width: 100%; max-width: 600px; display: block; }
</style>
<script src="https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js"></script>
<p>GPU <select id="gpu"><option value="4">4 GB GTX 1650</option><option value="8">8 GB</option><option value="24">24 GB</option><option value="32">32 GB</option></select> · none of these was run for the book</p>
<svg viewBox="0 0 600 300" font-size="11"></svg>
<script>
const OPEN = [['TripoSR', 6, 'MIT'], ['TRELLIS.2 4B', 24, 'MIT'], ['Hunyuan3D 2.1', 29, 'Tencent licence; not in EU, UK, Korea']];
const HOSTED = [['Meshy 7.1', 'API on paid plans; 20-35 credits a model; Free plan CC BY 4.0'], ['Tripo P1.0', 'pay-as-you-go credits, 30-50 a model'],
['Rodin (Hyper3D)', 'API on Business plan, from $96/month'], ['Stable Fast 3D', 'API $0.10 a model; open weights, Community License']];
const svg = d3.select('svg');
svg.append('text').attr('font-weight', 'bold').attr('y', 14).text('open weights: GPU memory needed');
const y = d3.scaleBand(OPEN.map(o => o[0]), [22, 130]).padding(0.25), x = d3.scaleLinear([0, 32], [110, 440]);
svg.append('g').attr('transform', 'translate(0,130)').call(d3.axisBottom(x).ticks(8).tickFormat(d => `${d} GB`));
const row = svg.selectAll('g.o').data(OPEN).join('g').attr('class', 'o').attr('transform', o => `translate(0,${y(o[0])})`);
row.append('text').attr('x', 104).attr('y', y.bandwidth() / 2).attr('dy', '0.35em').attr('text-anchor', 'end').text(o => o[0]);
const bars = row.append('rect').attr('x', 110).attr('height', y.bandwidth()).attr('width', o => x(o[1]) - 110);
row.append('text').attr('x', o => x(o[1]) + 4).attr('y', y.bandwidth() / 2).attr('dy', '0.35em').text(o => o[2]).attr('font-size', 10);
const line = svg.append('line').attr('y1', 18).attr('y2', 132).attr('stroke', '#b5452f').attr('stroke-width', 2);
svg.append('text').attr('font-weight', 'bold').attr('y', 168).text('hosted services');
svg.selectAll('g.h').data(HOSTED).join('g').attr('class', 'h').attr('transform', (h, i) => `translate(${(i % 2) * 300},${178 + Math.floor(i / 2) * 56})`)
.call(g => g.append('rect').attr('width', 290).attr('height', 48).attr('rx', 6).attr('fill', '#fff').attr('stroke', '#5b3f99'))
.call(g => g.append('text').attr('x', 8).attr('y', 18).attr('font-weight', 'bold').text(h => h[0]))
.call(g => g.append('text').attr('x', 8).attr('y', 36).attr('font-size', 10).text(h => h[1]));
function draw() {
const gpu = +document.getElementById('gpu').value;
line.transition().attr('x1', x(gpu)).attr('x2', x(gpu));
bars.transition().attr('fill', o => o[1] <= gpu ? '#3f7d3a' : '#b0bec5');
}
document.getElementById('gpu').onchange = draw;
draw();
</script>