Slide vertex on surface

过年上班没多几天啊, hackathon就开始了, 我报名的project是尝试实现以下paper:
Sliding Deformation: Shape Preserving Per-Vertex Displacement, Dmitriy Pinskiy, EUROGRAPHICS 2010.
本文做一些记录, 特别是有些问题以后可能也会遇到.

想做这个slide brush的原因是: 1. 上面那个paper本身适合放到brush framework里面来做, 做成一个brush; 2. 看上去不是太难, 是有难点(后面会提到), 但是=不是那种求解方程组的优化问题(我还不太懂这个), 估计可以在2天内搞定的, yes, hackathon就2天.

大体做成的效果应该是: brush stroke的时候会带动一些vertices在mesh/surface上滑动, mesh的形状shape被保持。区别于现在mudbox已有的grab brush, 后者顶点跟着鼠标在走,会跑到mesh外面. 区域

算法的输入包括(不限于)下面这些:
+ handle, which is the mouse/brush ...

more ...

优化-访问数组值

记录一下学到的一个技术.
alt text
假如value[]是一个很长的数组, 记录着某些对象的值, 值的范围是[0, 1]. 它的操作包括:
给value[]初始化为每个元素都是0;
设置某一个元素的值, 如value[vIndex] = x;
访问某一个元素的值, 如x = value[vIndex];

虽然数组很长, 很多时候一次使用到的就是其中的某一小部分的值, 例如10k大小, 某次使用到的可能就是10-1k这么小的局部.

for (int i = 0; i < 10000; ++i)
{
    // change the value of 100 elements to [0, 1];    
}    

for (int i = 0; i < 10000; ++i)
{
    if (value[i] > 0)     
        do ...
more ...

Corrective Blendshape at Maya

记录一下最近学到的corrective blendshape知识.

问题描述

First, a basic scene is built, pCylinder1 is rigged and skinned,
basic scene for test

Now, suppose we are not satisfied with the elbow shape, want it change it a little bit. 例如一个手臂的骨骼动画已经搞好了, 后面发现在形状上还想改进一下, 那怎么办呢?

If we select vertices and move them (adding vector delta to these vertics) on the skinned ...

more ...

GPP - Double Buffer

首先多谢作者的慷慨generous!
http://gameprogrammingpatterns.com/double-buffer.html

Double buffer 出发点intent是使得一系列连续的操作像是同时立刻完成的。 为什么这么说呢?
作者的例子是读写屏幕的, 我画图说明:
Alt text
问题是那个内存块还没有写完, 屏幕过来读的太快了, 我甚至猜想: 屏幕过来好几个笔头分任务读, 每个读一小块区域, 那速度就更快了, 快的结果是读到还没有来得及写的区域, 那可能那块区域里面就是一些不是这一帧原本想要呈现的信息(可能是之前的帧的遗留信息). 描述这样的现象专门有一个名词"tearing", or "image tearing".

解决方案,就是引入两个buffer, 你笔头2只能从我写完的那个bufferA里面读, 而另一个bufferB我笔头1在写, 没有写完之前不给笔头2来读. 等我笔头1写完了这个bufferB, 就做一个swap告诉笔头2可以来读这个bufferB了. 笔头2来读bufferB的时候, 我笔头1又过去写bufferA了, 依然没写完之前不给笔头2来读.....

[update 2014-12-18]在看以下新闻时候遇到了"image tearing"这个词. "A 4K monitor is great in theory, but ...

more ...

LeetCodeOJ - Find Minimum in Rotated Sorted Array

题目:

Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
Find the minimum element.
You may assume no duplicate exists in the array

基本上看到sorted, find, ... 这关键字就想到binary search二分查找.
根据输入 ...

more ...

Reading List

C++ Concurrency in Action: Practical Multithreading Paperback – February 28, 2012
by Anthony Williams (Author)

Multithreading for Visual Effects Hardcover – July 29, 2014

Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 Paperback – December 5, 2014
by Scott Meyers (Author)

Game Engine Architecture, Second ...

more ...

LeetCodeOJ - Min Stack

Leetcode 上的题目, 实现一个Min Stack.
+ 带stack的一般功能, push, pop, top;
+ int getMin()能在constant time 返回最小值.

很明显, 带stack一般功能的容易实现, 用std::vector也行,or直接用std::stack<>这个container adapter更直接( 所谓adapter, 就是这个类型里面的实现会用到某些简单的container, 如vector, list).
但是那个getMin()呢?
假如只是取一个最小值, 那就简单了, 每次push时候都比较记录当前最小值就ok了. 但是假如不断地pop, 不断地getMin, 那stack内容改动了就需要不停地更新最小值.

一开始我想到保存一个最小值, 并可能需要O(n)的时间来更新这个最小值. 下面的方法是保存所有当前的最小值. 你只要取走了最小的, 然后下一个最小的立马出现了.
Alt text
两个container, 其中一个是std::stack 用于实现一般的stack功能; 另一个可以是std::vector/list/stack ...

more ...

Algo - Tower of Hanoi

在书[Anany Levitin, 算法设计与分析基础]的第二章又看到汉诺塔的问题:
有三个柱子A B C; A柱上有好几个盘子, 小的放在大的上面;
现在问怎么把A柱上的盘子移到C柱上, B是做辅助的, 条件是大的盘子不能压到小的盘子上. 所以结果C柱上的盘子也是小的放在大的上面。

A,B,C; 三个柱子

假如A上有1个盘子,直接放到C上就解答完了。

假如A上有2个盘子ab,a盘小的 在 b盘大的上面. 先把a放到B上, b放到C上, 然后把a从B移到C上. 结果就是C柱上有ab。[pattern 1]
注意这种case中先把a放到C上, 那b放到B上, 然后a从C移到到B柱上, 那B柱上就有ab两个盘子了. 这结果很像上面的, 但是B柱跟C柱次序反了. 可见在移动盘子的时候, 柱子的次序, 是很重要的.

假如A上有3个盘子, 去尝试多画几次, 还是能解出来, 但是发现好像没有什么规律啊.
假如A上有4个盘子, 那可能就要尝试好多次才能碰巧一次解答出来. 还没有看出来规律.

要换一种角度来看啊, 上面我们已经解答了A柱上有2个盘子的case了. 那重新看A柱上有3个盘子的case.

A柱上的2个盘子 ...

more ...

Bit field

一般在C++代码里面遇到的基本类型bool, char, short, int, etc, 都是说占多少个字节, 也就是最少也是一个字节. 那有时候会不会1个字节就多余了, 或者说1个字节不单只可以表示true/false, 还可以表示更多的信息呢? 毕竟1个字节=8bits=2^8=256个状态.

Part 1

Bit field 貌似就是想充分利用内存. 下面是我看了参考(Reference那一节列了一些)之后做的实验:

#include <cstdio>          

// 交通繁忙时间            
enum CallTariff { tOffPeak, tMediumRate, tPeakTime } ;           

// 账单           
struct Bill           
{          
    unsigned int    iNameId;    // 客户名           
    CallTariff      eTariff;           
};           

struct BillVIP           
{          
    unsigned int    iNameId;    // 客户名           
    bool            isVIP ...
more ...

Volume Data Visualization

上周五Sq.B突然说起L.F到一个创业公司做Director of Engineer了,
http://www.datifex.com
为L.F高兴的同时, 这家公司很是吸引. 它的team介绍中很多都很牛的背景呢.

big data visualize ...

这年头连zf都在说大数据, 我不熟悉, 但好像他们的出发点都是怎么从大数据中获利, 例如怎么分析得到情报, 而visualization貌似可以帮到他们啊, 这就是需求? 有意思.

To read list:
http://cyrille.rossant.net/ 他写了两本书和很cool的project:
book Learning IPython for Interactive Computing and Data Visualization; 已下载pdf.
book IPython Interactive Computing and Visualization Cookbook;
vispy.org ...

more ...

阅读笔记 GLSL Cookbook - Chapter 1

[OpenGL 4.0 Shading Language Cookbook] - Chapter 1

Profiles: Core vs. Compatibility

OpenGL 3.0版本引入了deprecation model模型. 被标记为deprecated的函数或者功能, 意味着在将来的版本中会被removed去掉. 例如immdediate mode rendering使用的glBegin/glEnd在3.0版本中标记为deprecated而在3.1版本中被去掉.

为了backwoods compatibility后兼容, OpenGL 3.2版本引入了compatibility profiles的概念.
Core profile: 目标是某一个特定的版本, older features removed.
Compatibility profile: 为了后兼容, older features 还在的.

有些地方有full vs. forward compatible context这些概念, 听上去有点令人confusing. 跟上面的core/compatibility概念是有些不一样的 ...

more ...

Algo - Check if a binary tree is mirror or symmetric

问题: 给出一个binary tree二叉树, 判断这个数是否关于根节点对称.

尝试在纸上画画形状, 例如:
Alt text
这就引入一个问题, 问题中的对称是指结构上的对称就足够了, 还是还要加上node里面的值相等呢? case 1: structure symmetric; case 2: structure symmetric + value equal; 因为case 2是在case 1的基础上层进的, 所以并不矛盾, 先考虑case 1好了. 于是对着上面的图来写代码,

bool isSymmetricBinaryTree(Node *root)                    
{                                             
    // node without children                     
    if (root->left == nullptr && root->right == nullptr)        
        return true;                                                    
    //                       
    if (root->left && root->right == nullptr)                  
        return false ...
more ...

Algo - Detecting a Loop in a Singly Linked List

This is not the first time i see this algo problem, and i want to describe the details of how to solve it this time in case need to revisit it later.

首先想象一下一个list带loop/circle的形状.
Alt text
最左边的最general, 但是一个node只有一个next指针, 只能指向一个后续node, 所以只有最后的情况才可能. 或者是这个list没有loop, 或者是这个list本身就是一个loop/closed circle.

假如一个node的定义是:

struct Node {   
    struct Node *next; 
};     

要形成一个loop, 某一个node的next指向已经visit过的node ...

more ...

Difference between Parameter and Variabe and Argument

翻译过来的话, variable 是变量, parameter and argument 是参数的意思, 怎么区别使用呢?

int add(int a, int b)     // (int a, int b)叫argument list, a/b是parameter.  
{                         
    int c = a + b;        // c is variable.   
    return c;           
}          

int x = 1;                // x对应自己的scope下的variables.       
z = add(x, 2);            // x/y作为函数参数时候就是arguments.    

引用一下网上的解释:

A parameter is a variable in a method ...

more ...

Mode Switch in Class Hierarchy

Alt text
想象我们正在搞一个砌砖的程序, 是的, 码农只是其中一种称呼, 时不时也被称为搬砖的.
一开始, 我们只有不断在已有的基础上添加砖头的功能。
后来, 我们需要有移动某些砖块的功能。例如在最外表面的砖块都可以被移动。
再后来,我们需要敲掉某砖块的功能。
它们分别对应于add, move, delete这三种modes.

其中一种设计方法是

class Build 
{
    enum BuildMode {            
        Add,      
        Move,       
        Delete       
    };          
    BuildMode m_currentMode;            
};         

这方法是把所有mode的实现都放在同一个地方, 每次更新都要改这个地方Build的源代码实现. 但是假如在添加move, delete这新mode的时候, 我们不想or不能改已有的只有add mode的Build源码呢?

这是另一种设计方案

class Build  
{   
    // care about the add mode only.    
};   
class BuildMove : public Build 
{ 
    bool onMouseEvent()   
    { 
        check if we will go ...
more ...

Char Array vs Char Pointer

刚才在阅读以下内容时候复习了一下这两个概念. Quick case: Char Pointer vs Char Array in C++, by Bartlomiej Filipek

// Test case of char array vs char pointer. 
// 

#include <iostream>   

int main()     
{       
    char strA[] = "char array!";          
    char *strP = "char array?";        

    std::cout << "sizeof(strA): " << sizeof(strA) << ", of: " << strA << ", addr: " << &strA << std::endl;          
    std::cout << "sizeof(strA): " << sizeof ...
more ...

Pointer is copied when passed as function parameter

起源

看到这段代码(肯定是简化更改版啦)

void XList::merge(Item *item)   
{  
    ... // do the merge sth;   
    item->unref();  
}   
void XList::merge(Item &item)   
{  
    ... // do the merge sth;   
}   

上面的unref()是用于reference count的, reference计数减一的意思. 为什么有这东东呢, 为什么下面用引入作为参数的就不需要呢? 我怀疑是指针在作为函数参数的传递过程中被复制了, 也就是指向实际的物体的指针又多了一个, 所以merge之后就unref减少一个. 以下的test case尝试证明指针是否被复制了:

// try to check if a pointer will be copied during passing-by-pointer.         
//              
#include <iostream>             

void func1(int ...
more ...

Build myblog using pelican

都不知道这是第几次又想建一个自己blog来host那些笔记了, 相比于之前的blogger, wordpress, 这次用pelican and python来搞...

环境:

  • python 2.7, withn pip, easy_install
  • pelican
    Alt text
    注意上面的起始目录是E:\Temp\myblog> 我试过别的起始目录是E:\Temp\myblog\context> 就发生错误了. 进入output目录, 打开index.html就可以看到blog了。这里我没有用到make html命令哦.

遇到的problems:

  • 设置图片目录的路径.
    我的图片都是文档.md目录下的data目录, 例如folderA/xxx.md, folderA/data/yyy.PNG. 在pelican这里, 我想保持这样的结构, folderA 相当于 context目录, 目的是blog的内容(文档和图片)已经可以放到某个folderA里面, 然后要用pelican来build这个blog的时候, 直接把folderA目录里面的所有东西copy到context目录下就ok了.
    但是pelican默认是把图片放到blogFolder/image目录 ...
more ...

build simple ui using pySide

记录一下做UI prototype时候遇到的新概念

life is short, use python.

早有耳闻, 一试果然不凡. 安装Qt 4.8.X, 安装pySide (how? 具体看其主页), 然后新建file.py, 敲几行pySide代码, 然后command line里面python file.py立刻就出ui效果了. 省却了ide / c++代码 / 链接设置 / 反复修改反复编译的麻烦.
事情的缘由是, 最近要参与用python快速做一个ui的prototype, 本来主程序M里面就有Qt+pySide, 所以连安装都不需要, 直接改py文件就得到ui结果, 真快. 于是就缺学几下python了.

example 1. To define the style sheet 样式 of a button.
Alt text

QPushButton {
    border: 2px ...
more ...

Python Basis 基础笔记

新接触python programming, 记录一些基础.

Batteries Included. 立马就可以使用的. Installizaton


download 2.7 from python website and install at C:\Python27;
download Anaconda 2.1.0 install at E:\Anaconda;
Alt text
看来两者并不冲突.

这是从Anaconda里面起来的Spyder IDE:
Alt text

Variables and Data

A variable is a name that points to some specific data type. 不允许声明一个变量而没有=赋值. contents = 6;
print ...

more ...