1 
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright by Schrodinger, LLC
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #ifndef _H_CGO
18 #define _H_CGO
19 
20 #include"Base.h"
21 #include"Ray.h"
22 #include"Setting.h"
23 #include"os_gl.h"
24 #include"os_gl_cgo.h"
25 #include"Rep.h"
26 #include"MemoryDebug.h"
27 #include <vector>
28 #include <unordered_map>
29 #include <typeinfo>
30 #include <type_traits>
31 #include <memory>
32 #include "GenericBuffer.h"
33 #include <set>
34 #include <glm/vec3.hpp>
35 #include <glm/vec4.hpp>
36 
37 /* Compiled Graphics Library for simple graphics objects
38    in floating point three-space, with the goal of achieving
39    quick and easy rendering in multiple environments without the
40    headaches of OpenGL arrays.
41 
42 */
43 
44 #define CGO_read_int(p) (*((int*)((p)++)))
45 #define CGO_get_int(p) (*((int*)(p)))
46 #define CGO_get_uint(p) (uint)(*((uint*)(p)))
47 #define CGO_write_int(p,i) ((*((int*)(p++)))=(i))
48 #define CGO_write_uint(p,i) ((*((uint*)(p++)))=(i))
49 #define CGO_put_int(p,i) ((*((int*)(p)))=(i))
50 #define CGO_put_uint(p,i) ((*((uint*)(p)))=(i))
51 
CLIP_COLOR_VALUE(float cv)52 inline uchar CLIP_COLOR_VALUE(float cv){ return ((cv>1.f) ? 255 :  (cv < 0.f) ? 0 : pymol_roundf(cv * 255) ); }
CONVERT_COLOR_VALUE(unsigned char cv)53 inline float CONVERT_COLOR_VALUE(unsigned char cv) { return ((cv>255) ? 1.f :  (cv < 0) ? 0.f : (cv / 255.f) ); }
54 
55 // normal values are mapped between { -1, 1 } to { 0, 255 },
56 // the values are mapped: { -1/128, -.5/192, 0./255, .5/63, 1./127 }
CLIP_NORMAL_VALUE(float cv)57 inline uchar CLIP_NORMAL_VALUE(float cv){ return ((cv>1.f) ? 127 :
58                                                   (cv < -1.f) ? 128 :
59                                                   pymol_roundf(((cv + 1.f)/2.f) * 255) - 128 ); }
60 
61 /* Supported functions:
62  * stop
63  * null
64  * begin
65      GL_POINTS,
66      GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP,
67      GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN
68  * end
69  * vertex
70  * normal
71  * color
72  * sphere   * currently for ray-tracing only
73  * triangle * currently for ray-tracing only
74  * cylinder * currently for ray-tracing only
75  * linewidth
76  * primwidth * ray-tracing
77  */
78 
79 /* instructions and data segment sizes */
80 
81 #define CGO_STOP                 0x00
82 #define CGO_STOP_SZ              0
83 #define CGO_NULL                 0x01
84 #define CGO_NULL_SZ              0
85 #define CGO_BEGIN                0x02
86 #define CGO_BEGIN_SZ             1
87 #define CGO_END                  0x03
88 #define CGO_END_SZ               0
89 #define CGO_VERTEX               0x04
90 #define CGO_VERTEX_SZ            3
91 #define CGO_NORMAL               0x05
92 #define CGO_NORMAL_SZ            3
93 #define CGO_COLOR                0x06
94 #define CGO_COLOR_SZ             3
95 #define CGO_SPHERE               0x07
96 #define CGO_SPHERE_SZ            4
97 #define CGO_TRIANGLE             0x08
98 #define CGO_TRIANGLE_SZ          27
99 #define CGO_CYLINDER             0x09
100 #define CGO_CYLINDER_SZ          13
101 // CGO_LINEWIDTH, CGO_WIDTHSCALE, CGO_DOTWIDTH work only on ray tracing
102 #define CGO_LINEWIDTH            0x0A
103 #define CGO_LINEWIDTH_SZ         1
104 #define CGO_WIDTHSCALE           0x0B
105 #define CGO_WIDTHSCALE_SZ        1
106 
107 #define CGO_ENABLE               0x0C
108 #define CGO_ENABLE_SZ            1
109 #define CGO_DISABLE              0x0D
110 #define CGO_DISABLE_SZ           1
111 #define CGO_SAUSAGE              0x0E
112 #define CGO_SAUSAGE_SZ           13
113 #define CGO_CUSTOM_CYLINDER      0x0F
114 #define CGO_CUSTOM_CYLINDER_SZ   15
115 
116 #define CGO_DOTWIDTH             0x10
117 #define CGO_DOTWIDTH_SZ          1
118 
119 #define CGO_ALPHA_TRIANGLE       0x11
120 #define CGO_ALPHA_TRIANGLE_SZ    35
121 #define CGO_ELLIPSOID            0x12
122 #define CGO_ELLIPSOID_SZ         13
123 #define CGO_FONT                 0x13
124 #define CGO_FONT_SZ              3      /*  size, face, style */
125 #define CGO_FONT_SCALE           0x14
126 #define CGO_FONT_SCALE_SZ        2
127 #define CGO_FONT_VERTEX          0x15
128 #define CGO_FONT_VERTEX_SZ       3      /*  principle axes (zeros -> use camera x y z */
129 
130 // CGO_FONT_AXES not used
131 #define CGO_FONT_AXES            0x16
132 #define CGO_FONT_AXES_SZ         9      /*  principle axes (zeros -> use camera x y z */
133 
134 #define CGO_CHAR                 0x17
135 #define CGO_CHAR_SZ              1
136 #define CGO_INDENT               0x18
137 #define CGO_INDENT_SZ            2
138 #define CGO_ALPHA                0x19
139 #define CGO_ALPHA_SZ             1
140 #define CGO_QUADRIC              0x1A
141 #define CGO_QUADRIC_SZ           14
142 #define CGO_CONE                 0x1B
143 #define CGO_CONE_SZ              16
144 #define CGO_RESET_NORMAL         0x1E
145 #define CGO_RESET_NORMAL_SZ      1
146 #define CGO_PICK_COLOR           0x1F
147 #define CGO_PICK_COLOR_SZ        2
148 
149 
150 /* CGO_DRAW_ARRAYS : operation that calls glDrawArrays with all arrays in memory
151    (i.e., stored in the CGO array). There can be up to 4 arrays (vertex, normal, color,
152    and pick color array, where each are stored using GL_FLOAT array (except for the pick
153    color array, which is GL_UNSIGNED_BYTE, because the 2nd 2/3rds of the array is used to
154    store atom/bond picking information. Also, the color array is stored using 4 floats,
155    since glColorPointer() requires having 4 as an argument for OpenGLES.
156    - mode : GL Mode that is used
157    - arrays : which arrays that are used (bitmask on CGO_<type>_ARRAY, where <type>
158               can be VERTEX, NORMAL, COLOR, or PICK_COLOR)
159    - narrays : number of arrays specified in arrays
160    - nverts : number of total vertices specified in arrays
161    - each GL_FLOAT array specified in order
162 */
163 #define CGO_DRAW_ARRAYS          0x1C
164 /* CGO_DRAW_BUFFERS_INDEXED : operation that uses glDrawArrays with VBOs.  It also
165    has a dynamic length since it holds the picking information (atom/bond) for each vertex,
166    as well as space for picking to use when drawing colors (since colors are dynamically generated
167    for each atom/bond value).
168    - mode : GL Mode that is used
169    - arrays : which arrays that are used (bitmask on CGO_<type>_ARRAY, where <type>
170               can be VERTEX, NORMAL, COLOR, or PICK_COLOR)
171    - narrays : number of arrays specified in arrays
172    - nverts : number of total vertices specified in arrays
173    - bufs[5] : each VBO id in order (if used, VERTEX, NORMAL, COLOR, PICK_COLOR), plus the
174       vertex index array that specifies all vertices.
175  */
176 #define CGO_DRAW_BUFFERS_INDEXED         0x21
177 
178 /* CGO_BOUNDING_BOX : operation that allows the extent to be expanded.  Since the geometry
179    data is not kept in the CGO object for VBO objects (only on the card), this object allows
180    the bounding box of the object to be saved in the CGO.  This is used in the CGOGetExtent(),
181    typically when the view is being automatically set, but can be used for other things.
182  */
183 #define CGO_BOUNDING_BOX         0x22
184 #define CGO_BOUNDING_BOX_SZ      6
185 
186 #define CGO_DRAW_BUFFERS_NOT_INDEXED         0x23
187 
188 #define CGO_SPECIAL            0x24
189 #define CGO_SPECIAL_SZ         1
190 
191 #define CGO_DRAW_CYLINDER_BUFFERS       0x25
192 
193 #define CGO_SHADER_CYLINDER             0x26
194 #define CGO_SHADER_CYLINDER_SZ          8
195 
196 #define CGO_SHADER_CYLINDER_WITH_2ND_COLOR      0x27
197 #define CGO_SHADER_CYLINDER_WITH_2ND_COLOR_SZ    13
198 
199 #define CGO_DRAW_SPHERE_BUFFERS      0x28
200 
201 #define CGO_ACCESSIBILITY      0x29
202 #define CGO_ACCESSIBILITY_SZ    1
203 
204 #define CGO_DRAW_TEXTURE      0x2A
205 #define CGO_DRAW_TEXTURE_SZ    13
206 
207 #define CGO_DRAW_TEXTURES      0x2B
208 
209 #define CGO_DRAW_SCREEN_TEXTURES_AND_POLYGONS      0x2C
210 
211 #define CGO_TEX_COORD                0x2D
212 #define CGO_TEX_COORD_SZ             2
213 
214 
215 #define CGO_DRAW_LABEL      0x2E
216 #define CGO_DRAW_LABEL_SZ    20
217 
218 #define CGO_DRAW_LABELS      0x2F
219 
220 #define CGO_DRAW_CONNECTOR       0x30
221 #define CGO_DRAW_CONNECTOR_SZ    25
222 
223 #define CGO_DRAW_CONNECTORS      0x31
224 
225 #define CGO_DRAW_TRILINES        0x32
226 #define CGO_DRAW_TRILINES_SZ     2
227 
228 #define CGO_UNIFORM3F            0x33
229 #define CGO_UNIFORM3F_SZ         4
230 #define CGO_UNIFORM3F_HEADER     4
231 
232 #define CGO_SPECIAL_WITH_ARG    0x34
233 #define CGO_SPECIAL_WITH_ARG_SZ    2
234 
235 #define CGO_LINE                0x35
236 #define CGO_LINE_SZ                6
237 #define CGO_SPLITLINE           0x36
238 #define CGO_SPLITLINE_SZ           9
239 
240 #define CGO_DRAW_CUSTOM         0x37
241 
242 #define CGO_VERTEX_ATTRIB_3F    0x38
243 #define CGO_VERTEX_ATTRIB_4UB   0x39
244 #define CGO_VERTEX_ATTRIB_1F    0x3A
245 
246 #define CGO_MASK_ATTRIBUTE_IF_PICKING   0x3B
247 #define CGO_BIND_VBO_FOR_PICKING        0x3C
248 
249 #define CGO_VERTEX_BEGIN_LINE_STRIP     0x3D
250 #define CGO_VERTEX_BEGIN_LINE_STRIP_SZ     3
251 
252 #define CGO_INTERPOLATED     0x3E
253 #define CGO_INTERPOLATED_SZ     1
254 
255 #define CGO_VERTEX_CROSS     0x3F
256 #define CGO_VERTEX_CROSS_SZ     3
257 
258 #define CGO_VERTEX_ATTRIB_4UB_IF_PICKING   0x40
259 
260 #define CGO_CUSTOM_CYLINDER_ALPHA      0x41
261 
262 #define CGO_LIGHTING             0x0B50
263 
264 #define CGO_VERTEX_ARRAY         0x01
265 #define CGO_NORMAL_ARRAY         0x02
266 #define CGO_COLOR_ARRAY          0x04
267 #define CGO_PICK_COLOR_ARRAY     0x08
268 #define CGO_ACCESSIBILITY_ARRAY  0x10
269 #define CGO_TEX_COORD_ARRAY      0x20
270 
271 extern int CGO_sz[];
272 size_t CGO_sz_size();
273 
274 // CGOs are floating point arrays so we need to work with sizes in terms of floats
275 template <typename T>
fsizeof()276 static size_t fsizeof() { return sizeof(T) / sizeof(float); }
277 
278 struct ObjectGadgetRamp;
279 
280 class CGO;
281 
282 // These are only the optimized operations
283 namespace cgo {
284   namespace draw {
285     struct begin {
286       static const int op_code = CGO_BEGIN;
287       int mode;
beginbegin288       begin(int mode) : mode(mode) {}
289     };
290 
291     struct enable {
292       static const int op_code = CGO_ENABLE;
293       int mode;
enableenable294       enable(int mode) : mode(mode) {}
295     };
296 
297     struct disable {
298       static const int op_code = CGO_DISABLE;
299       int mode;
disabledisable300       disable(int mode) : mode(mode) {}
301     };
302 
303     struct trilines {
304       static const int op_code = CGO_DRAW_TRILINES;
305       unsigned nverts;
306       unsigned buffer; // GLuint
trilinestrilines307       trilines(unsigned nverts, unsigned buffer) : nverts(nverts), buffer(buffer) {}
308     };
309 
310     struct op_with_data {
311       float * floatdata { nullptr };
set_dataop_with_data312       void set_data(float * data) { floatdata = data; };
get_dataop_with_data313       float * get_data() { return floatdata; };
get_dataop_with_data314       const float * get_data() const { return floatdata; };
315       virtual int get_data_length() const = 0;
~op_with_dataop_with_data316       virtual ~op_with_data() {}
317     };
318 
319     struct op_with_draw_buffers {
320     };
321 
322     struct arrays : op_with_data {
323       static const int op_code = CGO_DRAW_ARRAYS;
arraysarrays324       arrays(int _mode, short _arrays, int _nverts) :
325       mode(_mode), arraybits(_arrays), narrays(0), nverts(_nverts) {
326         short bit;
327         for (bit = 0; bit < 4; bit++){
328           if ((1 << bit) & arraybits){
329             narrays+=3;
330           }
331         }
332         if (arraybits & CGO_ACCESSIBILITY_ARRAY) narrays++;
333         if (arraybits & CGO_COLOR_ARRAY) narrays++;
334       };
335       int mode;
336       int arraybits;
337       int narrays;
338       int nverts;
get_data_lengtharrays339       int get_data_length() const { return narrays * nverts; };
340     };
341 
342     struct buffers_indexed : op_with_data, op_with_draw_buffers {
343       static const int op_code = CGO_DRAW_BUFFERS_INDEXED;
344       buffers_indexed(int _mode, short _arrays, int _nindices,
345                       int _nverts, size_t _vboid, size_t _iboid, int _n_data, size_t _pickvboid = 0) :
modebuffers_indexed346         mode(_mode), arraybits(_arrays), narrays(0), nindices(_nindices),
347         nverts(_nverts), vboid(_vboid), iboid(_iboid)
348         , pickvboid(_pickvboid)
349         , pickcolorsset(0)
350         , n_data(_n_data)
351       {
352         short bit;
353         for (bit = 0; bit < 4; bit++){
354           if ((1 << bit) & arraybits){
355             narrays++;
356           }
357         }
358         if (arraybits & CGO_ACCESSIBILITY_ARRAY) narrays++;
359         if (arraybits & CGO_COLOR_ARRAY) narrays++;
360       }
361       int mode;
362       int arraybits;
363       int narrays;
364       int nindices;
365       int nverts;
366       size_t vboid;
367       size_t iboid;
368       size_t pickvboid;
369       int pickcolorsset;
370       int n_data;
get_data_lengthbuffers_indexed371       int get_data_length() const { return nverts * 3 + n_data; };
372     };
373 
374     struct sphere_buffers : op_with_data, op_with_draw_buffers {
375       static const int op_code = CGO_DRAW_SPHERE_BUFFERS;
sphere_bufferssphere_buffers376       sphere_buffers(int _num_spheres, int _ub_flags,
377                      size_t _vboid, size_t _pickvboid) :
378         num_spheres(_num_spheres), ub_flags(_ub_flags),
379         vboid(_vboid), pickvboid(_pickvboid), pickcolorsset(0) {}
380       int num_spheres;
381       int ub_flags;
382       size_t vboid;
383       size_t pickvboid;
384       int pickcolorsset;
get_data_lengthsphere_buffers385       int get_data_length() const { return num_spheres * 2; };
386     };
387 
388     struct cylinder_buffers : op_with_data, op_with_draw_buffers {
389       static const int op_code = CGO_DRAW_CYLINDER_BUFFERS;
cylinder_bufferscylinder_buffers390       cylinder_buffers(int _num_cyl, int _alpha, size_t _vboid,
391                        size_t _iboid, size_t _pickvboid) :
392         num_cyl(_num_cyl), alpha(_alpha), vboid(_vboid),
393         iboid(_iboid), pickvboid(_pickvboid), pickcolorsset(0) {
394       }
395       int num_cyl;
396       int alpha;
397       size_t vboid;
398       size_t iboid;
399       size_t pickvboid;
400       int pickcolorsset;
get_data_lengthcylinder_buffers401       int get_data_length() const { return num_cyl * 2 * 2; };
402     };
403 
404     struct textures : op_with_data, op_with_draw_buffers {
405       static const int op_code = CGO_DRAW_TEXTURES;
texturestextures406       textures(int _ntextures, size_t _vboid) : ntextures(_ntextures), vboid(_vboid) { }
407       int ntextures;
408       size_t vboid;
get_data_lengthtextures409       int get_data_length() const { return ntextures * 18; };
410     };
411 
412     struct screen_textures : op_with_draw_buffers {
413       static const int op_code = CGO_DRAW_SCREEN_TEXTURES_AND_POLYGONS;
screen_texturesscreen_textures414       screen_textures(int _nverts, size_t _vboid) : nverts(_nverts),
415                                                         vboid(_vboid) {};
416       int nverts;
417       size_t vboid;
418     };
419 
420     struct buffers_not_indexed : op_with_data, op_with_draw_buffers {
421       static const int op_code = CGO_DRAW_BUFFERS_NOT_INDEXED;
422       buffers_not_indexed(int _mode, int _arrays, int _nverts,
423                           size_t _vboid, size_t _pickvboid = 0) :
modebuffers_not_indexed424         mode(_mode), arraybits(_arrays), narrays(0), nverts(_nverts),
425         vboid(_vboid), pickvboid(_pickvboid), pickcolorsset(0) {
426         for (short bit = 0; bit < 4; bit++){
427           if ((1 << bit) & arraybits){
428             narrays++;
429           }
430         }
431         if (arraybits & CGO_ACCESSIBILITY_ARRAY) narrays++;
432         if (arraybits & CGO_COLOR_ARRAY) narrays++;
433       };
434       int mode;
435       int arraybits;
436       int narrays;
437       int nverts;
438       size_t vboid;
439       size_t pickvboid;
440       int pickcolorsset;
get_data_lengthbuffers_not_indexed441       int get_data_length() const { return nverts * 3; };
442     };
443 
444     struct label {
445       using vec3 = glm::vec3;
446       using vec4 = glm::vec4;
447       static const int op_code = CGO_DRAW_LABEL;
labellabel448       label(const vec3& _world_pos, const vec3& _screen_world_offset, const vec3& _screen_min,
449             const vec3& _screen_max, const vec4& _text_extent, float _relative_mode,
450             const vec3& _target_pos) :
451         world_pos(_world_pos), screen_world_offset(_screen_world_offset), screen_min(_screen_min),
452         screen_max(_screen_max), text_extent(_text_extent), relative_mode(_relative_mode),
453         target_pos(_target_pos) {}
454       vec3 world_pos;
455       vec3 screen_world_offset;
456       vec3 screen_min;
457       vec3 screen_max;
458       vec4 text_extent;
459       float relative_mode;
460       vec3 target_pos;
461     };
462 
463     struct labels : op_with_data, op_with_draw_buffers {
464       static const int op_code = CGO_DRAW_LABELS;
labelslabels465       labels(int _ntextures, size_t _vboid, size_t _pickvboid) :
466         vboid(_vboid)
467         , pickvboid(_pickvboid)
468         , ntextures(_ntextures)
469         , pickcolorsset(0)
470       {}
471       size_t vboid;
472       size_t pickvboid;
473       int ntextures;
474       int pickcolorsset;
get_data_lengthlabels475       int get_data_length() const { return ntextures * 18; };
476     };
477 
478     struct connectors : op_with_draw_buffers {
479       static const int op_code = CGO_DRAW_CONNECTORS;
connectorsconnectors480       connectors(int _nconnectors, size_t _vboid) :
481         nconnectors(_nconnectors), vboid(_vboid) {};
482       int nconnectors;
483       size_t vboid;
484     };
485 
486     struct line {
487       static const int op_code = CGO_LINE;
lineline488       line(const float *v1, const float *v2) {
489         copy3f(v1, vertex1);
490         copy3f(v2, vertex2);
491       };
492       float vertex1[3], vertex2[3];
493     };
494     struct splitline {
495       static const int op_code = CGO_SPLITLINE;
496 
497       static const unsigned char interpolation = 0x01; // ramp/interpolation
498       static const unsigned char no_split_for_pick = 0x02;
499       static const unsigned char equal_colors = 0x04;
splitlinesplitline500       splitline(const float *v1, const float *v2, const float *color2arg,
501                 unsigned int index_2nd, int bond_2nd,
502                 bool isRamped, bool same_pick, bool eq_colors) :
503       index(index_2nd), bond(bond_2nd) {
504           copy3f(v1, vertex1);
505           copy3f(v2, vertex2);
506           color2[0] = CLIP_COLOR_VALUE(color2arg[0]);
507           color2[1] = CLIP_COLOR_VALUE(color2arg[1]);
508           color2[2] = CLIP_COLOR_VALUE(color2arg[2]);
509           flags = (isRamped ? cgo::draw::splitline::interpolation : 0x00) |
510             (same_pick ? cgo::draw::splitline::no_split_for_pick : 0x00) |
511             (eq_colors ? cgo::draw::splitline::equal_colors : 0x00);
512       };
513       float vertex1[3], vertex2[3];
514       unsigned char color2[3];
515       unsigned char flags; // interpolation | no_split_for_pick | equal_colors
516       unsigned int index;
517       int bond;
518     };
519 
520     struct mask_attribute_if_picking : op_with_draw_buffers {
521       static const int op_code = CGO_MASK_ATTRIBUTE_IF_PICKING;
mask_attribute_if_pickingmask_attribute_if_picking522       mask_attribute_if_picking(int _attr_lookup_idx, size_t _vboid) {
523         attr_lookup_idx = _attr_lookup_idx;
524         vboid = _vboid;
525       };
526       int attr_lookup_idx;
527       size_t vboid;
528     };
529 
530     struct bind_vbo_for_picking : op_with_draw_buffers {
531       static const int op_code = CGO_BIND_VBO_FOR_PICKING;
bind_vbo_for_pickingbind_vbo_for_picking532       bind_vbo_for_picking(size_t _vboid, int _which_attr_idx, int _npickattrs) {
533         vboid = _vboid;
534         which_attr_idx = _which_attr_idx;
535         npickattrs = _npickattrs;
536       };
537       size_t vboid;
538       int which_attr_idx;
539       int npickattrs;
540     };
541 
542     struct custom : op_with_data, op_with_draw_buffers {
543       static const int op_code = CGO_DRAW_CUSTOM;
544       custom(int _mode, int _nverts, size_t _vboid, size_t _pickvboid,
545           int _vertsperpickinfo = 1, int _npickbufs = 1, size_t _iboid = 0,
546           int _nindices = 0)
modecustom547           : mode(_mode), nverts(_nverts), vboid(_vboid), pickvboid(_pickvboid),
548             pickcolorsset(0), iboid(_iboid), nindices(_nindices),
549             npickbufs(_npickbufs), vertsperpickinfo(_vertsperpickinfo){};
550       int mode;
551       int nverts;
552       size_t vboid;
553       size_t pickvboid;
554       int pickcolorsset;
555       size_t iboid;
556       int nindices;
557       int npickbufs;
558       int vertsperpickinfo;
get_data_lengthcustom559       int get_data_length() const { return npickbufs*nverts*2/vertsperpickinfo; };
560     };
561 
562     struct vertex_attribute_3f {
563       static const int op_code = CGO_VERTEX_ATTRIB_3F;
vertex_attribute_3fvertex_attribute_3f564       vertex_attribute_3f(int _attr_lookup_idx, void *v) {
565         attr_lookup_idx = _attr_lookup_idx;
566         copy3f((float*)v, values);
567       };
568       int attr_lookup_idx;
569       float values[3];
570     };
571 
572     struct vertex_attribute_4ub {
573       static const int op_code = CGO_VERTEX_ATTRIB_4UB;
vertex_attribute_4ubvertex_attribute_4ub574       vertex_attribute_4ub(int _attr_lookup_idx, void *_ubdata) {
575         attr_lookup_idx = _attr_lookup_idx;
576         memcpy(ubdata, _ubdata, 4);
577       };
578       int attr_lookup_idx;
579       unsigned char ubdata[4];
580     };
581 
582     struct vertex_attribute_4ub_if_picking {
583       static const int op_code = CGO_VERTEX_ATTRIB_4UB_IF_PICKING;
vertex_attribute_4ub_if_pickingvertex_attribute_4ub_if_picking584       vertex_attribute_4ub_if_picking(int _attr_lookup_idx, void *_ubdata) {
585         attr_lookup_idx = _attr_lookup_idx;
586         memcpy(ubdata, _ubdata, 4);
587       };
588       int attr_lookup_idx;
589       unsigned char ubdata[4];
590     };
591 
592     struct vertex_attribute_1f {
593       static const int op_code = CGO_VERTEX_ATTRIB_1F;
vertex_attribute_1fvertex_attribute_1f594       vertex_attribute_1f(int _attr_lookup_idx, float v) {
595         attr_lookup_idx = _attr_lookup_idx;
596         value = v;
597       };
598       int attr_lookup_idx;
599       float value;
600     };
601 
602     struct shadercylinder {
603       static const int op_code = CGO_SHADER_CYLINDER;
shadercylindershadercylinder604     shadercylinder(const float *_origin, const float *_axis, const float _tube_size, int _cap) :
605       tube_size(_tube_size), cap(_cap) {
606           copy3f(_origin, origin);
607           copy3f(_axis, axis);
608       };
609       float origin[3], axis[3], tube_size;
610       int cap;
611     };
612 
613     struct shadercylinder2ndcolor {
614       static const int op_code = CGO_SHADER_CYLINDER_WITH_2ND_COLOR;
615       shadercylinder2ndcolor(CGO *I, const float *_origin, const float *_axis, const float _radius,
616                              int _cap, const float *_color2, Pickable *pickcolor2 = NULL,
617                              const float alpha = -1.f);
618       float origin[3], axis[3], tube_size;
619       int cap;
620       float color2[3];
621       unsigned int pick_color_index;
622       int pick_color_bond;
623       float alpha;
624     };
625 
626     struct sausage {
627       static const int op_code = CGO_SAUSAGE;
sausagesausage628       sausage(const float *_vertex1, const float *_vertex2, const float _radius, const float *_color1, const float *_color2) :
629       radius(_radius) {
630           copy3f(_vertex1, vertex1);
631           copy3f(_vertex2, vertex2);
632           copy3f(_color1, color1);
633           copy3f(_color2, color2);
634       };
635       float vertex1[3], vertex2[3], radius, color1[3], color2[3];
636     };
637 
638     struct cylinder {
639       static const int op_code = CGO_CYLINDER;
cylindercylinder640       cylinder(const float *_vertex1, const float *_vertex2, const float _radius, const float *_color1, const float *_color2) :
641       radius(_radius) {
642           copy3f(_vertex1, vertex1);
643           copy3f(_vertex2, vertex2);
644           copy3f(_color1, color1);
645           copy3f(_color2, color2);
646       };
647       float vertex1[3], vertex2[3], radius, color1[3], color2[3];
648     };
649 
650     struct custom_cylinder {
651       static const int op_code = CGO_CUSTOM_CYLINDER;
custom_cylindercustom_cylinder652     custom_cylinder(const float *_vertex1, const float *_vertex2, const float _radius, const float *_color1, const float *_color2, const float _cap1, const float _cap2) :
653       radius(_radius), cap1(_cap1), cap2(_cap2) {
654           copy3f(_vertex1, vertex1);
655           copy3f(_vertex2, vertex2);
656           copy3f(_color1, color1);
657           copy3f(_color2, color2);
658       };
659       float vertex1[3], vertex2[3], radius, color1[3], color2[3];
660       float cap1, cap2;
661     };
662 
663     struct custom_cylinder_alpha {
664       static const int op_code = CGO_CUSTOM_CYLINDER_ALPHA;
custom_cylinder_alphacustom_cylinder_alpha665       custom_cylinder_alpha(const float *_vertex1, const float *_vertex2, const float _radius, const float *_color1, const float *_color2,
666                             const float _alpha1, const float _alpha2,
667                             const float _cap1, const float _cap2) :
668       radius(_radius), cap1(_cap1), cap2(_cap2) {
669           copy3f(_vertex1, vertex1);
670           copy3f(_vertex2, vertex2);
671           copy3f(_color1, color1);
672           copy3f(_color2, color2);
673           color1[3] = _alpha1;
674           color2[3] = _alpha2;
675       };
676       float vertex1[3], vertex2[3], radius, color1[4], color2[4];
677       float cap1, cap2;
678     };
679   };
680 };
681 
682 class CGO {
683 public:
684   CGO(PyMOLGlobals* G, int size = 0);
685   ~CGO();
686 
687   PyMOLGlobals *G { nullptr };
688   float *op { nullptr };
689   size_t c = 0;
690   bool z_flag = false;
691   float z_min { 0 }, z_max { 0 };
692   float z_vector[3];
693   float alpha { 1.f };
694   int *i_start { 0 }, i_size { 0 };
695   unsigned int current_pick_color_index { 0 };
696   int current_pick_color_bond { cPickableNoPick };
697   float current_accessibility { 1.f };
698   float normal[3]{0.f, 0.f, 1.f};
699   float color[3]{};
700   float texture[2];
701   uchar pickColor[4]{0, 0, 0, 0xff};
702   bool has_begin_end { false };
703   bool has_draw_buffers { false }, has_draw_cylinder_buffers { false }, has_draw_sphere_buffers { false };
704   bool use_shader { false }, cgo_shader_ub_color { false }, cgo_shader_ub_normal { false };
705   bool debug { false };
706   bool no_pick { false };
707   short render_alpha { 0 };  // 1 : render CGOSetZVector/CGORenderGLAlpha only
708                        // 2 : render both CGOSetZVector/CGORenderGLAlpha and rest of object
709                        // calcDepth=1 by default
710   short sphere_quality { 0 }; // quality of spheres when simplified or rendered in immediate mode
711   bool interpolated { false };
712   /***********************************************************************
713    * CGO iterator
714    *
715    * for (auto it = cgo->begin(); !it.is_stop(); ++it) {
716    *   auto pc = it.data();
717    *   int op = it.op_code();
718    *   ...
719    * }
720    ***********************************************************************/
721 
722   class const_iterator {
723     protected:
724       const float * m_pc;
725       const float * m_stop;
726     public:
op_code()727       unsigned op_code() const {
728         return *reinterpret_cast<const unsigned*>(m_pc);
729       }
730       operator int() const { return op_code(); }
731 
data()732       const float * data() const { return m_pc + 1; }
733 
734       template <typename T>
cast()735       const T * cast() const { return reinterpret_cast<const T *>(m_pc + 1); }
736 
const_iterator(const CGO * cgo)737       const_iterator(const CGO * cgo) {
738         m_pc = cgo->op;
739         m_stop = cgo->op + cgo->c;
740       }
741 
742       const_iterator& operator++();
743 
is_stop()744       bool is_stop() const {
745         return m_pc == m_stop || op_code() == CGO_STOP;
746       }
747   };
748 
749   class iterator : public const_iterator {
750     public:
iterator(CGO * cgo)751       iterator(CGO * cgo) : const_iterator(cgo) {}
data()752       float * data() { return const_cast<float*>(m_pc + 1); }
cast()753       template <typename T> T* cast() { return reinterpret_cast<T*>(data()); }
754   };
755 
begin()756   const_iterator begin() const { return this; }
begin()757   iterator begin() { return this; }
758 
759   /***********************************************************************
760    * This is the add function, the signature may look weird but it's
761    * common c++11 perfect forwarding. This function passes the constructor
762    * arguments into the function. Meaning it is used like:
763    * cgo.add<cgo::draw::arrays>(mode, arrays, nverts);
764    ***********************************************************************/
add(TArgs &&...args)765   template <typename T, typename... TArgs> float * add(TArgs&&... args) {
766     int size = fsizeof<T>() + 1;
767     float * at = add_to_buffer(size);
768     // write the op code
769     CGO_write_int(at, T::op_code);
770     // call the type constructor in place forwarding the args to the constructor
771     T * sp = new (at) T(std::forward<TArgs>(args)...);
772 
773     if (std::is_base_of<cgo::draw::op_with_draw_buffers, T>::value) {
774       has_draw_buffers = true;
775     }
776 
777     if (std::is_base_of<cgo::draw::op_with_data, T>::value) {
778       auto ptr = reinterpret_cast<cgo::draw::op_with_data *>(sp);
779       // set the buffer data flag
780       // create the floating point data for this type
781       auto data_len = ptr->get_data_length();
782       if (data_len) {
783         ptr->set_data(allocate_in_data_heap(data_len));
784         return ptr->get_data();
785       }
786     }
787 
788     // this op does not have dynamic data, but since the caller knows
789     // then we return the allocated pointer, so that the caller can determine
790     // whether this was successful or not.
791     return at;
792   }
793 
794   // Appends the source CGO onto this CGO
795   int append(const CGO * source, bool stopAtEnd);
796   void move_append(CGO * source);
797   void free_append(CGO * &source);
798 
799   // Allocates in our CGO data pool
allocate_in_data_heap(size_t size)800   float * allocate_in_data_heap(size_t size) {
801     std::unique_ptr<float[]> uni(new float[size]);
802     float * ptr = uni.get();
803     _data_heap.emplace_back(std::move(uni));
804     return ptr;
805   }
806 
807   // templated by the op type
copy_op_from(const float * pc)808   template <typename T> void copy_op_from(const float * pc) {
809     // copy the op
810     const size_t op_size = fsizeof<T>() + 1; // + 1 is the op
811     float * at = add_to_buffer(op_size);
812     memcpy(at, (pc - 1), op_size * 4);
813 
814     if (std::is_base_of<cgo::draw::op_with_draw_buffers, T>::value) {
815       has_draw_buffers = true;
816     }
817 
818     if (std::is_base_of<cgo::draw::op_with_data, T>::value) {
819       // copy the float data
820       float * vals { nullptr };
821       auto ptr = reinterpret_cast<const cgo::draw::op_with_data*>(pc);
822       int data_len = ptr->get_data_length();
823       if (data_len) {
824         vals = allocate_in_data_heap(data_len);
825         memcpy(vals, ptr->get_data(), data_len * 4);
826       }
827       auto spop = reinterpret_cast<cgo::draw::op_with_data *>(at + 1);
828       spop->set_data( vals );
829     }
830   }
831 
832   // Our CGO_add, allocates size bytes at end of cgo buffer
add_to_buffer(int size)833   float * add_to_buffer(int size) {
834     float * at { nullptr };
835     VLACheck(op, float, size + c);
836     if (!op)
837       return nullptr;
838     at = op + c;
839     c += size;
840     return at;
841   }
842 
843   /***********************************************************************
844    * This function adds to the end of this CGO the cgo op that exists in
845    * the float. This function will also increment the pointer passed to it
846    * by the size of the operation.
847    ***********************************************************************/
848   void add_to_cgo(int, const float*);
849 
850   // Pretty prints a table with the layout of this CGO
851   void print_table() const;
852 
853 private:
854   std::vector<std::unique_ptr<float[]>> _data_heap;
855 };
856 
857 int CGORendererInit(PyMOLGlobals * G);
858 void CGORendererFree(PyMOLGlobals * G);
859 #define CGONew new CGO
860 #define CGONewSized CGONew
861 int CGOGetExtent(const CGO * I, float *mn, float *mx);
862 int CGOHasNormals(const CGO * I);
863 
864 void CGOFree(CGO * &I, bool withVBOs=true);
865 #define CGOFreeWithoutVBOs(I) CGOFree(I, false)
866 
867 CGO *CGODrawText(const CGO * I, int est, float *camera);
868 
869 CGO *CGOSimplify(const CGO * I, int est, short sphere_quality = -1, bool stick_round_nub = true);
870 CGO *CGOSimplifyNoCompress(const CGO * I, int est, short sphere_quality = -1, bool stick_round_nub = true);
871 
872 // -1 - no lines, 0 - some no interpolation, 1 - all interpolation, 2 - all no interpolation
873 bool CGOCombineBeginEnd(CGO ** I, bool do_not_split_lines = false);
874 CGO *CGOCombineBeginEnd(const CGO * I, int est, bool do_not_split_lines = false);
875 
876 void CGOFreeVBOs(CGO *I);
877 
878 CGO *CGOOptimizeToVBOIndexed(CGO * I, int est=0, const float *color=NULL, bool addshaders=true, bool embedTransparencyInfo=false);
879 #define CGOOptimizeToVBOIndexedWithColorEmbedTransparentInfo(I, est, color, addshaders) CGOOptimizeToVBOIndexed(I, est, color, addshaders, true)
880 #define CGOOptimizeToVBOIndexedWithColor CGOOptimizeToVBOIndexed
881 #define CGOOptimizeToVBOIndexedNoShader(I, est) CGOOptimizeToVBOIndexed(I, est, NULL, false)
882 
883 bool CGOOptimizeToVBONotIndexed(CGO ** I);
884 CGO *CGOOptimizeToVBONotIndexed(const CGO * I, int est, bool addshaders=true, float **returnedData=NULL);
885 
886 #define CGOOptimizeToVBONotIndexedWithReturnedData CGOOptimizeToVBONotIndexed
887 #define CGOOptimizeToVBONotIndexedNoShader(I, est) CGOOptimizeToVBONotIndexed(I, est, false)
888 
889 
890 CGO *CGOOptimizeSpheresToVBONonIndexed(const CGO * I, int est=0, bool addshaders=false, CGO *leftOverCGO=NULL);
891 #define CGOOptimizeSpheresToVBONonIndexedNoShader(I, est) CGOOptimizeSpheresToVBONonIndexed(I, est, false, NULL)
892 
893 int CGOCheckComplex(CGO * I);
894 int CGOPreloadFonts(CGO * I);
895 
896 int CGOCheckForText(CGO * I);
897 
898 int CGOFromFloatArray(CGO * I, const float *src, int len);
899 
900 int CGOBegin(CGO * I, int mode);
901 int CGOEnd(CGO * I);
902 
903 int CGOSphere(CGO * I, const float *v1, float r);
904 int CGOEllipsoid(CGO * I, const float *v1, float r, const float *n1, const float *n2, const float *n3);
905 int CGOQuadric(CGO * I, const float *v1, float r, const float *p); /* NOT WORKING YET */
906 int CGOVertex(CGO * I, float v1, float v2, float v3);
907 int CGOVertexv(CGO * I, const float *v);
908 int CGOVertexCrossv(CGO * I, const float *v);
909 int CGOVertexBeginLineStripv(CGO * I, const float *v);
910 int CGOInterpolated(CGO * I, const bool interp);
911 int CGOAlpha(CGO * I, float alpha);
912 int CGOColor(CGO * I, float v1, float v2, float v3);
913 int CGOColorv(CGO * I, const float *v);
914 int CGOTexCoord2f(CGO * I, float v1, float v2);
915 int CGONormal(CGO * I, float v1, float v2, float v3);
916 int CGONormalv(CGO * I, const float *v);
917 int CGOResetNormal(CGO * I, int mode);
918 int CGOLinewidth(CGO * I, float v);
919 int CGOSpecial(CGO * I, int v);
920 // all pre-processor definitions for CGOSpecial ops
921 enum {
922   LINEWIDTH_DYNAMIC_WITH_SCALE = 1,
923   LINEWIDTH_DYNAMIC_MESH,
924   POINTSIZE_DYNAMIC_DOT_WIDTH,
925   LINEWIDTH_DYNAMIC_WITH_SCALE_RIBBON,
926   LINEWIDTH_DYNAMIC_WITH_SCALE_DASH,
927   CYLINDERWIDTH_DYNAMIC_MESH,
928   LINEWIDTH_WITH_SCALE,
929   DOTSIZE_WITH_SPHERESCALE,
930   MESH_WIDTH_FOR_SURFACES,
931   CYLINDER_WIDTH_FOR_DISTANCES,
932   CYLINDER_WIDTH_FOR_RIBBONS,
933   DOT_WIDTH_FOR_DOTS,
934   DOT_WIDTH_FOR_DOT_SPHERES,
935   CYLINDER_WIDTH_FOR_NONBONDED,
936   CYLINDER_WIDTH_FOR_REPWIRE,
937   CYLINDER_WIDTH_FOR_REPWIRE_VARWIDTH,
938   ENABLE_BACK_FACES_IF_NOT_TWO_SIDED,
939   DISABLE_BACK_FACES_IF_NOT_TWO_SIDED,
940   SET_SURFACE_UNIFORMS,
941   SET_ALIGNMENT_UNIFORMS_ATTRIBS,
942   LINEWIDTH_FOR_LINES,
943   SET_LABEL_SCALE_UNIFORMS
944 };
945 
946 int CGOSpecialWithArg(CGO * I, int v, float arg);
947 #define SPHERE_MODE_OPS 1
948 #define LINE_LIGHTING  2
949 
950 int CGODotwidth(CGO * I, float v);
951 int CGOChar(CGO * I, char c);
952 int CGOFontVertex(CGO * I, float x, float y, float z);
953 int CGOFontVertexv(CGO * I, const float *v);
954 int CGOFontScale(CGO * I, float v1, float v2);
955 int CGOIndent(CGO * I, char c, float dir);
956 int CGOWrite(CGO * I, const char *str);
957 int CGOWriteLeft(CGO * I, const char *str);
958 int CGOWriteIndent(CGO * I, const char *str, float indent);
959 
960 #define CGODrawArrays(this, ...) (this)->add<cgo::draw::arrays>(__VA_ARGS__)
961 #define CGOCustomCylinderv(this, ...) (this)->add<cgo::draw::custom_cylinder>(__VA_ARGS__)
962 #define CGOShaderCylinder(this, ...) (this)->add<cgo::draw::shadercylinder>(__VA_ARGS__)
963 #define CGOCylinderv(this, ...) (this)->add<cgo::draw::cylinder>(__VA_ARGS__)
964 
965 int CGOBoundingBox(CGO *I, const float *min, const float *max);
966 int CGOAccessibility(CGO * I, const float a);
967 
968 int CGODrawTexture(CGO *I, int texture_id, float *worldPos, float *screenMin, float *screenMax, float *textExtent);
969 int CGODrawLabel(CGO *I, int texture_id, float *targetPos, float *worldPos, float *screenWorldOffset, float *screenMin, float *screenMax, float *textExtent, short relativeMode);
970 int CGODrawConnector(CGO *I, float *targetPt3d, float *labelCenterPt3d, float text_width, float text_height, float *screenOffset, float *screenWorldOffset, float *connectorColor, short relativeMode, int draw_bkgrd, float bkgrd_transp, float *bkgrd_color, float rel_ext_length, float connectorWidth);
971 CGO *CGOOptimizeLabels(const CGO * I, int est, bool addshaders=false);
972 CGO *CGOOptimizeTextures(const CGO * I, int est);
973 CGO *CGOExpandDrawTextures(const CGO * I, int est);
974 CGO *CGOOptimizeConnectors(const CGO * I, int est);
975 
976 /*void CGOFontScale(CGO *I,float v);
977   void CGOFont(CGO *I,float size,int face,int style);*/
978 
979 void CGORoundNub(CGO * I,
980     const float *v1,    // cap center
981     const float *p0,    // normal along axis
982     const float *p1,    // x coord in cap space
983     const float *p2,    // y coord in cap space
984     int direction,      // 1 or -1
985     int nEdge,          // "quality"
986     float size);
987 
988 int CGOEnable(CGO * I, int mode);
989 int CGODisable(CGO * I, int mode);
990 
991 int CGOStop(CGO * I);
992 
993 int CGOConev(CGO * I, const float *p1, const float *p2, float r1, float r2, const float *c1, const float *c2,
994               float cap1, float cap2);
995 
996 int CGOAlphaTriangle(CGO * I,
997 		     const float *v1, const float *v2, const float *v3,
998 		     const float *n1, const float *n2, const float *n3,
999 		     const float *c1, const float *c2, const float *c3,
1000 		     float a1, float a2, float a3, int reverse);
1001 void CGOSetZVector(CGO * I, float z0, float z1, float z2);
1002 struct GadgetSet;
1003 void CGORenderGLPicking(CGO * I, RenderInfo *info,
1004                         PickContext * context, CSetting * set1, CSetting * set2, Rep *rep=NULL);
1005 void CGORenderGL(CGO * I, const float *color, CSetting * set1, CSetting * set2,
1006                  RenderInfo * info, Rep *rep);
1007 void CGORenderGLAlpha(CGO * I, RenderInfo * info, bool calcDepth);
1008 int CGORenderRay(CGO * I, CRay * ray, RenderInfo * info, const float *color, ObjectGadgetRamp *ramp, CSetting * set1, CSetting * set2);
1009 void CGOReset(CGO * I);
1010 
1011 void CGOSetUseShader(CGO *I, int use_shader);
1012 
1013 PyObject *CGOAsPyList(CGO * I);
1014 CGO *CGONewFromPyList(PyMOLGlobals * G, PyObject * list, int version, bool shouldCombine=true);
1015 int CGOPickColor(CGO * I, unsigned int index, int bond);
1016 
1017 const cgo::draw::buffers_not_indexed* CGOGetNextDrawBufferedNotIndex(
1018     const CGO*);
1019 
1020 float *CGOGetNextOp(float *cgo_op, int optype);
1021 
1022 int CGOAppend(CGO *dest, const CGO *source, bool stopAtEnd=true);
CGOAppendNoStop(CGO * dest,const CGO * source)1023 inline int CGOAppendNoStop(CGO *dest, const CGO *source) {
1024   return CGOAppend(dest, source, false);
1025 }
1026 
1027 int CGOCountNumberOfOperationsOfType(const CGO *I, int op);
1028 int CGOCountNumberOfOperationsOfTypeN(const CGO *I, const std::set<int> &optype);
1029 int CGOCountNumberOfOperationsOfTypeN(const CGO *I, const std::map<int, int> &optype);
1030 bool CGOHasOperations(const CGO *I);
1031 bool CGOHasOperationsOfType(const CGO *I, int optype);
1032 bool CGOHasOperationsOfTypeN(const CGO *I, const std::set<int> &optype);
1033 bool CGOHasCylinderOperations(const CGO *I);
1034 bool CGOHasSphereOperations(const CGO *I);
1035 bool CGOFilterOutCylinderOperationsInto(const CGO *I, CGO *cgo);
1036 
1037 bool CGOCheckWhetherToFree(PyMOLGlobals * G, CGO *I);
1038 
1039 CGO *CGOConvertLinesToShaderCylinders(const CGO * I, int est);
1040 CGO *CGOSplitUpLinesForPicking(const CGO * I);
1041 CGO *CGOConvertLinesToTrilines(const CGO * I, bool addshaders=true);
1042 CGO *CGOConvertToLabelShader(const CGO *I, CGO * addTo);
1043 
1044 void CGOChangeShadersTo(CGO *I, int frommode, int tomode);
1045 void CGOCountNumVerticesDEBUG(const CGO *I);
1046 CGO *CGOOptimizeScreenTexturesAndPolygons(CGO * I, int est);
1047 CGO *CGOColorByRamp(PyMOLGlobals * G, const CGO *I, ObjectGadgetRamp *ramp, int state, CSetting * set1);
1048 
1049 #define CGOLineAsTriangleStrips(CGO, minx, miny, maxx, maxy) \
1050 	CGOBegin(CGO, GL_TRIANGLE_STRIP);         \
1051 	CGOVertex(CGO, minx, miny, 0.f);         \
1052 	CGOVertex(CGO, minx, maxy+1, 0.f);         \
1053 	CGOVertex(CGO, minx+1, miny, 0.f);         \
1054 	CGOVertex(CGO, minx+1, maxy+1, 0.f);         \
1055 	CGOEnd(CGO);         \
1056 	CGOBegin(CGO, GL_TRIANGLE_STRIP);         \
1057 	CGOVertex(CGO, minx, maxy, 0.f);         \
1058 	CGOVertex(CGO, minx, maxy+1, 0.f);         \
1059 	CGOVertex(CGO, maxx, maxy, 0.f);         \
1060 	CGOVertex(CGO, maxx, maxy+1, 0.f);         \
1061 	CGOEnd(CGO);         \
1062 	CGOBegin(CGO, GL_TRIANGLE_STRIP);         \
1063 	CGOVertex(CGO, maxx, miny, 0.f);         \
1064 	CGOVertex(CGO, maxx, maxy+1, 0.f);         \
1065 	CGOVertex(CGO, maxx+1, miny, 0.f);         \
1066 	CGOVertex(CGO, maxx+1, maxy+1, 0.f);         \
1067 	CGOEnd(CGO);         \
1068 	CGOBegin(CGO, GL_TRIANGLE_STRIP);         \
1069 	CGOVertex(CGO, minx, miny, 0.f);         \
1070 	CGOVertex(CGO, minx, miny+1, 0.f);         \
1071 	CGOVertex(CGO, maxx, miny, 0.f);         \
1072 	CGOVertex(CGO, maxx, miny+1, 0.f);         \
1073 	CGOEnd(CGO);
1074 
1075 int CGOHasTransparency(const CGO *I, bool checkTransp=true, bool checkOpaque=false);
1076 #define CGOHasOpaque(I) CGOHasTransparency(I, false, true)
1077 
1078 CGO *CGOConvertTrianglesToAlpha(const CGO * I);
1079 CGO *CGOGenerateNormalsForTriangles(const CGO * I);
1080 
1081 bool CGOHasAnyTriangleVerticesWithoutNormals(const CGO *I, bool checkTriangles=true);
1082 #define CGOHasAnyLineVerticesWithoutNormals(I) CGOHasAnyTriangleVerticesWithoutNormals(I, false)
1083 
1084 CGO* CGOTurnLightingOnLinesOff(const CGO* I, bool use_shader);
CGOTurnLightingOnLinesOff(const CGO * I)1085 inline CGO* CGOTurnLightingOnLinesOff(const CGO* I)
1086 {
1087   return CGOTurnLightingOnLinesOff(I, I->use_shader);
1088 }
1089 
1090 // returns offset of floats in CGO array
1091 int CGOUniform3f(CGO *I, int uniform_id, const float *value);
1092 
1093 CGO *CGOConvertSpheresToPoints(const CGO *I);
1094 
1095 #ifdef _PYMOL_ARB_SHADERS
1096 void CGORenderSpheresARB(RenderInfo *info, const CGO *I, const float *fog_info);
1097 #endif
1098 
1099 CGO *CGOConvertToShader(const CGO *I, AttribDataDesc &attrData, AttribDataDesc &pickData, int mode, const VertexBuffer::buffer_layout layout=VertexBuffer::INTERLEAVED, bool check_attr_for_data=true, int *idx_array=NULL, int nindicesperfrag=0, int nfragspergroup = 1);
1100 
1101 bool CGOCheckSplitLineInterpolationIsSame(const CGO *I, bool &interp_value);
1102 
1103 CGO *CGOConvertToTrilinesShader(const CGO *I, CGO *addTo, bool add_color=true);
1104 CGO *CGOConvertToLinesShader(const CGO *I, CGO *addTo, bool add_color=true);
1105 
1106 CGO *CGOConvertLinesToCylinderShader(const CGO *I, CGO *addTo, bool add_color = true);
1107 CGO *CGOConvertCrossesToCylinderShader(const CGO *I, CGO *addTo, float cross_size);
1108 CGO *CGOConvertCrossesToLinesShader(const CGO *I, CGO *addTo, float cross_size);
1109 CGO *CGOConvertCrossesToTrilinesShader(const CGO *I, CGO *addTo, float cross_size);
1110 CGO *CGOConvertShaderCylindersToCylinderShader(const CGO *I, CGO *addTo);
1111 
1112 void AssignNewPickColor(CGO* cgo, PickColorManager*, unsigned char* color,
1113     const PickContext* context, unsigned int index, int bond);
1114 
1115 #endif
1116