魔方吧·中文魔方俱乐部

 找回密码
 注册
搜索
热搜: 魔方
查看: 16630|回复: 34
打印 上一主题 下一主题

Fenz 的在线魔方程序【更新变形魔方】 [复制链接]

银魔

魔方思者

Rank: 7Rank: 7Rank: 7

积分
3010
帖子
1832
精华
6
UID
102191
性别
保密
兴趣爱好
理论
结构
破解

四年元老

跳转到指定楼层
1#
发表于 2014-5-5 01:01:47 |只看该作者 |正序浏览
本帖最后由 Fenz 于 2014-5-21 21:40 编辑

本程序基于 SVG+JS 技术目前在 Chrome、FireFox、Safari、Opero、IE11 等浏览器下测试通过,国产的那些二次包装的浏览器就不一一测了。至于低版本的IE(9以下)不支持SVG,没有办法了,建议还是换更优秀的浏览器用吧。
代码是开源的,欢迎参考借鉴,更欢迎高手指点。

网址:http://uukoo.xjisu.cn/cube/

操作和胡老师的程序差不多,转视角操作略有不同,是用中键。
shift+中键拖拽是缩放,Alt+中键拖拽是调焦距,Ctrl+中键拖动是在屏幕面上旋转。
没有中键的朋友可以用其它键在魔方以外的地方拖拽,代替中键。Opera浏览器的中键行为比较怪异,请在魔方以外用左右键拖动。

5月9日更新了视角转动算法,将原来的二维转动改为三维转动,由于使用的是微分算法,和鼠标拖动事件的离散性,导致拖动过快时会有跳动的BUG,所以刻意减慢了转动速度比率。不知道其他程序是怎么处理三维视角转动,希望有人能指点一下。

5月10日更新视角控制规则,学习借鉴了胡波老师的算法,视角的三维旋转这块算是完善了。另外发现利用这个坐标变换矩阵,还能做许多有趣的事情。

魔方的转动具体是
二阶:直接点击转单层,Shift点击转整体;
三阶:直接点击转单层,Shift点击转中层,Ctrl点击转两层,Shift+Ctrl点击转整体

目前做了5个魔方。

这次更新除了修正五个魔方的链接都已经开放出来了,之前
有链接的魔方有三个,另外有两个隐藏魔方(都是市面上从未出现过的魔方,即偏门又奇怪),可以通过地址栏输入正确的地址访问到,给大家一点提示,看看有没有人能试出来。提示二:每个魔方的地址都是有规律的,前半段都一样。

其实

另外,隐藏的两个魔方也体现了我的程序的最大特点,也是和许多其他魔方程序的不同之处。

对了,上个截图才能在首页左上角显示。这是一个非常空的空心魔方。

2014-05-05_010554.png

Rank: 3Rank: 3

积分
803
帖子
575
精华
2
UID
1347349
性别
兴趣爱好
破解

两年元老 四年元老 六年元老

35#
发表于 2019-10-6 09:42:22 |只看该作者
看得出来:1#、2#、3#、7#、10#都是大神呀,向大神致敬。6#那些数据,那个大图,不要说其中关系,就是照着画画都费老劲。

使用道具 举报

Rank: 4

积分
1668
帖子
988
精华
8
UID
82833
性别
保密

魔方破解达人 六年元老

34#
发表于 2014-5-21 13:20:55 |只看该作者
Fenz 发表于 2014-5-20 21:04
svg比较面向对象,事件绑定比较方便。记得你的魔方是用canvas做的吧。
原来也想把你的反射魔方也加进去, ...

不错。我回头也试试SVG

使用道具 举报

银魔

魔方思者

Rank: 7Rank: 7Rank: 7

积分
3010
帖子
1832
精华
6
UID
102191
性别
保密
兴趣爱好
理论
结构
破解

四年元老

33#
发表于 2014-5-21 13:04:56 |只看该作者
schuma 发表于 2014-5-21 11:41
不错。我还没用过SVG来做过魔方。干得好!

svg比较面向对象,事件绑定比较方便。记得你的魔方是用canvas做的吧。
原来也想把你的反射魔方也加进去,但是还有一点法线问题。
要改进的地方蛮多,不打算改了,直接写2.0的节奏。

使用道具 举报

Rank: 4

积分
1668
帖子
988
精华
8
UID
82833
性别
保密

魔方破解达人 六年元老

32#
发表于 2014-5-21 11:41:34 |只看该作者
不错。我还没用过SVG来做过魔方。干得好!

使用道具 举报

Rank: 8Rank: 8

积分
9581
帖子
3769
精华
81
UID
4618
性别

论坛建设奖 十年元老

31#
发表于 2014-5-11 08:06:57 |只看该作者
Fenz 发表于 2014-5-10 16:16
最后还是改用了您的方法,用矩阵表示摄像机位置和方向,这样比我原来的算法少了许多三角函数和反三角函数 ...

使用道具 举报

银魔

魔方思者

Rank: 7Rank: 7Rank: 7

积分
3010
帖子
1832
精华
6
UID
102191
性别
保密
兴趣爱好
理论
结构
破解

四年元老

30#
发表于 2014-5-10 16:16:26 |只看该作者
hubo5563 发表于 2014-5-9 22:10
程序:
//////////////////////////////////////////////
//鼠标拖动事件处理

最后还是改用了您的方法,用矩阵表示摄像机位置和方向,这样比我原来的算法少了许多三角函数和反三角函数(以及带来的正负判断)等计算。矩阵这块看来我需要补一补。

使用道具 举报

银魔

魔方思者

Rank: 7Rank: 7Rank: 7

积分
3010
帖子
1832
精华
6
UID
102191
性别
保密
兴趣爱好
理论
结构
破解

四年元老

29#
发表于 2014-5-9 23:50:26 |只看该作者
本帖最后由 Fenz 于 2014-5-10 00:07 编辑
hubo5563 发表于 2014-5-9 22:10
程序:
//////////////////////////////////////////////
//鼠标拖动事件处理


多谢胡老师。我慢慢学习。
今晚我又写了另一个基于坐标变换的算法,看看是否正确可用,如果还行,就要借用您的算法了。

--------------
原来如此,我用的是通过三个表示摄像机状态的角来完成从世界坐标系到屏幕坐标的变换,相当于每次通过三角函数的计算得到变换矩阵,而您的程序则是直接储存这个变换矩阵来表示摄像机状态。

使用道具 举报

Rank: 8Rank: 8

积分
9581
帖子
3769
精华
81
UID
4618
性别

论坛建设奖 十年元老

28#
发表于 2014-5-9 22:10:10 |只看该作者
本帖最后由 hubo5563 于 2014-5-9 22:20 编辑
Fenz 发表于 2014-5-9 19:32
其实我的也不会改变魔方的坐标,改变的是摄像机的坐标。然后再根据摄像机坐标来投影绘图。原理是一样的, ...


程序:
//////////////////////////////////////////////
//鼠标拖动事件处理
public void mouseDragged(MouseEvent e){
    int x = e.getX();
    int y = e.getY();
    if (pushed)
    return;
    if (dragging) {
    if(prevy>top && prevy<height+top)
    {
    if (painted) {
      painted = false;
      double xtheta = (y-prevy) * (360.0d / getSize().width);     //计算按x轴转动的角度
      double ytheta = (prevx-x) * (360.0d / getSize().height);    //计算按y轴转动的角度
      SpinX(xtheta);                //变换矩阵
      SpinY(ytheta);                //变换矩阵
      Graphics gg=getGraphics();
      xianshimq(gg);             //显示魔方
      drawButtons(gg);           //画底下的按钮
      painted = true;
       };   
     };  
     };
    prevx = x;
    prevy = y;
    e.consume();
};



        初始化矩阵
       //将坐标变换矩阵设为单位矩阵
        da11=1;        da12=0;        da13=0;
        da21=0;        da22=1;        da23=0;
        da31=0;        da32=0;        da33=1;


void  SpinX(double jiao)
{
double a11,a12,a13,a21,a22,a23,a31,a32,a33;
double sina,cosa;
sina=Math.sin( jiao*Math.PI/180);
cosa=Math.cos( jiao*Math.PI/180);
a11=da11;
a21=cosa*da21+sina*da31;
a31=-sina*da21+cosa*da31;
a12=da12;
a22=cosa*da22+sina*da32;
a32=-sina*da22+cosa*da32;
a13=da13;
a23=cosa*da23+sina*da33;
a33=-sina*da23+cosa*da33;
//给全局变量赋值
da11=a11;da12=a12;da13=a13;
da21=a21;da22=a22;da23=a23;
da31=a31;da32=a32;da33=a33;
};
//以Y轴为轴魔方整体顺时针旋转一个角度
void  SpinY(double jiao)
{

        double a11,a12,a13,a21,a22,a23,a31,a32,a33;
double sina,cosa;
sina=Math.sin( jiao*Math.PI/180);
cosa=Math.cos( jiao*Math.PI/180);
a11=cosa*da11+sina*da31;
a21=da21;
a31=-sina*da11+cosa*da31;
a12=cosa*da12+sina*da32;
a22=da22;
a32=-sina*da12+cosa*da32;
a13=cosa*da13+sina*da33;
a23=da23;
a33=-sina*da13+cosa*da33;
//给全局变量赋值
da11=a11;da12=a12;da13=a13;
da21=a21;da22=a22;da23=a23;
da31=a31;da32=a32;da33=a33;
};

//以当前旋转矩阵变换三维点,整体旋转时采用
void  dbh3(Point3d p,Point3d pp)
{
        p.x=(pp.x)*da11+(pp.y)*da12+(pp.z)*da13;
        p.y=(pp.x)*da21+(pp.y)*da22+(pp.z)*da23;
        p.z=(pp.x)*da31+(pp.y)*da32+(pp.z)*da33;
};

//将三维坐标转换为2维透视坐标,转换x坐标
int  dbh5x(Point3d p)
{
double xx,zz;int ii;
xx=p.x+xx1;
zz=p.z+zz1;
xx=xx*zz0/(zz0+zz);
xx=xx0+factor_x*xx;
ii=(int)xx;
return ii;
};
//将三维坐标转换为2维透视坐标,转换y坐标
int  dbh5y(Point3d p)
{
double yy,zz;int ii;
yy=p.y+yy1;
zz=p.z+zz1;
yy=yy*zz0/(zz0+zz);
yy=yy0-factor_y*yy;
ii=(int)yy;
return ii;
};

经过变换就是屏幕的实际坐标。

使用道具 举报

银魔

魔方思者

Rank: 7Rank: 7Rank: 7

积分
3010
帖子
1832
精华
6
UID
102191
性别
保密
兴趣爱好
理论
结构
破解

四年元老

27#
发表于 2014-5-9 19:32:43 |只看该作者
hubo5563 发表于 2014-5-9 11:23
我处理的方法和你不同,鼠标拖动不改变模型的3D坐标。
我用一个矩阵记录转动积累,每次鼠标拖动计算x和y ...

其实我的也不会改变魔方的坐标,改变的是摄像机的坐标。然后再根据摄像机坐标来投影绘图。原理是一样的,区别在于算法。您用矩阵,我用的是坐标变换的微分关系。
我的算法是有问题的,所以想学习一下更好的算法。可否详细描述一下您的算法?

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|魔方吧·中文魔方俱乐部

GMT+8, 2025-5-2 15:10

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部