Асимптота 3d: Убрать мерцание точек на игральной кости, чтобы играть?

Асимптота 3d: Убрать мерцание точек на игральной кости, чтобы играть?

Я закодировал свою первую фигуру с помощью Asymptote в 3d, которая представляет собой игральные кости с гранями, пронумерованными от одного до шести точек, представляющих числа от 1 до 6 классическим способом. Этими костями можно управлять с помощью мыши.

Проблема в том, что диски, представляющие точки, сверкают, когда вы манипулируете костями.

Когда я комментирую оператор draw (строка 25), draw(scale3(84a)*unitcube, surfacepen=white);то диски вообще не мерцают, но внезапно кости становятся прозрачными. Я делаю вывод, что проблема возникает из-за того, что синий цвет дисков накладывается на белый цвет граней. Поэтому решением было бы раскрашивать грани в два этапа, как это можно сделать с помощью Tikz:

  • Лица без дисков в пустом виде
  • Отдельные диски синего цвета

Но команды clip, fill, unfill, filldrawне работают с 3D- surface()функцией.

Как можно раскрасить грани игральных костей, не допуская мерцания?

Файл Asymptote .asyвыглядит следующим образом (код не оптимизирован для удобства чтения):

import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight; 
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path    carre = box ((0,0),(84a,84a)),
        disque = scale(9a)*unitcircle,
        patron1[] = shift(42a,42a)*disque,
        patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
        patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
        patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
        patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
        patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift(84a*X), tY=shift(84a*Y), tZ=shift(84a*Z);       
path3   facegauche[] =path3(patron6,ZXplane),
        facedroite[] =path3(patron1,ZXplane),
        faceavant[] =path3(patron2,YZplane),
        facearriere[] =path3(patron5,YZplane),  
        facehaut[] =path3(patron4,XYplane),     
        facebas[] =path3(patron3,XYplane);      
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);

решение1

После французского ответа на французском форуме, пожалуйста, найдите приблизительный английский ответ. На самом деле диски находятся на/в гранях куба, но невозможно узнать, каково относительное положение дисков по отношению к граням. В зависимости от численного приближения диски находятся выше/ниже граней, а числовые артефакты создают мерцания.

Решение 1): сместить каждый диск в правильном направлении, которое предлагается здесь

import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path    carre = box ((0,0),(84a,84a)),
      disque = scale(9a)*unitcircle,
      patron1[] = shift(42a,42a)*disque,
      patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
      patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
      patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
      patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
      patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a+00.1)*X), tY=shift((84a+.001)*Y), tZ=shift((84a+0.01)*Z);      
path3    facegauche[] =shift(0,-0.001,0)*path3(patron6,ZXplane),
      facedroite[] =path3(patron1,ZXplane),
      faceavant[] =path3(patron2,YZplane),
      facearriere[] =shift(-0.001,0,0)*path3(patron5,YZplane),   
      facehaut[] =path3(patron4,XYplane),      
      facebas[] =shift(0,0,-0.001)*path3(patron3,XYplane);      
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);

Решение 2): создать реальную поверхность граней игральных костей. Обновление: пожалуйста, найдите 2-е решение. Действительно, bezulateможно преобразовать 2D-путь в 3D. Согласно документации,

Плоские поверхности Безье строятся с помощью процедуры bezulate Ореста Шардта, которая разбивает (возможно, неодносвязные) области, ограниченные (в соответствии с правилом заполнения с нулевой обмоткой) простыми циклическими путями (пересекающимися только в конечных точках), на подобласти, ограниченные циклическими путями длиной 4 или меньше.

Для создания отверстия необходимо использовать reverse(бег назад по пути): например bezulate(unitsquate^^reverse(scale(.3)*unitcircle)). Затем surface(bezulate(unitsquate^^reverse(scale(.3)*unitcircle)))создается поверхность единичного квадрата с небольшим отверстием. Код для полной кости.

import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
//settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path    carre = box ((0,0),(84a,84a)),
      // reverse est capital pour créer les trous avec bezulate
      // c'est la règle : unitsquare et disque ne seront pas dans le
      // même sens, donc bezulate comprend que c'est un trou
      disque = scale(9a)*reverse(unitcircle),  

      patron1[] = shift(42a,42a)*disque,
      patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
      patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
      patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
      patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
      patron6[]=  shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a)*X), tY=shift((84a)*Y), tZ=shift((84a)*Z);      
path3    facegauche[] =path3(patron6,ZXplane),
      facedroite[] =path3(patron1,ZXplane),
      faceavant[] =path3(patron2,YZplane),
      facearriere[] =path3(patron5,YZplane),   
      facehaut[] =path3(patron4,XYplane),      
      facebas[] =path3(patron3,XYplane);      

 //   draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
 // les faces trouées
path[] gp6=bezulate(scale(84a)*unitsquare^^patron6);
path[] gp5=bezulate(scale(84a)*unitsquare^^patron5);
path[] gp4=bezulate(scale(84a)*unitsquare^^patron4);
path[] gp3=bezulate(scale(84a)*unitsquare^^patron3);
path[] gp2=bezulate(scale(84a)*unitsquare^^patron2);
path[] gp1=bezulate(scale(84a)*unitsquare^^patron1);
surface s1=shift((0,84a,84a))*rotate(90,Y)*rotate(90,X)*surface(gp1);
surface s2=shift(84a,0,0)*rotate(-90,Y)*surface(gp2);
surface s3=surface(gp3);
surface s4=shift((0,0,84a))*surface(gp4);
surface s5=shift((0,0,84a))*rotate(90,Y)*surface(gp5);
surface s6=shift((0,0,84a))*rotate(90,Y)*rotate(90,X)*surface(gp6);
draw(s6,red);
draw(s5,red);
draw(s4,red);
draw(s3,red);
draw(s2,red);
draw(s1,red);

и результат

введите описание изображения здесь

ОГ

Связанный контент