
Код:
// глобальные переменные позволяют нам не заморачиваться
// с передачей параметров в методы, сделав т.о. код короче
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 )();
        ... 
Комментариев нет:
Отправить комментарий