Код:
// глобальные переменные позволяют нам не заморачиваться
// с передачей параметров в методы, сделав т.о. код короче
const Vec3 TOWER_SHIFT( 0, 0, 200 );
const Vec3 FLOOR_SHIFT( 0, 200, 0 );
Vec3 tower = TOWER_SHIFT * (-4.5);
Vec3 floor( 0 );
Mesh a, b, mesh;
// с помощью `builder` создаём разные меши
Builder builder;
// используем `room` для формирования сцены
SculptRoom room;
void main() {
// подготавливаем сцену
room.clear().toSurface();
// капсула
{
// первый меш
a = builder.capsule()
// подготавливаем к строительству
.startPosition( Vec3( 0 ) )
.endPosition( Vec3( 40, 50, 60 ) )
.startRadius( 30 )
.endRadius( 50 )
// плотность сетки
.details( 0.1 )
// строим
.build();
// второй меш
b = builder.capsule()
.startPosition( Vec3( 0 ) )
.endPosition( Vec3( 20, 30, 40 ) )
.startRadius( 20 )
.endRadius( 30 )
.position( Vec3( 20, 30, 40 ) )
.details( 0.5 )
.build();
// рисуем меши `a` и `b`
// см. реализацию draw() в конце листинга
draw();
}
// конус
{
a = builder.cone()
.radius( 50 )
.height( 120 )
.details( 0.1 )
.build();
b = builder.cone()
.radius( 40 )
.height( 80 )
.position( Vec3( 10, 20, 30 ) )
.details( 0.5 )
.build();
draw();
}
// кубоид
{
a = builder.cuboid()
.side( Vec3( 100, 80, 60 ) )
.details( 0.1 )
.build();
b = builder.cuboid()
.side( Vec3( 30, 50, 70 ) )
.position( Vec3( 20, 30, 40 ) )
.details( 0.5 )
.build();
draw();
}
// цилиндр
{
a = builder.cylinder()
.positionTop( Vec3( 80, 0, 0 ) )
.positionBottom( Vec3( 0, 0, 0 ) )
.radiusTop( 40 )
.radiusBottom( 50 )
.details( 0.1 )
.build();
b = builder.cylinder()
.positionTop( Vec3( 70, 0, 10 ) )
.positionBottom( Vec3( 0, 0, 0 ) )
.radiusTop( 20 )
.radiusBottom( 30 )
.position( Vec3( 20, 30, 40 ) )
.details( 0.5 )
.build();
draw();
}
// эллипсоид
{
a = builder.ellipsoid()
.radius( Vec3( 80, 60, 40 ) )
.details( 0.1 )
.build();
b = builder.ellipsoid()
.radius( Vec3( 20, 40, 60 ) )
.position( Vec3( 20, 30, 40 ) )
.details( 0.5 )
.build();
draw();
}
// шестерёнка
{
a = builder.gear()
.startPoint( Vec3( 0, 0, 0 ) )
.endPoint( Vec3( 90, 90, 90 ) )
.topRadius( 30 )
.bottomRadius( 50 )
.relativeHoleRadius( 0.3 )
.depth( 0.5 )
.sharpness( 0.2 )
.teeth( 3 )
.details( 0.1 )
.build();
b = builder.gear()
.startPoint( Vec3( 20, 20, 20 ) )
.endPoint( Vec3( 50, 50, 50 ) )
.topRadius( 50 )
.bottomRadius( 50 )
.relativeHoleRadius( 0.3 )
.depth( 0.2 )
.sharpness( 1.0 )
.teeth( 6 )
.details( 0.5 )
.build();
draw();
}
// энгон
{
a = builder.ngon()
.startPoint( Vec3( 0, 0, 0 ) )
.endPoint( Vec3( 90, 90, 90 ) )
.topRadius( 30 )
.bottomRadius( 40 )
.relativeHoleRadius( 0.3 )
.teeth( 3 )
.details( 0.1 )
.build();
b = builder.ngon()
.startPoint( Vec3( 20, 20, 20 ) )
.endPoint( Vec3( 50, 50, 50 ) )
.topRadius( 50 )
.bottomRadius( 50 )
.relativeHoleRadius( 0.2 )
.teeth( 6 )
.details( 0.5 )
.build();
draw();
}
// труба
{
a = builder.tube()
.startPoint( Vec3( 0, 0, 0 ) )
.endPoint( Vec3( 30, 50, 70 ) )
.topRadius( 30 )
.bottomRadius( 40 )
.relativeHoleRadius( 0.8 )
.topScale( 2.0 )
.bottomScale( 1.0 )
.details( 0.1 )
.build();
b = builder.tube()
.startPoint( Vec3( 10, 20, 30 ) )
.endPoint( Vec3( 20, 40, 60 ) )
.topRadius( 20 )
.bottomRadius( 20 )
.relativeHoleRadius( 0.2 )
.topScale( 1.5 )
.bottomScale( 3.0 )
.details( 0.5 )
.build();
draw();
}
// сфера
{
a = builder.sphere()
.radius( 70 )
.details( 0.1 )
.build();
b = builder.sphere()
.radius( 40 )
.position( Vec3( 30, 40, 50 ) )
.details( 0.5 )
.build();
draw();
}
}
// выполняет булевы операции над мешами `a` и `b`
// и добавляет результат на сцену
void draw() {
floor = Vec3( 0 );
// объединение (add)
mesh = a | b;
mesh.tools().transform().position( tower + floor ).run();
room += mesh;
floor += FLOOR_SHIFT;
// вычитание (subtract)
mesh = a - b;
mesh.tools().transform().position( tower + floor ).run();
room += mesh;
floor += FLOOR_SHIFT;
// пересечение (intersect)
mesh = a & b;
mesh.tools().transform().position( tower + floor ).run();
room += mesh;
tower += TOWER_SHIFT;
}
Запустив скрипт в 3D-Coat, получаем такую картинку:
Обратите внимание на плотность сетки: она у фигур разная и сохраняется после булевых операций.
Код можно сократить, зная, что методы `
MeshX::build()
` и `ToolsX::run()
` могут выступать функторами. Т.е. можем писать: ...
a = builder.sphere()
.radius( 70 )
.details( 0.1 )
();
...
и
...
mesh.tools().transform().position( tower + floor )();
...
с тем же результатом.
Комментариев нет:
Отправить комментарий