1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 12 мая 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <ui/tk/tk.h> 23 24 namespace lsp 25 { 26 namespace tk 27 { 28 #define V3(x, y, z) { x, y, z, 1.0f } 29 30 static const point3d_t tk_capture_vertices[] = 31 { 32 V3(0, 0, 0), 33 V3(0.30, 0, 0), 34 V3(0.22, 0.06, 0), 35 V3(0.22, -0.06, 0), 36 V3(0.22, 0, 0.06), 37 V3(0.22, 0, -0.06) 38 }; 39 // 40 // static const point3d_t tk_capture_capsule[] = 41 // { 42 // V3(0, 0, 1), V3(1, 0, 0), V3(0, 1, 0), 43 // V3(0, 0, 1), V3(0, 1, 0), V3(-1, 0, 0), 44 // V3(0, 0, 1), V3(-1, 0, 0), V3(0, -1, 0), 45 // V3(0, 0, 1), V3(0, -1, 0), V3(1, 0, 0), 46 // 47 // V3(0, 0, -1), V3(0, 1, 0), V3(1, 0, 0), 48 // V3(0, 0, -1), V3(-1, 0, 0), V3(0, 1, 0), 49 // V3(0, 0, -1), V3(0, -1, 0), V3(-1, 0, 0), 50 // V3(0, 0, -1), V3(1, 0, 0), V3(0, -1, 0), 51 // }; 52 53 static const uint32_t tk_arrow_indexes[] = 54 { 55 0, 1, 56 1, 2, 57 1, 3, 58 1, 4, 59 1, 5 60 }; 61 62 const w_class_t LSPCapture3D::metadata = { "LSPCapture3D", &LSPObject3D::metadata }; 63 LSPCapture3D(LSPDisplay * dpy)64 LSPCapture3D::LSPCapture3D(LSPDisplay *dpy): 65 LSPObject3D(dpy), 66 sColor(this), 67 sAxisColor(this) 68 { 69 pClass = &metadata; 70 } 71 ~LSPCapture3D()72 LSPCapture3D::~LSPCapture3D() 73 { 74 } 75 init()76 status_t LSPCapture3D::init() 77 { 78 status_t res = LSPObject3D::init(); 79 if (res != STATUS_OK) 80 return res; 81 82 init_color(C_RED, &sColor); 83 init_color(C_YELLOW, &sAxisColor); 84 return STATUS_OK; 85 } 86 destroy()87 void LSPCapture3D::destroy() 88 { 89 LSPObject3D::destroy(); 90 } 91 get_position(point3d_t * dst,size_t id)92 status_t LSPCapture3D::get_position(point3d_t *dst, size_t id) 93 { 94 v_capture_t *cap = vItems.get(id); 95 if (cap == NULL) 96 return STATUS_NOT_FOUND; 97 dsp::init_point_xyz(dst, 0.0f, 0.0f, 0.0f); 98 dsp::apply_matrix3d_mp1(dst, &cap->pos); 99 return STATUS_OK; 100 } 101 get_direction(vector3d_t * dst,size_t id)102 status_t LSPCapture3D::get_direction(vector3d_t *dst, size_t id) 103 { 104 v_capture_t *cap = vItems.get(id); 105 if (cap == NULL) 106 return STATUS_NOT_FOUND; 107 dsp::init_vector_dxyz(dst, 1.0f, 0.0f, 0.0f); 108 dsp::apply_matrix3d_mv1(dst, &cap->pos); 109 return STATUS_OK; 110 } 111 get_location(ray3d_t * dst,size_t id)112 status_t LSPCapture3D::get_location(ray3d_t *dst, size_t id) 113 { 114 v_capture_t *cap = vItems.get(id); 115 if (cap == NULL) 116 return STATUS_NOT_FOUND; 117 dsp::init_point_xyz(&dst->z, 0.0f, 0.0f, 0.0f); 118 dsp::init_vector_dxyz(&dst->v, 1.0f, 0.0f, 0.0f); 119 dsp::apply_matrix3d_mp1(&dst->z, &cap->pos); 120 dsp::apply_matrix3d_mv1(&dst->v, &cap->pos); 121 return STATUS_OK; 122 } 123 enabled(size_t id) const124 bool LSPCapture3D::enabled(size_t id) const 125 { 126 LSPCapture3D *_this = const_cast<LSPCapture3D *>(this); 127 v_capture_t *cap = _this->vItems.get(id); 128 return (cap != NULL) ? cap->bEnabled : false; 129 } 130 radius(size_t id) const131 float LSPCapture3D::radius(size_t id) const 132 { 133 LSPCapture3D *_this = const_cast<LSPCapture3D *>(this); 134 v_capture_t *cap = _this->vItems.get(id); 135 return (cap != NULL) ? cap->radius : false; 136 } 137 clear()138 void LSPCapture3D::clear() 139 { 140 if (vItems.size() > 0) 141 { 142 vItems.clear(); 143 query_draw(); 144 } 145 } 146 set_items(size_t items)147 status_t LSPCapture3D::set_items(size_t items) 148 { 149 if (vItems.size() == items) 150 return STATUS_OK; 151 152 while (vItems.size() < items) 153 { 154 v_capture_t *cap = vItems.add(); 155 if (cap == NULL) 156 return STATUS_NO_MEM; 157 158 dsp::init_matrix3d_identity(&cap->pos); 159 cap->radius = 1.0f; 160 cap->bEnabled = false; 161 } 162 163 while (vItems.size() > items) 164 vItems.remove_last(); 165 166 query_draw(); 167 return STATUS_OK; 168 } 169 set_transform(size_t id,const matrix3d_t * matrix)170 status_t LSPCapture3D::set_transform(size_t id, const matrix3d_t *matrix) 171 { 172 v_capture_t *cap = vItems.get(id); 173 if (cap == NULL) 174 return STATUS_NOT_FOUND; 175 cap->pos = *matrix; 176 query_draw(); 177 return STATUS_OK; 178 } 179 set_enabled(size_t id,bool enabled)180 status_t LSPCapture3D::set_enabled(size_t id, bool enabled) 181 { 182 v_capture_t *cap = vItems.get(id); 183 if (cap == NULL) 184 return STATUS_NOT_FOUND; 185 if (cap->bEnabled == enabled) 186 return STATUS_OK; 187 cap->bEnabled = enabled; 188 query_draw(); 189 return STATUS_OK; 190 } 191 set_radius(size_t id,float radius)192 void LSPCapture3D::set_radius(size_t id, float radius) 193 { 194 v_capture_t *cap = vItems.get(id); 195 if ((cap == NULL) || (cap->radius == radius)) 196 return; 197 cap->radius = radius; 198 if (cap->bEnabled) 199 query_draw(); 200 } 201 render(IR3DBackend * r3d)202 void LSPCapture3D::render(IR3DBackend *r3d) 203 { 204 if (!is_visible()) 205 return; 206 207 r3d_buffer_t buf; 208 cstorage<raw_triangle_t> mesh; 209 cstorage<ray3d_t> vertices; 210 211 // Draw all elements of the capture 212 for (size_t id=0, nid=vItems.size(); id < nid; ++id) 213 { 214 v_capture_t *cap = vItems.get(id); 215 if ((cap == NULL) || (!cap->bEnabled)) 216 continue; 217 218 // Update mesh data for lines 219 for (size_t i=0; i<6; ++i) 220 dsp::apply_matrix3d_mp2(&sLines[i], &tk_capture_vertices[i], &cap->pos); 221 222 // Call draw of lines 223 buf.type = R3D_PRIMITIVE_LINES; 224 buf.width = 2.0f; 225 buf.count = sizeof(tk_arrow_indexes) / (sizeof(uint32_t) * 2); 226 buf.flags = 0; 227 228 buf.vertex.data = sLines; 229 buf.vertex.stride = sizeof(point3d_t); 230 buf.normal.data = NULL; 231 buf.normal.stride = sizeof(point3d_t); 232 buf.color.data = NULL; 233 buf.color.stride = sizeof(point3d_t); 234 buf.color.dfl.r = sAxisColor.red(); 235 buf.color.dfl.g = sAxisColor.green(); 236 buf.color.dfl.b = sAxisColor.blue(); 237 buf.color.dfl.a = 1.0f; 238 buf.index.data = tk_arrow_indexes; 239 240 r3d->draw_primitives(&buf); 241 242 // Update mesh data for body 243 status_t res = rt_gen_capture_mesh(mesh, cap); 244 if (res != STATUS_OK) 245 continue; 246 247 vertices.clear(); 248 if (!vertices.append_n(mesh.size() * 3)) 249 continue; 250 251 raw_triangle_t *tv = mesh.get_array(); 252 ray3d_t *tr = vertices.get_array(); 253 for (size_t i=0, n=mesh.size(); i<n; ++i, tr += 3) 254 { 255 dsp::apply_matrix3d_mp2(&tr[0].z, &tv[i].v[0], &cap->pos); 256 dsp::apply_matrix3d_mp2(&tr[1].z, &tv[i].v[1], &cap->pos); 257 dsp::apply_matrix3d_mp2(&tr[2].z, &tv[i].v[2], &cap->pos); 258 259 dsp::calc_normal3d_p3(&tr[0].v, &tr[0].z, &tr[1].z, &tr[2].z); 260 tr[1].v = tr[0].v; 261 tr[2].v = tr[0].v; 262 } 263 tr = vertices.get_array(); 264 265 // Call draw of capsule 266 buf.type = R3D_PRIMITIVE_TRIANGLES; 267 buf.flags = R3D_BUFFER_LIGHTING; 268 buf.width = 1.0f; 269 buf.count = mesh.size(); 270 buf.color.dfl.r = sColor.red(); 271 buf.color.dfl.g = sColor.green(); 272 buf.color.dfl.b = sColor.blue(); 273 buf.color.dfl.a = 1.0f; 274 275 buf.vertex.data = &tr[0].z; 276 buf.vertex.stride = sizeof(ray3d_t); 277 buf.normal.data = &tr[0].v; 278 buf.normal.stride = sizeof(ray3d_t); 279 buf.index.data = NULL; 280 281 r3d->draw_primitives(&buf); 282 } 283 } 284 285 } /* namespace tk */ 286 } /* namespace lsp */ 287