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月25日星期三
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效果。
查看了下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如何才能上传文件。
把手头的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
订阅:
博文 (Atom)