2月29日 Clover 界面,以及关于折叠的流程

WPF的界面制作功能真的是无比强大。虽然我并不是美工,但我通过精确复制网上某位设计师的作品(其实就是一张截图)

完成了这个……

今天晚上把折叠的逻辑步骤理了一遍,现在思路清晰多了,写代码效率也高很多。当然暂时我这边还不能写交互,因为要等他们把纸张显示到屏幕上。

徐小孟师兄的字好漂亮啊

接下来的工作,在C#中完成VisualInfo类。

本文链接

2月28日 Clover 使用新版本的Mogre+Wpf

昨天下载的那个版本是非常老旧的,其中.net运行时是3.5,对应的ogre和mogre版本是1.4.8……所以,当我尝试在我的Win7上面编译这个程序的Debug版本时,出现了一大堆乱七八糟的警告。最后程序是跑起来了,但是窗口一片空白,啥也没有。

幸好网上牛人非常的多,其中一位在前人的基础上,将MogreInWpf升级到了.net4.0+Ogre1.7

下载传送门:https://bitbucket.org/JaredThirsk/mogreinwpf/overview

下载分两部分,一部分是Dependency,大概10M。另外一部分是MogreImage,大概900多kb,需要使用版本控制器下载。下载好两个以后,将Dependency放入MogreImage,直接编译就能通过(如果你是Win7,有.net4.0Framework和DirectX9SDK的话……)

运行的窗口是这样的:

你会看到一堆ogre头在很囧地滚来滚去。在右边的Test栏可以很清楚地看到许多有用的信息,比如当前帧率。这个Demo程序甚至有鼠标拾取。另外,还可以通过拖动控件来改变一些测试选项,来测试Wpf的性能,比如这样:

又比如这样:

再比如这样……

这个Demo程序还使用了Wpf的多线程,总而言之是个非常强大的演示教学程序!

再次感叹,网上牛人就是多……

本文链接

2月27日 Clover 将Clover转移到C#平台

前一段时间一直在忙另外一个项目,Clover就被搁置下来了。最终那个项目告一段落,要重拾进度,继续完成Clover。

由于上一个项目我用的是WPF做界面,当我再切换回Clover时,发现CEGUI的界面是那么的苍白。事实上当初在Clover立项时,我们曾想过完全使用WPF。然而,WPF对3D的支持明显没有它宣传的那么好,于是我们转向了Ogre。如果能够使用Ogre渲染3D场景,再用WPF制作界面,那就太好了!幸好,由于网上许多牛人不懈的努力,使Ogre+WPF成为了可能:

1.Ogre本身提供C#的包装类Mogre

传送门:http://www.ogre3d.org/tikiwiki/Mogre

2.网上有个牛人专门写了个工程,在WPF中集成了Mogre

传送门:http://www.codeproject.com/Articles/29190/Blend-the-OGRE-Graphics-Engine-into-your-WPF-proje

其实在WPF中集成Ogre的原理很简单,就是将3D场景用Ogre渲染成纹理,再装载到WPF的Image中。

要使用非常简单

首先要在这个地址下载OgreInWpf工程:http://www.codeproject.com/Articles/29190/Blend-the-OGRE-Graphics-Engine-into-your-WPF-proje

上面的地址导向的页面有讲解该如何使用OgreInWpf。工程本身就是个例子,下载下来改造一下就可以给自己的项目使用。

唯一需要注意的一点就是,该项目的.net运行时是3.5,所以当你尝试使用.net4.0运行工程时,它会报错。

解决方法很简单,找到工程下面的app.config文件,用记事本打开,在<startup>中加入键值useLegacyV2RuntimeActivationPolicy=true

就像这样:

<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>

在C#中Ogre的用法与C++中的大同小异,都是一些命名规范上的不同。

下一步的工作是,把Clover移植到C#中。


本文链接

CubeTest 老项目

这个项目是在大二上学期完成的,为了拿来交数据结构与算法课程的大作业

大概花了大半个学期的时间,使用的语言是C++,使用了郝靖同学提供的一个2D贴图库

郝靖同学的2D贴图库名字叫做2dRender,基于dx9,并且用上了多线程(虽然现在看来毫无意义……)。这是他在大一时候完成的,感谢郝靖同学!

我的本意是想把CubeTest做成一个重力感应的游戏,通过改变屏幕方向来改变重力方向,让玩家操控小球走过陷阱重重的迷宫。

然而由于缺少在手机上编程的经验,只好改为在电脑上实现,通过鼠标操控。

一路上,小球要通过吃能量来维持自己的生命。如果能量归零,则游戏结束。

小球还有血量,如果触发机关则会掉血。血量归零游戏也结束。

为什么要做这个呢,主要是想自己写个2D的物理引擎。

后来发现这是一件非常困难的事情,虽然到最后我也或多或少的实现了一些物理引擎的功能(比如重力,比如反弹,比如摩擦)。

我现在依旧记得,当时我桌面上那满满一叠的物理和数学草稿纸。

这也是我第一次与他人合作的一个编程作品。

我们组三个人。我是组长,另外两人是廖南濠和李润超。

其中廖南豪负责迷宫生成算法,李润超负责屏幕坐标转换和贴图,我负责物理引擎以及一些乱七八糟的东西。

在团队合作这件事情上我犯了很大的错误,因为我已经习惯于一个人单打独斗,所以我包揽了大部分工作,并且喜欢一个人闷声编程。

这在后面引起了某位组员的不满情绪。

不过我也吸收了经验教训,在之后的项目中都有做到和组员良好互动。

本文链接

Snake贪吃蛇 老项目

这是我在大一的时候完成的,也是我的第一个编程作品。花了一个暑假的时间完成,使用的语言是C++,使用了第三方图像库CxImage

那时候我除了会在黑白框(控制台)里面cout一堆毫无意义的东西以外,什么都不懂。

首先我花了大量的时间了解了Windows窗口的创建和管理机制,以及它的消息传递机制

其后我又花了大量的时间纠结该如何贴图

由于是第一次一个人完成这么大一个程序(七千行代码量),明明规范注释什么的真的没有注意

而且全局变量随便乱用,代码冗余毫无可读性,完全没有面向对象的思想

并且直到最后,我的程序依然有严重的内存泄露……

不过,这个作品却是我大学生涯的转折点

正是由于这个作品,我发现我自己深深地迷恋上了编程,踏上了程序员的不归路……

有三种游戏模式选择

游戏中所有图片(背景除外)都是由我一手设计绘画的

也是从这个作品开始,同学们觉得我是个做界面的高手

以至于之后许多人都认为我是个“搞界面的”

虽然说在后来很多项目中,我也包揽了做界面的工作,实际上我是逼不得已

因为除了我之外没人能做界面

但其他人看不见你七千行代码的努力,其他人能看见的就是界面

所以我也悟出来一个道理,无论内在如何,界面一定要做的漂亮……在现在这个社会就是真理

贪吃蛇一期:http://antdiscovered.blog.163.com/blog/static/1143646512010621102331304/

贪吃蛇二期:http://antdiscovered.blog.163.com/blog/static/1143646512010717111726298/

本文链接

2月8日 Clover VisualInfo架构设计

因为现在只有高亮这一块的需求是比较明确的,所以先根据高亮这个需求来设计架构

首先由于要绘制高亮的区域,因此必然会有类型为ManualObject的实例成为VisualInfo的成员,这就引出了两个问题:

1.使用ManualObject需要为其指定Material, ogre规定每个Material的名称必须唯一

2.ogre规定每个ManualObject也必须有个唯一的名字

由于Material的可重用性,第一个问题很好解决。只需要把VisualInfo做成单例模式,就能保证不会重复初始化Material

实际上把VisualInfo做成单例是非常有必要的。因为VisualInfo将会成为BasicPicker的成员

而实际上VisualInfo只需要在全局保存一份副本就足够了

对于第二个问题就比较麻烦,因为必须要为每个视觉效果创建一个ManualObject出来。

单就高亮来说,如果规定,每时每刻只能有一处地方被高亮

那么一切不成问题,只需要保存一个ManualObject,再通过beginUpdate和setVisible操作就可以了

可是需求中,所有高亮元素应该支持淡出和淡入的视觉效果

因此一个ManualObject在它的生存周期内,它最多会经历以下五个阶段:

看样子只有新创建一个类VIElement,并使其派生自ManualObject

VIElement内部保存实例的当前状态,以及对应的接口函数。

VIElement将会是特定的视觉元素(如VIFaceHeightLight)的父类。

而VIElement自己将作为VisualInfo的类成员存在

由于在同一时刻,可能会同时有数个ManualObject存在,因此需要有个list来保存当前仍然生存的ManualObject

这样,每一次循环时,只需要依次遍历list里面的元素,并根据其相应的状态调用相应的接口函数就可以了

def update(self):
"""
Update and display all the elements in Visual Info Element List.
@note: This function should be called in frameRenderingQueued.
"""
# VIEL Visual Info Element List
if len(self.VIEL) == 0:
return
for element in self.VIEL:
if element.state == "fadein":
element.fadeIn()
elif element.state == "display":
element.display()
elif element.state == "fadeout":
element.fadeOut()
elif element.state == "destory":
self.VIEL.remove(element)
del element

当鼠标移动到一个Face上面的时候,会发生什么事呢?

1. BasicPicker会拾取到当前Face,储存到overedElement中

2. 在BasicPicker的onMove()函数里面会根据overedElement的name属性判断出这是个Face

并调用_onOverFace()函数

3. 在特定的继承自BasicPicker的工具(如SimplePicker)里,开发人员重载(或者说实现)_onOverFace()函数

并在_onOverFace()函数内调用VisualInfo的相关函数来进行高亮操作

以下是实现Face,Edge和Vertex高亮的具体算法

本文链接

2月7日 Clover VisualInfo需求

接下来我的工作就是开始写视觉辅助信息类VisualInfo

俗话说的好,架构未动,需求先行

今晚先想了需求,以后再想架构

总体需求:

1. 绝大部分视觉或文字信息应该以2D屏幕坐标而不是3D世界坐标为基础绘制

2. 绝大部分视觉效果应使用淡出淡入动画

3. 要做到简洁,清晰,智能

VisualInfo应该提供以下的功能:

1. 元素高亮

当鼠标拾取或移动到某个元素上时,应该高亮该元素

悬停使用黄色,拾取使用蓝色,绿色待定

要支持多处同时高亮

2. 鼠标操作

 

3. 辅助信息

当折叠操作发生时

以残影的方式显示元素原来的位置(可能需要在3D中作图)

以点状线显示移动路径

显示面与面之间的夹角,该面与多个面同时存在夹角,则显示与多个面的夹角

当绘制折线时

以分数形式显示被拆分的边每部分所占的比例

能遇见到的要使用的技术:

需要将3D世界坐标中的点转化为屏幕坐标(杨旭瑜已实现)

使用ManualObject在(0,0,-1)到(1,1,-1)的坐标范围内作图,并管理ManualObject的创建和销毁

自定义材质以支持视觉效果,并管理这些材质的创建和销毁

VisualInfo应创建为单例,并成为BasicPicker的成员

需要与FrameListerer进行交互,以支持动画


本文链接

2月6日 Clover

今天把亮哥把逻辑层的数据结构基本写出来了,参考的这篇论文:

http://www.om.sist.chukyo-u.ac.jp/main/research/origami/journal/jvca.html

我这边配合着亮哥的数据结构,把鼠标拾取那块基本写完了。

进度上,我们两个人应该是快于徐小孟的。明天问问徐小孟那边怎么样了。

至于杨旭瑜他那边的进度……好吧我要去催催他

本文链接

2月5日 Clover 与徐小孟关于鼠标拾取及需求的讨论

因为手中缺乏折纸的数据结构,所以只好用我自己的导航立方体来研究下ogre的拾取问题

昨天重写了Cube,现在通过使用面索引点的方式来储存数据

# point list
PL = [[-20, 20, 20], [-20, -20, 20], [20, -20, 20], [20, 20, 20],
[-20, 20, -20], [-20, -20, -20], [20, -20, -20], [20, 20, -20]]
# index list /ft/bk/lt/rt/up/dn
IL = [[0,1,3], [3,1,2],
[7,6,4], [4,6,5],
[4,5,0], [0,5,1],
[3,2,7], [7,2,6],
[4,0,7], [7,0,3],
[1,5,2], [2,5,6]]
# height light index list
HIL = [[0,1,3,2], [7,6,4,5], [4,5,0,1],
[3,2,7,6], [4,0,7,3], [1,5,2,6]]
# texture coordinates list
TC = [[[0.6667, 0], [0.6667, 1], [0.8333, 0]],
[[0.8333, 0],[0.6667, 1], [0.8333, 1]],
[[0.833, 0], [0.833, 1], [1, 0]],
[[1, 0], [0.833, 1], [1, 1]],
[[0.3333, 0], [0.3333, 1], [0.5, 0]],
[[0.5, 0], [0.3333, 1], [0.5, 1]],
[[0.5, 0], [0.5, 1], [0.6667, 0]],
[[0.6667, 0], [0.5, 1], [0.6667, 1]],
[[0, 0], [0, 1], [0.1667, 0]],
[[0.1667, 0], [0, 1], [0.1667, 1]],
[[0.1667, 0], [0.1667, 1], [0.3333, 0]],
[[0.3333, 0], [0.1667, 1], [0.3333, 1]]]

另外今天中午和徐小孟讨论了一下关于折纸逻辑层的数据结构应该怎么处理

徐小孟找到了一篇关于折纸的论文:http://www.om.sist.chukyo-u.ac.jp/main/research/origami/journal/jvca.html

下面是我和徐小孟交流的一些记录:

屠文翔  15:31:28
师兄我跟你描述一下我这边的需求吧
徐小孟 15:31:36
恩,好的。。
我想根据这篇文章把我的数据结构重做
屠文翔 15:32:19
恩恩,我先把需求明确了就免得走弯路了
徐小孟 15:32:26
恩,好的。。
你说
屠文翔 15:32:29
首先我高亮的话肯定是高亮逻辑上的点,面和边
高亮渲染三角形是没有意义的
徐小孟 15:32:44
恩,
然后
屠文翔 15:33:00
所以实际上我拾取的是逻辑上的单元,那这个计算量就急剧下降了
徐小孟 15:33:28
基本的鼠标操作
1,拾取一个顶点
2.移动一个拾取的顶点
3释放拾取的顶点
取线上一点就做bending
屠文翔 15:34:09
我的搜索步骤是
1先判断鼠标是不是在一个逻辑面内
2判断鼠标是不是靠近一条逻辑边
3判断鼠标是不是靠近一个逻辑点
徐小孟 15:34:24
恩,这个是拾取逻辑

主要还是这两种吧。。
屠文翔 15:34:49
这就要求树的基本节点是面了~
这是我的第一点需求~
徐小孟 15:35:14
你看到图了么
屠文翔 15:35:17
看到了
徐小孟 15:35:20
你怎么取折线
屠文翔 15:35:35
那是算法问题了,我现在只是要结构
徐小孟 15:35:39
恩,好的
那先放下。。
你继续
屠文翔 15:36:13
然后就是,为了判断我是否在一个逻辑面内,我需要知道组成这个逻辑面的几个逻辑点的位置
徐小孟 15:36:26
记下了
这个在我现在的数据结构里面有
屠文翔 15:36:36
而这个位置却是渲染顶点的位置了
恩恩
徐小孟 15:36:52
然后?
屠文翔 15:37:01
所以我感觉逻辑层和渲染层一个最关键的联系就是这些
逻辑点,和它们所对应的渲染顶点
徐小孟 15:37:17
其实你不用考虑渲染层的东西
那个我会做算法去映射出来的
屠文翔 15:37:31
这些特殊的渲染顶点可以称为关键顶点了
徐小孟 15:37:37

只考虑关键顶点
逻辑顶点
有点乱
屠文翔 15:37:55
可是我总得知道他的渲染位置
徐小孟 15:37:57
其实渲染顶点就vertex
屠文翔 15:38:00
否则我如何做拾取呢
徐小孟 15:38:02
逻辑顶点就point
屠文翔 15:38:06
恩,好
这样,我要知道point的位置,才能做拾取
徐小孟 15:38:27
渲染位置不用需要知道吧
恩,对
知道point就行了
我保证数据中有point
屠文翔 15:38:44
而point的位置,刚好就是它所对应的关键vertex的位置
徐小孟 15:38:48
point做成tuple
恩,所有vertices用point去算
屠文翔 15:39:13
或者你确保你在point的数据结构里面有储存关于它的位置信息就好
徐小孟 15:39:28
恩,我也才找到那篇文章
我再看下这个文章
修正数据结构先
屠文翔 15:39:43
还有就是关于拾取的,其实有三个选择
1.由鼠标做射线映射到3D,然后在3D中判断
2.由3D映射到屏幕坐标,然后在2D中判断
屠文翔 15:40:50
3.用特殊的颜色信息标记每一个面,把他们渲染到texture里面,通过hittest判断
徐小孟 15:41:26
感觉第一种靠谱
个人感觉
屠文翔 15:41:35
我的第三个需求是,希望你能够结合自己的结构,考虑一下用哪种好,
徐小孟 15:41:45
恩 ,好的
屠文翔 15:41:52
并且改进自己的结构使之适应其中的一种
徐小孟 15:41:56
我先考虑下。。

这部分我来考虑。。你们先做做别的哈
我的数据需要重做
屠文翔 15:43:25
恩恩

今天下午先继续研究一下令人蛋疼的四元数,我对ogre里面对旋转的处理机制还真是一知半解

本文链接