I finally managed to finish the triangular shaped kaleidoscope (its not that straightforward):
Hope it works for you guys. Have fun
PHP Code:
// Kaleidoscope (triangle base)
// v0.1
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//@param1:preview 'preview' 0 0 1 0 1
//@param3:cxn 'center x' 0.5 0 1 0.5 0.01
//@param4:cyn 'center y' 0.5 0 1 0.5 0.01
//@param5:lenn 'length' 0.25 0 1 0.5 0.01
//@param6:rot 'rotate' 0 0 360 180 1
//@param7:sc 'scale' 1 0.01 5 2.5 0.01
//@param9:bg 'graylevel background' 0.5 0 1 0.5 0.01
///@param11:debug 'debug' 0 0 3 2 1
function gfx_line(x,y,x2,y2,t) local(i,n,dx,dy,dxn,dyn) (
dx=(x2-x); dy=(y2-y);
n=abs(dx)+abs(dy);
dxn=dx/n; dyn=dy/n;
i=0;
loop(n,
gfx_fillrect(x+i*dxn,y+i*dyn,t,t);
i+=1;
);
gfx_fillrect(x2,y2,1,1);
);
function pt(x,y) instance(x,y) (
this.x=x;
this.y=y;
);
function pRot(cx,cy,a) local(tx,ty) instance(x,y) (
tx=x-cx;
ty=y-cy;
x=tx*cos(a)-ty*sin(a);
y=tx*sin(a)+ty*cos(a);
x+=cx;
y+=cy;
);
!initdone ? (
sqrt3div6=sqrt(3)/6;
lrot=lcxn=lcyn=llenn=-1;
initdone=1;
);
lcxn!=cxn || lcyn!=cyn || llenn!=lenn || lrot!=rot || lsc!=sc || lproject_w!=project_w || lproject_h!=project_h ? (
cx=(cxn*project_w)|0;
cy=(cyn*project_h)|0;
lenNoSc=lenn*max(project_w,project_h);
trApoNoSc=(sqrt3div6*lenNoSc)|1; // apothem/height of center
trHnoSc=trApoNoSc*3;
lenNoSc=(trApoNoSc/sqrt3div6)|1;
wslenNoSc=(sqrt(2*((4*trApoNoSc)^2))+2)|1;
p1.pt(cx-(lenNoSc-1)/2, cy+trApoNoSc);
p2.pt(cx+(lenNoSc-1)/2, cy+trApoNoSc);
p3.pt(cx, cy-trApoNoSc*2);
rotrad=$pi/180*rot;
p1.pRot(cx,cy,rotrad);
p2.pRot(cx,cy,rotrad);
p3.pRot(cx,cy,rotrad);
linew=(max(project_w,project_h)/200)|1;
trApo=(sqrt3div6*lenNoSc*sc)|1;
trH=trApo*3;
len=(trApo/sqrt3div6)|1;
wslen=(sqrt(2*((4*trApo)^2))+2)|1;
startX=(wslen-len)/2;
l1.a=-2*trH/len;
l1.b=wslen/2+trApo-l1.a*startX;
l2.a=-l1.a;
l2.b=wslen/2+trApo-l2.a*(wslen+len)/2;
l3.b=wslen/2+trApo;
minX=min(p1.x, min(p2.x,p3.x)) -cx+project_w/2;
maxX=max(p1.x, max(p2.x,p3.x)) -cx+project_w/2;
minY=min(p1.y, min(p2.y,p3.y)) -cy+project_h/2;
maxY=max(p1.y, max(p2.y,p3.y)) -cy+project_h/2;
rotoDx=max(0,max(-minX,maxX-project_w));
rotoDy=max(0,max(-minY,maxY-project_h));
rwsw=project_w+2*rotoDx;
rwsh=project_h+2*rotoDy;
lcxn=cxn; lcyn=cyn; llenn=lenn; lrot=rot; lsc=sc; lproject_w=project_w; lproject_h=project_h;
);
input=0;
colorspace='RGBA';
preview ? (
gfx_blit(input);
gfx_set(1,0,0);
gfx_fillrect(cx-(linew-1)/2,cy-(linew-1)/2,linew,linew);
gfx_line(p1.x,p1.y,p2.x,p2.y,linew);
gfx_line(p2.x,p2.y,p3.x,p3.y,linew);
gfx_line(p3.x,p3.y,p1.x,p1.y,linew);
):(
gfx_set(bg);
// add margins to work with rotoblit()
gfx_dest = ws1 = gfx_img_resize(ws1,rwsw,rwsh,1);
gfx_blit(input,0,rotoDx,rotoDy,project_w,project_h);
// rotate
gfx_dest = ws2 = gfx_img_resize(ws2,rwsw,rwsh,1);
gfx_rotoblit(ws1,-rotrad, 0,0,rwsw,rwsh, 0,0,rwsw,rwsh, 0, -rwsw/2+cx+rotoDx, -rwsh/2+cy+rotoDy);
// crop to square (scaled)
gfx_dest = ws3 = gfx_img_resize(ws3,wslen,wslen,1);
gfx_blit(ws2,0, 0,0,wslen,wslen, rwsw/2-(wslenNoSc-1)/2,rwsh/2-(wslenNoSc-1)/2,wslenNoSc,wslenNoSc);
// set alpha (create triangle)
code="
_1>wslen-1 ? (_2+=1;_1=0;);
_2>wslen-1 ? _2=0;
_2>l3.b || _2<l1.a*(_1+1)+l1.b || _2<l2.a*_1+l2.b ? a=0;
_1+=1;
";
gfx_evalrect(0,0,wslen,wslen,code);
// create template of 6 rotated/mirrored triangles
gfx_dest = templates = gfx_img_resize(templates,3*len,2*trH);
// upper left
gfx_blit(ws3,0, 0,0,len,trH, startX,(wslen-1)/2-2*trApo,len,trH);
// upper mid
gfx_dest = rotTr = gfx_img_resize(rotTr,wslen,wslen,1);
gfx_rotoblit(ws3,$pi/3,0, 0, wslen, wslen , 0, 0, wslen, wslen, 0, 0, 0);
gfx_dest = mirrTr = gfx_img_resize(mirrTr,wslen,wslen,1);
gfx_deltablit(rotTr, 0,0, wslen,wslen, wslen-1,0, -1,0, 0,1);
gfx_dest=templates;
gfx_blit(mirrTr,0, len,0,len,trH, startX, (wslen-1)/2-trApo+1, len,trH);
gfx_evalrect(len,0,len,1,"a=255"); // remove some rotating artefacts (sporadic for some triangle length)
// upper right
gfx_dest = rotTr = gfx_img_resize(rotTr,wslen,wslen,1);
gfx_rotoblit(ws3,$pi*2/3,0, 0, wslen, wslen , 0, 0, wslen, wslen, 0, 0, 0);
gfx_dest=templates;
gfx_blit(rotTr,0, 2*len,0,len,trH, startX,(wslen-1)/2-2*trApo+1,len,trH);
gfx_evalrect(2*len,trH-1,len,1,"a=255;"); // remove artefacts
// create lower 3 triangles (mirror along x)
gfx_deltablit(templates, 0,trH, 3*len,trH, 0,trH-1, 1,0, 0,-1);
// build image
gfx_dest=-1;
gfx_set(bg);gfx_fillrect(0,0,project_w,project_w);
gfx_mode=gfx_mode|0x10000;
// !debug ? (
curX=-(len-1)/2;
curY=0;
curTr=lTr=0;
while(curY<=project_h) (
curTemX=(curTr%3)*len;
curTemY=(curTr/3)<1?0:trH;
gfx_blit(templates,0, curX,curY,len,trH, curTemX,curTemY,len,trH);
curX+=(len-1)/2;
curTr=(curTr+1)%6;
curX>project_w ? (
curY+=trH;
curX=-(len-1)/2;
curTr=lTr=lTr?0:3;
);
);
// ):debug==1 ? gfx_blit(ws2,1,0,0,project_w,project_h) : debug==2 ? gfx_blit(ws3,1,0,0,wslen,wslen) : debug==3 ? gfx_blit(templates,1,0,0,3*len,2*trH);
);