Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / OpenCLClothDemo / cloth.h
1 /*\r
2 Bullet Continuous Collision Detection and Physics Library\r
3 Copyright (c) 2008 Advanced Micro Devices\r
4 \r
5 This software is provided 'as-is', without any express or implied warranty.\r
6 In no event will the authors be held liable for any damages arising from the use of this software.\r
7 Permission is granted to anyone to use this software for any purpose, \r
8 including commercial applications, and to alter it and redistribute it freely, \r
9 subject to the following restrictions:\r
10 \r
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\r
13 3. This notice may not be removed or altered from any source distribution.\r
14 */\r
15 \r
16 \r
17 #include "gl_win.h" //for OpenGL stuff\r
18 \r
19 #include "stb_image.h"\r
20 \r
21 #include <string>\r
22 #include <cstring>\r
23 #include "LinearMath/btScalar.h"\r
24 #include <stdio.h>\r
25 \r
26 \r
27 struct vertex_struct \r
28 {\r
29         float pos[3];\r
30         float normal[3];\r
31         float texcoord[2];\r
32 \r
33 };\r
34 \r
35 class btVertexBufferDescriptor;\r
36 \r
37 class piece_of_cloth \r
38 {\r
39         public:\r
40 \r
41         void destroy(void)\r
42         {\r
43                 if(created)\r
44                 {\r
45                         if(cpu_buffer) delete [] cpu_buffer;\r
46                 }\r
47         }\r
48 \r
49         piece_of_cloth()\r
50         {\r
51                 created = false;\r
52                 cpu_buffer = NULL;\r
53                 m_vertexBufferDescriptor = NULL;\r
54 #ifdef USE_GPU_COPY\r
55                 clothVBO = 0;\r
56 #endif\r
57         }\r
58 \r
59         bool created;\r
60 \r
61         vertex_struct* cpu_buffer;\r
62         unsigned int* indices;\r
63         btVertexBufferDescriptor *m_vertexBufferDescriptor;\r
64 \r
65         double x_offset, y_offset, z_offset;\r
66 \r
67         int width;\r
68         int height;\r
69 \r
70         GLuint m_texture;\r
71 #ifdef USE_GPU_COPY\r
72         \r
73         GLuint clothVBO;\r
74 \r
75         GLuint getVBO()\r
76         {\r
77                 return clothVBO;\r
78         }\r
79 #endif //USE_GPU_COPY\r
80 \r
81         void draw(void)\r
82         {\r
83                 glEnable(GL_TEXTURE_2D);\r
84                 glBindTexture (GL_TEXTURE_2D, m_texture);\r
85 \r
86                 glEnable(GL_DEPTH_TEST);\r
87 \r
88                 glColor3f(1.0f, 1.0f, 1.0f);\r
89 #ifdef USE_GPU_COPY\r
90                 int error = 0;\r
91                 glBindBuffer(GL_ARRAY_BUFFER, clothVBO);\r
92 #ifndef USE_GPU_COPY\r
93                 // Upload data to VBO\r
94                 // Needed while we're not doing interop\r
95                 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_struct)*width*height, &(cpu_buffer[0]), GL_DYNAMIC_DRAW);\r
96 #endif\r
97 #endif\r
98                 glEnableClientState(GL_VERTEX_ARRAY);\r
99 #ifdef USE_GPU_COPY\r
100                 glEnableClientState(GL_NORMAL_ARRAY);\r
101 #endif\r
102                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);\r
103 \r
104                 glBindTexture(GL_TEXTURE_2D, m_texture);\r
105 #ifdef USE_GPU_COPY\r
106                 error = glGetError();\r
107 \r
108                 // VBO version\r
109                 glVertexPointer( 3, GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)0 );\r
110                 error = glGetError();\r
111                 glNormalPointer( GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)(sizeof(float)*3) );\r
112                 error = glGetError();\r
113                 glTexCoordPointer( 2, GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)(sizeof(float)*6) );\r
114                 error = glGetError();\r
115         \r
116 \r
117 #else\r
118                 glVertexPointer( 3, GL_FLOAT, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].pos[0])) );\r
119                 //glNormalPointer( 3, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].normal[0])) );\r
120                 glTexCoordPointer( 2, GL_FLOAT, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].texcoord[0])) );\r
121 #endif\r
122 \r
123                 glDrawElements(GL_TRIANGLES, (height-1  )*(width-1)*3*2, GL_UNSIGNED_INT, indices);\r
124 //              glDisableClientState(GL_NORMAL_ARRAY);\r
125                 glDisableClientState(GL_VERTEX_ARRAY);\r
126                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);\r
127                 glBindTexture(GL_TEXTURE_2D, 0);\r
128 #ifdef  USE_GPU_COPY\r
129                 error = glGetError();\r
130                 glBindBuffer(GL_ARRAY_BUFFER, 0);\r
131                 error = glGetError();\r
132 #endif\r
133 \r
134         }\r
135 \r
136         void create_texture(std::string filename)\r
137         {\r
138                 int width,height,n;\r
139                 unsigned char *data = stbi_load(filename.c_str(), &width, &height, &n, 0);\r
140                 if (!data)\r
141                 {\r
142                         //premake project happens to be 2 levels above the root of Bullet, so try this instead:\r
143                         std::string newname = "../../"+filename;\r
144                         data = stbi_load(newname.c_str(), &width, &height, &n, 0);\r
145                 }\r
146                 \r
147                 GLubyte*        image=new GLubyte[512*256*4];\r
148                 for(int y=0;y<256;++y)\r
149                 {\r
150                         const int       t=y>>4;\r
151                         GLubyte*        pi=image+y*512*4;\r
152                         for(int x=0;x<512;++x)\r
153                         {\r
154                                 const int               s=x>>5;\r
155                                 const GLubyte   b=180;                                  \r
156                                 GLubyte                 c=b+((s+t&1)&1)*(255-b);\r
157                                 pi[0]=pi[1]=pi[2]=c;pi[3]=1;pi+=4;\r
158                         }\r
159                 }\r
160 \r
161                 if ( data ) \r
162                 {\r
163                         \r
164                         for (int i=0;i<width;i++)\r
165                         {\r
166                                 for (int j=0;j<height;j++)\r
167                                 {\r
168                                         int offsetx = (512-width)/2;\r
169                                         int offsety = (256-height)/2;\r
170 \r
171                                         GLubyte*        pi=image+((j+offsety)*512+i+offsetx)*4;\r
172                                         const GLubyte*  src=data+(j*width+i)*4;\r
173                                         pi[0] = src[0];\r
174                                         pi[1] = src[1];\r
175                                         pi[2] = src[2];\r
176                                         pi[3] = 1;\r
177                                 }\r
178                         }\r
179 \r
180                         \r
181                 }\r
182                 else \r
183                 {\r
184                         printf("ERROR: could not load bitmap, using placeholder\n");\r
185                 }\r
186 \r
187                 glGenTextures(1,(GLuint*)&m_texture);\r
188                 glBindTexture(GL_TEXTURE_2D,m_texture);\r
189                 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);\r
190                 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);\r
191                 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);\r
192                 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);\r
193                 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);\r
194                 gluBuild2DMipmaps(GL_TEXTURE_2D,4,512,256,GL_RGBA,GL_UNSIGNED_BYTE,image);\r
195                 delete[] image;\r
196         }\r
197 \r
198         void create_buffers(int width_, int height_)\r
199         {           \r
200                 width = width_;\r
201                 height = height_;\r
202                 \r
203                 created = true;\r
204 \r
205                 cpu_buffer = new vertex_struct[width*height];\r
206                 memset(cpu_buffer, 0, width*height*sizeof(vertex_struct));\r
207 \r
208 \r
209                 // Initial test data for rendering\r
210                 for(int y = 0; y < height; y++)\r
211                 {\r
212                         for(int x = 0; x < width; x++)\r
213                         {\r
214                                 double coord = btSin(x/5.0)*0.01;\r
215                                 //coord = sin(y/);\r
216 \r
217                                 cpu_buffer[y*width+x].pos[0]      = (x/((float)(width-1)))*1;\r
218                                 cpu_buffer[y*width+x].pos[1]      = coord;\r
219                                 cpu_buffer[y*width+x].pos[2]      = (y/((float)(height-1)))*1; \r
220                                 cpu_buffer[y*width+x].normal[0]   = 1;\r
221                                 cpu_buffer[y*width+x].normal[1]   = 0;\r
222                                 cpu_buffer[y*width+x].normal[2]   = 0;\r
223                                 cpu_buffer[y*width+x].texcoord[0] = 1*x/((float)(width-1));\r
224                                 cpu_buffer[y*width+x].texcoord[1] = (1.f-4*y/((float)(height-1)));\r
225                         }\r
226                 }\r
227 \r
228 \r
229                 // Generate and fill index array for rendering\r
230                 indices = new unsigned int[width*3*2+2 + height*width*3*2];\r
231 \r
232                 for(int y = 0; y < height-1; y++)\r
233                 {\r
234                         for(int x = 0; x < width-1; x++)\r
235                         {\r
236                                 // *3 indices/triangle, *2 triangles/quad\r
237                                 int baseIndex = (x + y*(width-1))*3*2;\r
238                                 indices[baseIndex] = x + y*width;\r
239                                 indices[baseIndex+1] = x+1 + y*width;\r
240                                 indices[baseIndex+2] = x+width + y*width;\r
241 \r
242 \r
243                                 indices[baseIndex+3] = x + 1 +  y*width;\r
244                                 indices[baseIndex+4] = x+(width+1) + y*width;\r
245                                 indices[baseIndex+5] = x+width + y*width;\r
246                         }\r
247                 }\r
248 #ifdef USE_GPU_COPY\r
249                 // Construct VBO\r
250                 glGenBuffers(1, &clothVBO);\r
251                 glBindBuffer(GL_ARRAY_BUFFER, clothVBO);\r
252                 // Do initial upload to ensure that the buffer exists on the device\r
253                 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_struct)*width*height, &(cpu_buffer[0]), GL_DYNAMIC_DRAW);\r
254                 int error = glGetError();\r
255                 glBindBuffer(GL_ARRAY_BUFFER, 0);\r
256 #endif\r
257         }\r
258 };\r