岁月流转,往昔空明

C++博客 首页 新随笔 联系 聚合 管理
  72 Posts :: 3 Stories :: 197 Comments :: 0 Trackbacks

2008年11月21日 #

     摘要: 设计模式小结的最后一篇,这样 GOF 2X 个模式就都齐全了。。。
欢迎大家喷。。。。  阅读全文
posted @ 2008-11-21 18:29 空明流转 阅读(566) | 评论 (0)编辑 收藏

2008年11月6日 #

这个工具源自于我的一个需求,
我将文档都保存在了硬盘上,只不过由于分布不够大而只能分开放置于多个文件夹中。
有时候我需要将这些数据进行备份,一张盘也放不下,也就需要备份到多张盘中。

此时问题出现了,如果我往硬盘上新添了一些文档,在我下一次备份的时,我如何准确的筛选出新增的文档。

一般来讲如果只是一个源盘和一个目标盘,用Beyond Compare或者类似的工具就能解决问题。
不过现在是多对多的,问题就变得比较复杂。

因此我就做了这么个东西,可以将多个目录组成虚拟的文件树再进行比较。
文件夹的对应关系直接利用同级文件夹的名称来判断
我也提供了手工设置文件夹对应关系的功能,不过因为UI方面还没考虑好所以没有加上。

文件之间的比较利用两种方案,一种方案在文件被计算过MD5效验的时候直接使用MD5比较
如果没有MD5的话使用文件大小和最后修改时间比较
由于文件比较不使用文件名,也就获得不了对应关系,因此目录树下面的所有文件的所有组合都要一一遍历。
同时由于计算MD5效验码需要读取整个文件,时间较长,因此Checksum是需要手动计算和刷新的。

最后就是树可以整棵的被保存到快照文件中,格式是XML的格式,人也可以读。
比较过后,可以某个子树或者单棵整树的相同文件或这新增文件拷贝到一个目录下。
本来希望能直接生成Nero的刻录清单的文件格式,后来找不到相关的资料就只好放弃了。

Download Source Code Project,VS2005 / VS2005 SP1, XP SP2/SP3下通过。



屏幕快照。红色表示新增文件,蓝色表示相同文件,黄色表示不完全对应。

posted @ 2008-11-06 23:48 空明流转 阅读(1169) | 评论 (6)编辑 收藏

2008年9月13日 #

呃,怎么说呢,这个和vczh的同名文章是互为补充的。这是最近老板的要求,所以就写了这么个东西。

vczh的方法生成的树是sparse的,而我这里树则要紧凑一些,所使用的坐标系也与之不同。

效果(看起来挺菜,哇咔咔)


布局分为水平布局和竖直布局两个部分,我这里先进行了水平布局再进行了竖直布局。

一般来讲紧凑的树主要指同级节点方向上的紧凑性。由于这里树是父节点在上,子结点在下,因此水平方向上的节点要尽量紧凑。那么便需要我将节点尽量往左布局。
如果自左往右布置节点,那么很显然,左边的节点的位置一旦固定下来就不需要再行调整。
同时,为了保持树的美观,父节点的水平中心应当是子结点的水平中心,这样子结点就会对称分布在父节点的下方,有利于美观。
然而父节点能正常布局的位置,子结点可能无法正常布局(子结点的宽度比父节点宽得多)。因此我们还需要调整子结点的布局。
由于是自左向右布局的,此时子结点的左边的节点都已经确定了,正确的布局很容易便可以通过右移得到。
为了保证正确性,还需要把父节点也右移。因为父节点的右边没有布局限制,因而可以放心的右移。这样一直传递到根节点就可以了。
那么很明显,整体来说,布局顺序就是,自下而上,自左而右。

为了让节点在布局的时候知道自己能被安排的最左位置,需要为每一层保存最左可布局位置的坐标。
一旦有节点被安排妥当,便更新节点所在层次的最左可布局位置。后来的节点只要在这个位置的右方布局,就不会与已布置的节点冲突。

竖直布局并不复杂,算出每一层的Top就可以了。

代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

//布局算法:
//采用平行节点最左布局,父子节点对中布局的原则。

/****
 *  void Layout(int lyr)
 *  {
 *     
 *  }
 * 
****
*/
namespace CrowdTree
{
    
class LayoutTreeLayerInfo
    {
        
//可安排布局的最左坐标
        private Dictionary<intfloat> lyrLefts = new Dictionary<int,float>();
        
private Dictionary<intfloat> heights = new Dictionary<int,float>();

        
public void Reset()
        {
            lyrLefts 
= new Dictionary<intfloat>();
            heights 
= new Dictionary<intfloat>();
        }

        
public float GetLayoutableLeft(int level)
        {
            
if (lyrLefts.ContainsKey(level))
            {
                
return lyrLefts[level];
            }
            
return 0;
        }

        
public void SetLayoutableLeft(int level, float left)
        {
            
if (lyrLefts.ContainsKey(level))
            {
                lyrLefts[level] 
= Math.Max(left, lyrLefts[level]);
            }
            
else
            {
                lyrLefts[level] 
= Math.Max(0, left);
            }
        }

        
public void SetLayoutLevelMinHeight(int level, float height)
        {
            
if (heights.ContainsKey(level))
            {
                heights[level] 
= Math.Max(heights[level], height);
            }
            
else
            {
                heights[level] 
= height;
            }
        }

        
public float GetLayoutLevelMinHeight(int level)
        {
            
if (heights.ContainsKey(level))
            {
                
return heights[level];
            }
            
return 0;
        }
    }

    
class LayoutTreeNode
    {
        
protected LayoutTree owner_;
        
protected LayoutTreeLayerInfo lyrInfo_;
        
protected int lyrLevel_;
        
protected RectangleF rect_;
        
protected List<LayoutTreeNode> children_ = new List<LayoutTreeNode>();

        
public int Level
        {
            
get { return lyrLevel_; }
            
set { lyrLevel_ = value; }
        }

        
public LayoutTree Owner
        {
            
get { return owner_; }
            
set { owner_ = value; }
        }

        
public LayoutTreeLayerInfo LayerInfo
        {
            
set { lyrInfo_ = value; }
        }

        
public List<LayoutTreeNode> Children
        {
            
get { return children_; }
        }

        
public RectangleF Extent
        {
            
get { return rect_; }
        }

        
protected void LayoutHorizontal()
        {
            
//获取当前节点能够排布的最左位置,并预先安排当前节点。
            float originLeft = lyrInfo_.GetLayoutableLeft(lyrLevel_);
            rect_.X 
= originLeft;

            
//根据当前结点的坐标,安排子结点,并需要根据子结点的安置情况重新调整父节点的安置
            if (children_.Count > 0)
            {
                
//计算子结点最左可以安放的位置
                float childrenTotalWidth = 0.0F;
                
foreach (LayoutTreeNode child in children_)
                {
                    childrenTotalWidth 
+= child.Extent.Width;
                }
                childrenTotalWidth 
+= ((children_.Count - 1* owner_.HorizontalSpacer);
                
float childLeftest = originLeft + (rect_.Width / 2.0f- (childrenTotalWidth / 2.0F);

                
//设置子结点安放的最左位
                lyrInfo_.SetLayoutableLeft(lyrLevel_ + 1, childLeftest);

                
//安放子结点
                for (int idxChild = 0; idxChild < children_.Count; ++idxChild)
                {
                    children_[idxChild].LayoutHorizontal();
                }

                 
//利用子结点重新对中安置当前节点
                float center = (children_[0].Extent.Left + children_[children_.Count - 1].Extent.Right) / 2.0F;
                rect_.X 
= center - rect_.Width / 2.0F;
            }

            
//利用节点坐标设置该层其他子结点所能安放的最左位置,并设置一下当前层元素的最大高度
            lyrInfo_.SetLayoutableLeft(lyrLevel_, this.rect_.Right + owner_.HorizontalSpacer);
            lyrInfo_.SetLayoutLevelMinHeight(lyrLevel_, 
this.rect_.Height);
        }

        
protected void LayoutVertical(float top)
        {
            rect_.Y 
= top;
            
foreach (LayoutTreeNode child in children_)
            {
                child.LayoutVertical(top 
+ lyrInfo_.GetLayoutLevelMinHeight(lyrLevel_) + owner_.VerticalSpacer);
            }
        }

        
public void Layout()
        {
            LayoutHorizontal();
            LayoutVertical(
0.0f);
        }

        
public virtual void CalculateSize(float maxWidth, Font font, Graphics g)
        {
        }

        
public virtual void CalculateSizeRecursive(float maxWidth, Font font, Graphics g)
        {
        }

        
public virtual void Draw(Graphics g) { }
    }

    
class TextLayoutTreeNode: LayoutTreeNode
    {
        
private string text;
        
private StringFormat strFmt = new StringFormat();
        
private Font font;

        
public String Text
        {
            
get { return text; }
            
set { text = value; }
        }

        
public override void CalculateSize(float maxWidth, Font font, Graphics g)
        {
            strFmt.Alignment 
= StringAlignment.Center;
            strFmt.LineAlignment 
= StringAlignment.Center;

            rect_.Size 
= g.MeasureString(text, font, (int)maxWidth, strFmt);
            
this.font = font;
        }

        
public override void CalculateSizeRecursive(float maxWidth, Font font, Graphics g)
        {
            CalculateSize(maxWidth, font, g);
            
foreach (LayoutTreeNode node in children_)
            {
                node.CalculateSizeRecursive(maxWidth, font, g);
            }
        }

        
public override void Draw(Graphics g)
        {
            
//外轮廓,内容,连线
            g.DrawRectangle(Pens.Black, Rectangle.Round(Extent));
            g.DrawString(text, font, Brushes.Red, Extent);

            
foreach (LayoutTreeNode childNode in children_)
            {
                
//绘制斜线
                
                
float childX = (childNode.Extent.Left + childNode.Extent.Right) / 2.0F;
                
float childY = childNode.Extent.Top;
                
                
float curX = (Extent.Left + Extent.Right) / 2.0f;
                
float curY = Extent.Bottom;

                g.DrawLine(Pens.Black, 
new PointF(childX, childY), new PointF(curX, curY));
            }
        }
    }

    
class LayoutTree
    {
        
private float vertical_spacer;
        
private float horizontal_spacer;

        
private LayoutTreeNode root;
        
private LayoutTreeLayerInfo lyrInfo = new LayoutTreeLayerInfo();

        
public float VerticalSpacer
        {
            
get { return vertical_spacer; }
            
set { vertical_spacer = value; }
        }

        
public float HorizontalSpacer
        {
            
get { return horizontal_spacer; }
            
set { horizontal_spacer = value; }
        }

        
public LayoutTreeNode Root
        {
            
get { return root; }
            
set { root = value; }
        }

        
public void ResetLayout()
        {
            lyrInfo.Reset();
        }

        
public T CreateNode<T> (LayoutTreeNode parent) where T:LayoutTreeNode, new()
        {
            T retNode 
= new T();
            
            retNode.Owner 
= this;
            retNode.LayerInfo 
= this.lyrInfo;

            
if (parent == null)
            {
                
this.root = retNode;
                retNode.Level 
= 0;
            }
            
else
            {
                parent.Children.Add(retNode);
                retNode.Level 
= parent.Level + 1;
            }
            
return retNode;
        }
    }
}

posted @ 2008-09-13 12:42 空明流转 阅读(889) | 评论 (2)编辑 收藏

2008年7月25日 #

经过一晚上的整理,把 SoftArt Shader Language 的 EBNF 弄出来了。
主要参照的是 ISO C++的EBNF
由于ISO C++并不是一个LALR(1)能够解决的问题,因此不知道这个C++ EBNF的简化版能否在YACC上比较方便的实现。
如果不能实现,我会先考虑修正语法满足需要,而不是手写编译器,我还没那个能耐。

Flex 与 Bison 的 下载地址

//SASL: SoftArt Shader Language

Syntax

Program             ::
= DeclSeq

//////////////////////////////////
//Declaration
//////////////////////////////////
DeclSeq             ::
= Decl | 
                        DeclSeq Decl
                        
Decl                ::
= BlockDecl |
                        FunctioDef

Declarator          ::
= DirectDecl [SemanticSpec] [RegisterSpec]

DirectDecl          ::
= DeclId |
                        DirectDecl '(' ParamDeclClause ')'|
                        DirectDecl '
[' [ConstExp] ']'|
                        '(' Declarator ')'

CvQualifierSeq      ::
= CvQualifier [CvQualifierSeq]

CvQualifier         ::
= 'const' | 'uniform'

SemanticSpec        ::
= ':' Semantic

RegisterSpec        ::
= ':' 'register' '(' Register ')'
                        
BlockDecl           ::
= SimpleDecl

SimpleDecl          ::
= [DeclSpecSeq] [InitDeclList] ';'

AbsDecl             ::
= DirectAbsDecl

DirectAbsDecl       ::
= [DirectAbsDecl] '(' ParamDeclClause ')' |
                        
[DirectAbsDecl] '[' [ConstExp] ']' |
                        '(' AbsDecl ')'
                        

DeclSpecSeq         ::
= [DeclSpecSeq] DeclSpec

InitDeclList        ::
= InitDecl |
                        InitDeclList '
,' InitDecl

InitDecl            ::
=    Declarator [Init]

Init                ::
= '=' InitClause                         |
                        ( ExpList)
                        
InitClause          ::
= AssignmentExp |
                        '{' InitList 
[','] '}' |
                        '{' '}'
InitList            ::
= InitClause |
                        InitList '
,' InitClause
                        
DeclSpec            ::
= TypeSpec
                        
TypeSpec            ::
= SimpleTypeSpec |
                        ClassSpec

SimpleTypeSpec      ::
=    'int' | 'half' | 'float' |
                        'int2' | 'half2' | 'float2' |
                        'int3' | 'half3' | 'float3' |
                        'int4' | 'half4' | 'float4' |
                        'float4x4'

/////////////////////////////
//Function
/////////////////////////////
FunctionDef         ::
= [DeclSpecSeq] Declarator FunctionBody

FunctionBody        ::
= CompoundStatement

/////////////////////////////
//Statements
/////////////////////////////
CompoundStatement   ::
= '{' [StatementSeq] '}'

StatementSeq        ::
= Statement |
                        StatementSeq Statement

Statement           ::
= ExpStatement |
                        CompountStatement |
                        SelectionStatement |
                        IterationStatement |
                        DeclStatement
                        
ExpStatement        ::
= [ Expression ] ';'

SelectionStatement  ::
= 'if' '(' Condition ')' Statement |
                        'if' '(' Condition ')' Statement 'else' Statement

IterationStatement  ::
= 'while' '(' Condition ')' Statement |
                        'do' Statement 'while' '(' Expression ')' '
;'
                        'for' '(' ForInitStatement [Condition] ';' [ Expression ] ')' Statement
        
Condition           ::
= Expression |
                        TypeSpecSeq Declarator '
=' AssignmentExp

ForInitStatement    ::
= ExpStatement |
                        SimpleDecl

DeclStatement       ::
= BlockDecl

/////////////////////////////                        
//Parameter
/////////////////////////////
ParamDeclClause     ::
= [ ParamDeclList ]

ParamDeclList       ::
= ParamDecl |
                        ParamDeclList '
,' ParamDecl

ParamDecl           ::
= DeclSpecSeq Delarator |
                        DeclSpecSeq 
[AbsDecl]


/////////////////////////////
//Class And Struct
/////////////////////////////
ClassSpec           ::
= ClassHead '{' [ MemberSpec ] '}'

ClassHead           ::
= 'struct' [ Identifier ]

MemberSpec    `     ::
= MemberDecl [MemberSpec]

MemberDeclaration   ::
= [DeclSpecSeq] [MemberDeclList]

MemberDeclList      ::
= MemberDecl |
                        MemberDeclList '
,' MemberDeclarator
                        
MemberDeclarator    ::
=    Declarator [ PureSpec ] |
                        Declarator 
[ ConstInit ] |
                        
[ Identifier ] ':' ConstExp



//////////////////////////////////////
//Expressions
//////////////////////////////////////
Expression          ::
= AssignmentExp

ConstExp            ::
= CondExp

AssignmentExp       ::
= CondExp |
                        LogicalOrExp AssignmentOp AssignmentExp
                        
CondExp             ::
= LogicalOrExp |
                        LogicalOrExp '?' Expression ':' AssignmentExp

LogicalOrExp        ::
= LogicalAndExp |
                        LogicalOrExp '||' LogicalAndExp
                        
LogicalAndExp       ::
= InclusiveOrExp |
                        LogicalAndExp '&&' InclusiveOrExp
                        
InclusiveOrExp      ::
= ExclusiveOrExp |
                        InclusiveOrExp '|' ExclusiveOrExp
                        
ExclusiveOrExp      ::
= AndExp |
                        ExclusiveOrExp '^' AndExp

AndExp              ::
= EqualExp |
                        AndExp '&' EqualExp

EqualExp            ::
= RelExp |
                        EqualExp '
==' RelExp |
                        EqualExp '!
=' RelExp

RelExp              ::
= ShiftExp |
                        RelExp '<' ShiftExp |
                        RelExp '>' ShiftExp |
                        RelExp '<
=' ShiftExp |
                        RelExp '>
=' ShiftExp

ShiftExp            ::
= AddExp |
                        ShiftExp '<<' AddExp |
                        ShiftExp '>>' AddExp

AddExp              ::
= MulExp |
                        AddExp '+' MulExp |
                        AddExp '-' MulExp

MulExp              ::
= PmExp |
                        MulExp '*' PmExp |
                        MulExp '/' PmExp |
                        MulExp '%' PmExp
    
PmExp               ::
= CastExp |
                        PmExp '.*' CastExp

CastExp             ::
= UnaryExp |
                        '(' TypeId ')' CastExp

UnaryExp            ::
= PostfixExp |
                        '++' CastExp |
                        '--' CastExp |
                        UnaryOp CastExp
                        
PostfixExp          ::
= PrimaryExp |
                        PostfixExp '
[' Expression ']' |
                        PostfixExp '(' Expression ')' |
                        PostfixExp '(' 
[ ExpList ] ')' |
                        SimpleTypeSpec '(' 
[ ExpList ] ')' |
                        PostfixExp '++' |
                        PostfixExp '--'

PrimaryExp          ::
= Literal |
                        '(' Expression ')' |
                        IdExp

IdExp               ::
= UnqualifiedId

ExpList             ::
= AssigmentExp |
                        ExpList '
,' AssignmentExp
                        
//////////////////////////////
//Identifier
//////////////////////////////
DeclId              ::
= IdExp |
                        TypeName

UnqualifiedId       ::
= Identifier

Identifier          ::
= NonDigit |
                        Identifier NonDigit |
                        Identifier Digit

//////////////////////////////
//Literals
//////////////////////////////
Literal             ::
= IntLiteral |
                        FloatLiteral |
                        BoolLitreral

IntLiteral          ::
= DemicalLiteral

DemicalLiteral      ::
= NonZeroDigit |
                        DemicalLiteral | Digit
    
FloatLiteral        ::
= FracConstant [ExponentPart] |
                        DigitSeq ExponentPart
                        
BoolLiteral         ::
= 'false' |
                        'true'

FracConstant        ::
= [DigitSeq] '.' DigitSeq |
                        DigitSeq '.'
                        
ExponentPart        ::
= 'e' [Sign] DigitSeq |
                        'E' 
[Sign] DigitSeq
                        
DigitSeq            ::
= Digit |
                        DigitSeq Digit
                        
//////////////////////////
//Terminals
//////////////////////////

NonDigit            ::
= AlphaChar |
                        '_'

NonZeroDigit        ::
= '1' |  | '9'

AssignmentOp        ::
= '=' | 
                        '*
='  | '/='  | '%=' |
                        '+
='  | '-='  |
                        '>>
=' | '<<=' |
                        '&
='  | '^='  | '|='
Register
Semantic
Digit
AlphaChar
Keyword


有点儿参差不齐,哈哈。一些Terminator我就没有写了。预处理的部分由于使用Boost.Wave,因此也没有加入到EBNF中。这些都很大程度上简化了EBNF的内容。
然后大概的根据层次归了一下类,看起来要方便一点。
但愿语法树里面没有漏掉的。
等回到自己机器上就开始自下向上的实现这个东西了,争取10月份之前能把整个Shader编译器集成到SoftArt里面去。
目前就让它在SVN的SandBox里面待着好了。
posted @ 2008-07-25 02:25 空明流转 阅读(1262) | 评论 (2)编辑 收藏

最近在做Shader的编译器。

想好了我的编译器就叫SASL,SoftArt Shader Language。
因为之前没写过EBNF,没什么经验,因此找了C和C++的EBNF在参考。
特别是C的EBNF。
因为可以用LALR(1)实现,因此对我这样用LEX + YACC的人而言就更加有用一点。
整体而言准备尽可能和SM4.0一致,用Boost.Wave支持Preprocessing。
这样的话差不多就全了。这两天先把Shader的EBNF弄出来,完了开始从小往大写慢慢写语法分析器和编译器。

http://www.externsoft.ch/download/cpp-iso.html

这里是C++的EBNF。有点太复杂了觉得。。。



posted @ 2008-07-25 00:11 空明流转 阅读(188) | 评论 (2)编辑 收藏

2008年7月14日 #

上次用boost.python的时候boost还是1.33的时候。

那个时候刚刚开始看shader的东西,就用boost.python做了用python做shader语言的演示。
其实当时看boost.python完全是半懂不懂的。
这段时间找了个C的数值库,要Python的接口,Python For C的Interface又懒得使用,还是用boost.python把一些我要的功能给封装出来好了。
结果一看才发现对Boost.Python的理解好了不好。

看来人都是在慢慢进步的。。。哈哈。

posted @ 2008-07-14 19:05 空明流转 阅读(194) | 评论 (0)编辑 收藏

2008年6月7日 #


以前看D3D的时候,就发现骨骼动画是个有点难以掌握的东西。
但是也可以说,骨骼动画是3D齐次空间变换的集大成者,掌握了骨骼动画,差不多3D空间变换你也就掌握了。
其他所有的层级变换,基本上都不会脱离骨骼动画需要你了解的东西。

网上骨骼动画的demo多如牛毛,我空间想象能力不行,看过无数资料都不大明白骨骼怎么转,皮肤怎么蒙。况且那些基于DX、基于GL的代码都长的不行,难看的明白。

前两天vczh搞了个C#的弱智版的2D物理Engine,我今天就搞个C#和GDIPlus的低能版骨骼变换。虽然是2D的,但是原理和实现基本和3D的完全一样。希望这已经简单到不能再简单的代码能帮助大家搞明白骨骼动画是咋回事。

代码框架上都有注释了,矩阵使用的是Sharp3D的数学库,已经在包中了。不过也就用了矩阵乘法和矩阵-矢量乘法,还有一些矢量加减法。

源代码在此下载


2楼的回帖给了一个地址,是关于骨骼运动变换的数学推理和理论解释,还讨论了左右手系的问题。理论上有问题的亲们可以参照此篇文章

截图:

骨骼的初始状态


变换后的骨骼


加了一圈子顶点,这个虽然是2D的,但也是货真价实的蒙皮哈。

posted @ 2008-06-07 19:35 空明流转 阅读(1861) | 评论 (7)编辑 收藏

2008年5月21日 #

 

 1 for(int i=0; i<numBS; i++)
 2 {
 3   uint offset = bsPitch * bsOffsets.Load(i);
 4   float weight = bsWeights.Load(i);
 5   dp = bsVertices.Load(offset + 3*vertexID+0);
 6   dn = bsVertices.Load(offset + 3*vertexID+1);
 7   dt = bsVertices.Load(offset + 3*vertexID+2);
 8 
 9   pos += dp * weight;
10   normal += dn * weight;
11   tangent += dt * weight;
12 }
13 



Blend Shapes 放在一个固定的数组bsVertices中,
按照

S0V0, S0V1 ... S0VN, S1V0 ... SMVN
的形式存放.

numBS说明了有多少个BS被混合,也就是slots的大小;
bsPitch为SxV0 - SxVN的长