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 ...
优化-访问数组值
记录一下学到的一个技术.
假如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 ...
Corrective Blendshape at Maya
记录一下最近学到的corrective blendshape知识.
问题描述
First, a basic scene is built, pCylinder1 is rigged and skinned,
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是使得一系列连续的操作像是同时立刻完成的。
为什么这么说呢?
作者的例子是读写屏幕的, 我画图说明:
问题是那个内存块还没有写完, 屏幕过来读的太快了, 我甚至猜想: 屏幕过来好几个笔头分任务读, 每个读一小块区域, 那速度就更快了, 快的结果是读到还没有来得及写的区域, 那可能那块区域里面就是一些不是这一帧原本想要呈现的信息(可能是之前的帧的遗留信息). 描述这样的现象专门有一个名词"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二分查找.
根据输入 ...
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)的时间来更新这个最小值. 下面的方法是保存所有当前的最小值. 你只要取走了最小的, 然后下一个最小的立马出现了.
两个container, 其中一个是std::stack 用于实现一般的stack功能; 另一个可以是std::vector/list/stack ...
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 ...
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 ...
阅读笔记 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二叉树, 判断这个数是否关于根节点对称.
尝试在纸上画画形状, 例如:
这就引入一个问题, 问题中的对称是指结构上的对称就足够了, 还是还要加上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 ...
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的形状.
最左边的最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.
引用一下网上的解释:
more ...A parameter is a variable in a method ...
Mode Switch in Class Hierarchy
想象我们正在搞一个砌砖的程序, 是的, 码农只是其中一种称呼, 时不时也被称为搬砖的.
一开始, 我们只有不断在已有的基础上添加砖头的功能。
后来, 我们需要有移动某些砖块的功能。例如在最外表面的砖块都可以被移动。
再后来,我们需要敲掉某砖块的功能。
它们分别对应于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 ...
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 ...
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 ...
Build myblog using pelican
都不知道这是第几次又想建一个自己blog来host那些笔记了, 相比于之前的blogger, wordpress, 这次用pelican and python来搞...
环境:
- python 2.7, withn pip, easy_install
- pelican
注意上面的起始目录是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目录 ...
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.
QPushButton {
border: 2px ...
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;
看来两者并不冲突.
这是从Anaconda里面起来的Spyder IDE:
Variables and Data
A variable is a name that points to some specific data type. 不允许声明一个变量而没有=赋值.
contents = 6;
print ...