PhpScad
Create SCAD 3D models using PHP
Install / Use
/learn @RikudouSage/PhpScadREADME
PhpScad - 3D modelling using OpenSCAD in PHP
Ever wanted to create a 3D model in php? Sure you did, everyone does. And now you can.
How does it work?
It generates OpenSCAD code that in turn creates the STL 3D model. OpenScad basically looks like this:
translate([10, 0, 0]) // translate([x, y, z]) - moves the model by given coordinates
cube([10, 10, 10]); // cube([width, depth, height])
difference() { // only the difference between child objects is rendered
cube([5, 10, 15]);
cylinder(10, 5, 5); // cylinder(height, bottomRadius, topRadius)
}
This is the resulting 3D model preview:

So why use php if you can already create the model using code?
- PHP is full-blown general-purpose language with a lot of documentation around the internet
- There are full-blown IDEs that help with code completion
- PHP supports more paradigms, like object oriented programming
- Saner parameter names - for example the
cylindersignature iscylinder(h, r, r1, r2, d, d1, d2, center)compared to PhpScad version -new Cylinder(height, radius, bottomRadius, topRadius, diameter, bottomDiameter, topDiameter)- note that in both OpenSCAD and PhpScad version many of the parameters are optional
- Created an interesting parametric shape? Cool, share it via composer because PHP has a package manager!
So how does the example above look in PHP?
<?php
use Rikudou\PhpScad\ScadModel;
use Rikudou\PhpScad\Shape\Cube;
use Rikudou\PhpScad\Combination\Difference;
use Rikudou\PhpScad\Shape\Cylinder;
$model = new ScadModel();
$model = $model
->withRenderable((new Cube(width: 10, depth: 10, height: 10))->movedRight(10)) // using named parameters
->withRenderable(new Difference(
new Cube(5, 10, 15), // using positional parameters
new Cylinder(height: 10, bottomRadius: 5, topRadius: 5),
));
$model->render(__DIR__ . '/output.scad');
You can notice the preview looks the same:

Notice the convenience method ->movedRight() which is one of the examples of what's possible in PHP but not in
OpenSCAD - a fluent api that's more natural and easy to think about.
You can also go the OpenSCAD way in PhpScad:
<?php
use Rikudou\PhpScad\Transformation\Translate;
use Rikudou\PhpScad\Coordinate\XYZ;
use Rikudou\PhpScad\Shape\Cube;
new Translate(new XYZ(x: 10, y: 0, z: 0), new Cube(width: 10, depth: 10, height: 10));

Installation
composer require rikudou/php-scad:dev-master
Usage
Shapes
Shapes are the base of all models. PhpScad provides the same basic shades as OpenSCAD does, namely:
- Cube
- Cylinder
- Polyhedron
- Sphere
Additional shapes provided by PhpScad:
- Pyramid
Basically all shapes can be created by combining the basic shapes.
Cube
Creates a cube.
Parameters
number $width(default: 0)number $depth(default: 0)number $height(default: 0)
Rendered if: At least one of the parameters is non-zero or is a reference type.
Example:
<?php
use Rikudou\PhpScad\Shape\Cube;
$cube = new Cube(width: 10, depth: 10, height: 10);

Cylinder
Creates a cylinder.
Parameters
number $height(default: 0)?number $radius(default: null)?number $bottomRadius(default: null)?number $topRadius(default: null)?number $diameter(default: null)?number $bottomDiameter(default: null)?number $topDiameter(default: null)bool $centerOnZ(default: false) - whether the model should be centered on the Z axisbool $centerOnXY(default: true) - whether the model should be centered on the X and Y axis?FacetsConfiguration $facetsConfiguration(default: null) - facets configuration, more below
You should either provide radius or diameter, not both. Also, you should provide either the singular parameter
($radius, $diameter) or one or both of the top/bottom pair
($bottomRadius/$topRadius, $bottomDiameter/`$topDiameter).
Using a pair of radii/diameters allows you to create a cone.
If you provide invalid combination of radii, the behavior is undefined and depends on the OpenSCAD implementation as PhpScad will generate the shape with all the parameters you provide.
Rendered if: Height is non-zero and at least one of the radius parameters is provided.
Example:
<?php
use Rikudou\PhpScad\Shape\Cylinder;
// all these shapes are equivalent
$cylinderWithDiameter = new Cylinder(height: 10, diameter: 20);
$cylinderWithTopBottomDiameters = new Cylinder(height: 10, topDiameter: 20, bottomDiameter: 20);
$cylinderWithRadius = new Cylinder(height: 10, radius: 10);
$cylinderWithTopBottomRadii = new Cylinder(height: 10, topRadius: 10, bottomRadius: 10);
// cone
$cone = new Cylinder(height: 10, topRadius: 10, bottomRadius: 20);
// fully centered
$centered = new Cylinder(height: 10, diameter: 10, centerOnXY: true, centerOnZ: true);



Polyhedron
The most versatile of shapes, allows you to define your own shapes using points and faces. It can be used to create any regular or irregular shape.
Parameters
array|PointVector $points(default: empty PointVector) - all points that the shape will consist ofarray|FaceVector $faces(default: empty FaceVector) - the faces the shape will consist ofint $convexity(default: 1) - specifies the maximum number of faces a ray intersecting the object might penetrate, only used in preview mode
While arrays may be used for both points and faces, using the provided PointVector and FaceVector is recommended
for better readability. When using FaceVector you don't have to populate PointVector manually.
There are basically two ways to create a polyhedron, let's call them "the OpenSCAD way" and "the PhpScad way".
Polyhedron - the OpenSCAD way
I can't think of any reason to use this instead of the other way, but it's supported for the sake of completeness, feel free to skip this part of the documentation.
First you need to define an array of points, you can either use PointVector or an array:
<?php
use Rikudou\PhpScad\Value\PointVector;
use Rikudou\PhpScad\Value\Point;
// five points to make a pyramid, in no particular order
$points = [
[10, 15, 0],
[10, 0, 0],
[5, 7.5, 20],
[0, 0, 0],
[0, 15, 0],
];
// using PointVector
$points = new PointVector(
new Point(x: 10, y: 15, z: 0),
new Point(x: 10, y: 0, z: 0),
new Point(x: 5, y: 7.5, z: 20),
new Point(x: 0, y: 0, z: 0),
new Point(x: 0, y: 15, z: 0),
);
Then you need to reference those points when creating faces, using an index of the points in the points array:
All faces must have their points ordered in clockwise direction when looking at each face from outside inward.
<?php
use Rikudou\PhpScad\Shape\Polyhedron;
use Rikudou\PhpScad\Value\PointVector;
use Rikudou\PhpScad\Value\Point;
use Rikudou\PhpScad\Value\FaceVector;
use Rikudou\PhpScad\Value\Face;
// from previous example, added manual indexes for clarity
$points = [
0 => [10, 15, 0],
1 => [10, 0, 0],
2 => [5, 7.5, 20],
3 => [0, 0, 0],
4 => [0, 15, 0],
];
$faces = [
new Face(0, 1, 2), // points with indexes 0, 1 and 2, meaning '[10, 15, 0]', '[10, 0, 0]' and '[5, 7.5, 20]'
new Face(1, 3, 2), // points with indexes 1, 3 and 2, meaning '[10, 0, 0]', '[0, 0, 0]' and '[5, 7.5, 20]'
new Face(3, 4, 2), // '[0, 0, 0]', '[0, 15, 0]' and '[5, 7.5, 20]'
new Face(4, 0, 2), // '[0, 15, 0]', '[10, 15, 0]', '[5, 7.5, 20]'
new Face(0, 4, 3, 1), // '[10, 15, 0]', '[0, 15, 0]', '[0, 0, 0]', '[10, 0, 0]'
];
$polyhedron = new Polyhedron(points: $points, faces: $faces);
// or the same example using provided DTOs
$points = new PointVector(
new Point(x: 10, y: 15, z: 0),
new Point(x: 10, y: 0, z: 0),
new Point(x: 5, y: 7.5, z: 20),
new Point(x: 0, y: 0, z: 0),
new Point(x: 0, y: 15, z: 0),
);
$faces = new FaceVector(
new Face(0, 1, 2),
new Face(1, 3, 2),
new Face(3, 4, 2),
new Face(4, 0, 2),
new Face(0, 4, 3, 1),
);
$polyhedron = new Polyhedron(points: $points, faces: $faces);
// unless I made some mistake, $polyhedron should now hold a proper pyramid

As you can see this is hard to work with.
Polyhedron - the PhpScad way
Instead of the complicated stuff with referencing points by their indexes you can simply create the points when creating faces, the points array will be defined internally:
<?php
use Rikudou\PhpScad\Shape\Polyhedron;
use Rikudou\PhpScad\Value\Point;
use Rikudou\PhpScad\Value\Face;
use Rikudou\PhpScad\Value\FaceVector;
// this should be the same pyramid as above (unless I made a mistake)
$faces = new FaceVector(
new Face(
new Point(x: 10, y: 15, z: 0),
new Point(x: 10, y: 0, z: 0),
new Point(x: 5, y: 7.5, z: 20),
),
new Face(
new Point(x: 10, y: 0, z: 0),
new Point(x: 0, y: 0, z: 0),
new Point(x: 5, y: 7.5, z: 20),
),
new Face(
new Point(x: 0, y: 0, z: 0),
new Point(x: 0, y: 15, z: 0),
new Point(x: 5, y: 7.5, z: 20),
),
new Face(
new Point(x: 0, y: 15, z: 0),
new Point(x: 10, y: 15, z: 0),
new Point(x: 5, y: 7.5, z: 20),
Related Skills
node-connect
350.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
350.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
350.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
