2009年5月4日星期一

compiler & program

compiler建立起来的syntax tree,一切都很完美。让大脑短路一下,设想所有程序都这么简单
component = { {component}, {component}...{resource} | component }
resource = { resource, ... | component } 这样构成了一个DAG tree,每个component有自己的child node...resource唯一属于某个component,这世界就完美了,然后呢...
你要做的就是恰当的安排好时序--node的顺序.,如果某个component要访问另一个component,通过一系列的string组成的"path",比如"root:child1:xxx",就可以拿到ptr,加入一个网络节点,你可以很容易在程序运行时和program通讯,比如dump当前状态,很容易的得到某个节点的状态...
这能解决一切问题么?处理合理的话,其实能解决很多问题。递归虽然简单,但其实能处理的复杂事物却是超乎想象的,前提是,得把握好分寸。

2009年4月2日星期四

为SGI默哀

负债高达5亿美元的Silicon Graphics公司,被Rackable Systems以2500万美元收购,后者将负担部分Silicon Graphics的债务..SGI公司历程:

1982年
斯坦福大学Jim Clark教授离开大学开发三维计算机图形技术,创办了Silicon Graphics

1984年
推出第一台高端三维工作站计算机

1986年
首次公开募股1720万美元

1992年
2280万美元购买芯片制造商MIPS Computer Systems

1995年
收购图形软件公司Alias Research and Wavefront Technologies,花费5亿

1996年
7.4亿收购超级计算机公司Cray Research

1997年
总收入达到36.6亿

1998年
Rick Belluzzo离开惠普成为SGI首席执行官,在此期间公司售出了MIPS Computer Systems

1999年
Rick Belluzzo突然辞职,加入微软

2000年
售出Cray Research,售出价格2200万美元

2003年
公司迁出Mountain View的总部,建筑物租给了Google

2004年
售出Alias Systems,售价5800万美元

2005年7月
公司被纽约证券交易所除名

2006年5月
申请破产保护

2008年8月28日
2008财年的收入降为前一年的24%

2008年12月2日
纳斯达克警告,因为该公司的财务问题,Silicon Graphics有可能会被除名。.

2009年3月25日星期三

Steve Perlman

Steve Perlman, the founder of onlive & mova.
I guess onlive will be the hotest topic in gdc09. http://www.onlive.com/
Mova is also an interesting tech...http://www.mova.com/

2009年3月22日星期日

2009年3月20日星期五

c++ ini parser class

最早ini用win32 api,后来用qt的setting类,或者用ogre的时候cfg读取也很方便,现在重新回到最原始的sdk层次,感觉有必要写一个自己的ini类了。

查看了下ogre的实现,麻烦的很,搞了很多不必要的麻烦工作,不可理解;qt的就更不想看了,移植起来估计会很累。google了一把,找来找去,都不满意,我理想中的ini类,应该就是个.h文件,简洁明了,支持读取section/key/value,load/save就可以了。在codeproject找到了一个CInixxxx的class,初看好像挺简介,然后改了改,最后发现基本不能用,还是重写一个更快些。贴出来,顺便看看转换后的code效果。

1 #ifndef __sglib_inifile_h
2 #define __sglib_inifile_h

3
4 #include <map>
5 #include <string>
6 #include <iostream>

7 #include <fstream>
8 #include <algorithm>
9 #include <functional>

10 #include <sstream>
11
12 namespace sglib {

13
14 template<typename rtT>
15 rtT string_toT (const std::string & value , rtT def = 0){

16 rtT ret;
17 std::istringstream is(value);

18 is >> (rtT)ret ;
19 if( is.fail())

20 return def;
21 return ret;
22 };

23
24 class ini_file {
25 inline void string_trim(std::string& str, const std::string & chrs_trim = " \t\n\r", int trim_dir = 0){

26 size_t start_index = str.find_first_not_of(chrs_trim);

27 if (start_index == std::string::npos){

28 str.erase();
29 return;
30 }

31 if (trim_dir < 2)
32 str = str.substr(start_index, str.size()-start_index);

33 if (trim_dir!=1)
34 str = str.substr(0, str.find_last_not_of(chrs_trim) + 1);

35 }
36 inline void string_remove_comment(std::string & s){

37 std::basic_string <char>::size_type idx;
38 idx = s.find('#');

39 if( idx!= std::string::npos)

40 s.erase(idx);
41 idx = s.find(';');

42 if( idx!= std::string::npos)

43 s.erase(idx);
44 }
45 inline void string_simplify (std::string & str){

46 string_remove_comment(str);
47 string_trim(str);

48 }
49 //inline void trim_right(std::string& str, const std::string & chrs_trim = " \t\n\r")

50 //{
51 // trim(str, chrs_trim, 2);
52 //}
53

54 //inline void trim_left(std::string& str, const std::string & chrs_trim = " \t\n\r")
55 //{

56 // trim(str, chrs_trim, 1);
57 //}
58 inline void string_lower(std::string& str)

59 {
60 std::transform (str.begin(), str.end(), str.begin(), tolower);

61 }
62 inline void string_upper(std::string& str)

63 {
64 std::transform (str.begin(), str.end(), str.begin(), toupper);

65 }
66
67 protected:
68 std::string _file_name;

69 std::string _cur_section;
70 std::map<std::string, std::string> _content;

71 std::map<std::string, std::string> _root;

72
73 void add_record(const std::string & key, const std::string & value){

74 if(_cur_section == "")
75 _root[key] = value;

76 else{
77 std::string map_key = _cur_section + ":" + key;

78 _content[map_key] = value;
79 }

80 }
81 std::string _get_root_value (const std::string & key, std::string default_value){

82 std::map<std::string, std::string>::iterator f;

83 f = _root.find(key);
84 if(f == _root.end())

85 return default_value;
86 return f->second;

87 }
88
89 std::string _get_value (const std::string & section_key, std::string default_value){

90 std::map<std::string, std::string>::iterator f;

91 f = _content.find(section_key);
92 if(f == _content.end())

93 return default_value;
94 return f->second;

95 }
96
97 public:
98 ini_file(void)

99 : _file_name(""){
100 }
101 ini_file(std::string file_name)

102 : _file_name(file_name){
103 }
104 virtual ~ini_file(void){

105 }
106
107 public:
108 std::string get_value (const std::string & section_key){

109 if(section_key.find(':') != std::string::npos)

110 return _get_value(section_key, "");
111 return _get_root_value(section_key, "");

112 }
113
114 std::string get_value (const std::string & section, const std::string & key){

115 if(section == "")
116 return _get_root_value(key, "");

117 std::string map_key = section + ":" + key;

118 return _get_value(map_key, "");
119 }
120

121 std::string get_value (const std::string & section, const std::string & key, const std::string & default_value){

122 if(section == "")
123 return _get_root_value(key, default_value);

124 std::string map_key = section + ":" + key;

125 return _get_value(map_key, default_value);
126 }
127

128 int get_int (const std::string & section_key, int def = 0){

129 std::string value = get_value (section_key);

130 return string_toT<int>(value, def);
131 }

132 int get_int (const std::string & section, const std::string & key, int def = 0){

133 std::string value = get_value (section, key);

134 return string_toT<int>(value, def);
135 }

136 float get_float (const std::string & section_key, float def = 0){

137 std::string value = get_value (section_key);

138 return string_toT<float>(value, def);
139 }

140 float get_float (const std::string & section, const std::string & key, float def = 0){

141 std::string value = get_value (section, key);

142 return string_toT<float>(value, def);
143 }

144 bool get_bool (std::string section_key, bool def = false){

145 std::string value = get_value (section_key);

146 string_lower(value);
147 if(value == "true")

148 return true;
149 if(value == "false")

150 return false;
151 return def;
152 }

153 bool get_bool (const std::string & section, const std::string & key, bool def = false){

154 std::string value = get_value (section, key);

155 string_lower(value);
156 if(value == "true")

157 return true;
158 if(value == "false")

159 return false;
160 return def;
161 }

162
163 // set
164 void set_value(std::string key, std::string value){

165 _root[key] = value;
166 }
167 void set_value(std::string section, std::string key, std::string value){

168 if(section == "")
169 _root[key] = value;

170 else {
171 std::string map_key = section + ":" + key;

172 _content[map_key] = value;
173 }
174 }

175
176 public:
177 bool load (){

178 return load(_file_name);
179 }
180 bool save (){

181 return save(_file_name);
182 }
183
184 bool load (std::string file_name){

185 std::string s;
186 std::string key;

187 std::string value;
188 std::string cur_section;

189 std::basic_string <char>::size_type idx;
190

191 _file_name = file_name;
192 std::ifstream file(file_name.c_str());

193 if (!file.is_open())
194 return false;

195
196 _root.clear();
197 _content.clear();

198 _cur_section = "";
199
200 while(!std::getline(file, s).eof()) {

201 string_simplify(s);
202 if(s.empty())

203 continue;
204 if(s[0] == '[') {

205 idx = s.find(']');
206 if( idx != std::string::npos){

207 _cur_section = s.substr(1, idx-1);

208 string_simplify(_cur_section);
209 }
210 continue;

211 }
212 idx = s.find('=');

213 if(idx != std::string::npos){

214 key = s.substr (0, idx);

215 string_simplify(key);
216
217 value = s.substr (idx+1);

218 string_simplify(value);
219
220 add_record(key, value);

221 }
222 }
223 file.close();

224 return true;
225 }
226
227 bool save(const std::string & file_name) {

228 std::ofstream of(file_name.c_str());

229 if (!of.is_open())
230 return false;

231 std::for_each(_root.begin(), _root.end(), save_item(of));

232 std::for_each(_content.begin(), _content.end(), save_item(of));

233 of.close();
234 return true;
235 };

236 private:
237 struct save_item {
238 std::ofstream & _of;

239 std::string _section;
240 save_item(std::ofstream &of): _of(of), _section(""){}

241
242 void operator () (const std::pair<std::string, std::string> & a) {

243 std::string key = a.first;
244 std::string sec = a.first;

245 std::basic_string <char>::size_type idx = sec.find(':');

246
247 if( idx != std::string::npos){

248 key.erase(0, idx+1);
249 sec.erase(idx);

250 if(_section != sec ){
251 _section = sec;

252 if(_section != "")
253 _of << std::endl << "[" << _section << "]" << std::endl;

254 }
255 }
256 _of << key << " = " << a.second << std::endl;

257 }
258 };
259 };
260
261 } // sglib

262 #endif

2009年2月15日星期日

OpenGL Evaluators

OpenGL的求值器很好用,对于显示和编辑曲面非常有用,不过遗憾的是它仅仅能够帮助显示曲面,而无法回传给用户真正的多边形数据,这也难怪,最初ogl在SGI的图形工作站上,Evaluators是以硬件加速实现的。
把手头的opengl driver代码打开,看来看去,还是mesa的好些,整理一下贴出来,顺便测试一下如何贴代码, 颜色显示的还不正常,需要上传一个css文件,不知道blogspot如何才能上传文件。

namespace sglib{
namespace gfx{

class bezier{
public:
/*
* Horner scheme for Bezier curves
*
* Bezier curves can be computed via a Horner scheme.
* Horner is numerically less stable than the de Casteljau
* algorithm, but it is faster. For curves of degree n
* the complexity of Horner is O(n) and de Casteljau is O(n^2).
* Since stability is not important for displaying curve
* points I decided to use the Horner scheme.
*
* A cubic Bezier curve with control points b0, b1, b2, b3 can be
* written as
*
* (([3] [3] ) [3] ) [3]
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
*
* [n]
* where s=1-t and the binomial coefficients [i]. These can
* be computed iteratively using the identity:
*
* [n] [n ] [n]
* [i] = (n-i+1)/i * [i-1] and [0] = 1
*/
static void curve(
const float * cp
, float * out
, float t
, int dim
, int order ) {

#define MAX_EVAL_ORDER 30
static float inv_tab[MAX_EVAL_ORDER];
static bool inited = false;
if(!inited){
// KW: precompute 1/x for useful x.
for (int i = 1; i < MAX_EVAL_ORDER; i++)
inv_tab[i] = 1.0F / i;
inited = true;
}
float s, powert, bincoeff;
unsigned int i, k;

if(t == 0){
for (k = 0; k < dim; k++)
out[k] = cp[k];
}
else if( t == 1.0){
for (k = 0; k<dim; k++)
out[k] = cp[dim*(order-1)+k];
}
else {
if (order >= 2) {
bincoeff = (float) (order - 1);
s = 1.0F - t;

for (k = 0; k < dim; k++)
out[k] = s * cp[k] + bincoeff * t * cp[dim + k];

for (i = 2, cp += 2 * dim, powert = t * t; i < order; i++, powert *= t, cp += dim) {
bincoeff *= (float) (order - i);
bincoeff *= inv_tab[i];
for (k = 0; k < dim; k++)
out[k] = s * out[k] + bincoeff * powert * cp[k];
}
}
else { /* order=1 -> constant curve */
for (k = 0; k < dim; k++)
out[k] = cp[k];
}
}
}
private:
void cleanup(){
if(_ver)
delete []_ver;
_ver = 0;
}
bool gen_vertex(int usize, int vsize){
cleanup();

int total = _dim * usize * vsize;

float * vcp = new float [_dim*_vorder];
_ver = new float[total];
if(!_cp || !_ver || !vcp)
return false;

float ustep = 1.0f/(usize-1);
float vstep = 1.0f/(vsize-1);
float fu, fv;
int u, v;
for(u=0, fu=0 ; u<usize; u++, fu += ustep){
//1. calc control point first
for(v=0; v<_vorder; v++){
curve (&_cp[_dim*v*_uorder], &vcp[v*_dim], fu, _dim, _uorder);
}
float * ver = _ver + _dim*u;
//2. calc vertex along v dir
for(v=0, fv=0; v<vsize; v++, fv += vstep){
curve (vcp, ver, fv, _dim, _vorder);
ver += usize*_dim;
}
}
delete []vcp;
return true;
}
public:
bezier(): _cp(0) , _ver(0) {
}
~bezier(){
cleanup();
}
void init(const float * cp, int dim, int uorder, int vorder){
_cp = cp, _dim = dim, _uorder = uorder, _vorder = vorder;
}

bool gen(int usize, int vsize){
bool b = true;
b &= gen_vertex(usize, vsize);
return b;
}

float * get_vertex() {
return _ver;
}
protected:
const float * _cp; // control points
int _uorder;
int _vorder;
int _dim;
float * _ver;
};


}} //gfx, sglib