1 /** 2 Provides high-performance mesh instancing. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.multimesh; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.traits; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.globalenums; 22 import godot.object; 23 import godot.classdb; 24 import godot.resource; 25 import godot.mesh; 26 /** 27 Provides high-performance mesh instancing. 28 29 MultiMesh provides low-level mesh instancing. Drawing thousands of $(D MeshInstance) nodes can be slow, since each object is submitted to the GPU then drawn individually. 30 MultiMesh is much faster as it can draw thousands of instances with a single draw call, resulting in less API overhead. 31 As a drawback, if the instances are too far away from each other, performance may be reduced as every single instance will always render (they are spatially indexed as one, for the whole object). 32 Since instances may have any behavior, the AABB used for visibility must be provided by the user. 33 */ 34 @GodotBaseClass struct MultiMesh 35 { 36 package(godot) enum string _GODOT_internal_name = "MultiMesh"; 37 public: 38 @nogc nothrow: 39 union { /** */ godot_object _godot_object; /** */ Resource _GODOT_base; } 40 alias _GODOT_base this; 41 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 42 package(godot) __gshared bool _classBindingInitialized = false; 43 package(godot) static struct GDNativeClassBinding 44 { 45 __gshared: 46 @GodotName("_get_color_array") GodotMethod!(PoolColorArray) _getColorArray; 47 @GodotName("_get_custom_data_array") GodotMethod!(PoolColorArray) _getCustomDataArray; 48 @GodotName("_get_transform_2d_array") GodotMethod!(PoolVector2Array) _getTransform2dArray; 49 @GodotName("_get_transform_array") GodotMethod!(PoolVector3Array) _getTransformArray; 50 @GodotName("_set_color_array") GodotMethod!(void, PoolColorArray) _setColorArray; 51 @GodotName("_set_custom_data_array") GodotMethod!(void, PoolColorArray) _setCustomDataArray; 52 @GodotName("_set_transform_2d_array") GodotMethod!(void, PoolVector2Array) _setTransform2dArray; 53 @GodotName("_set_transform_array") GodotMethod!(void, PoolVector3Array) _setTransformArray; 54 @GodotName("get_aabb") GodotMethod!(AABB) getAabb; 55 @GodotName("get_color_format") GodotMethod!(MultiMesh.ColorFormat) getColorFormat; 56 @GodotName("get_custom_data_format") GodotMethod!(MultiMesh.CustomDataFormat) getCustomDataFormat; 57 @GodotName("get_instance_color") GodotMethod!(Color, long) getInstanceColor; 58 @GodotName("get_instance_count") GodotMethod!(long) getInstanceCount; 59 @GodotName("get_instance_custom_data") GodotMethod!(Color, long) getInstanceCustomData; 60 @GodotName("get_instance_transform") GodotMethod!(Transform, long) getInstanceTransform; 61 @GodotName("get_instance_transform_2d") GodotMethod!(Transform2D, long) getInstanceTransform2d; 62 @GodotName("get_mesh") GodotMethod!(Mesh) getMesh; 63 @GodotName("get_transform_format") GodotMethod!(MultiMesh.TransformFormat) getTransformFormat; 64 @GodotName("get_visible_instance_count") GodotMethod!(long) getVisibleInstanceCount; 65 @GodotName("set_as_bulk_array") GodotMethod!(void, PoolRealArray) setAsBulkArray; 66 @GodotName("set_color_format") GodotMethod!(void, long) setColorFormat; 67 @GodotName("set_custom_data_format") GodotMethod!(void, long) setCustomDataFormat; 68 @GodotName("set_instance_color") GodotMethod!(void, long, Color) setInstanceColor; 69 @GodotName("set_instance_count") GodotMethod!(void, long) setInstanceCount; 70 @GodotName("set_instance_custom_data") GodotMethod!(void, long, Color) setInstanceCustomData; 71 @GodotName("set_instance_transform") GodotMethod!(void, long, Transform) setInstanceTransform; 72 @GodotName("set_instance_transform_2d") GodotMethod!(void, long, Transform2D) setInstanceTransform2d; 73 @GodotName("set_mesh") GodotMethod!(void, Mesh) setMesh; 74 @GodotName("set_transform_format") GodotMethod!(void, long) setTransformFormat; 75 @GodotName("set_visible_instance_count") GodotMethod!(void, long) setVisibleInstanceCount; 76 } 77 /// 78 pragma(inline, true) bool opEquals(in MultiMesh other) const 79 { return _godot_object.ptr is other._godot_object.ptr; } 80 /// 81 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 82 { _godot_object.ptr = n; return null; } 83 /// 84 pragma(inline, true) bool opEquals(typeof(null) n) const 85 { return _godot_object.ptr is n; } 86 /// 87 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 88 mixin baseCasts; 89 /// Construct a new instance of MultiMesh. 90 /// Note: use `memnew!MultiMesh` instead. 91 static MultiMesh _new() 92 { 93 static godot_class_constructor constructor; 94 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("MultiMesh"); 95 if(constructor is null) return typeof(this).init; 96 return cast(MultiMesh)(constructor()); 97 } 98 @disable new(size_t s); 99 /// 100 enum TransformFormat : int 101 { 102 /** 103 Use this when using 2D transforms. 104 */ 105 transform2d = 0, 106 /** 107 Use this when using 3D transforms. 108 */ 109 transform3d = 1, 110 } 111 /// 112 enum CustomDataFormat : int 113 { 114 /** 115 Use when you are not using per-instance custom data. 116 */ 117 customDataNone = 0, 118 /** 119 Compress custom_data into 8 bits when passing to shader. This uses less memory and can be faster, but loses precision and range. Floats packed into 8 bits can only represent values between 0 and 1, numbers outside that range will be clamped. 120 */ 121 customData8bit = 1, 122 /** 123 The $(D Color) passed into $(D setInstanceCustomData) will use 4 floats. Use this for highest precision. 124 */ 125 customDataFloat = 2, 126 } 127 /// 128 enum ColorFormat : int 129 { 130 /** 131 Use when you are not using per-instance $(D Color)s. 132 */ 133 colorNone = 0, 134 /** 135 Compress $(D Color) data into 8 bits when passing to shader. This uses less memory and can be faster, but the $(D Color) loses precision. 136 */ 137 color8bit = 1, 138 /** 139 The $(D Color) passed into $(D setInstanceColor) will use 4 floats. Use this for highest precision $(D Color). 140 */ 141 colorFloat = 2, 142 } 143 /// 144 enum Constants : int 145 { 146 colorNone = 0, 147 transform2d = 0, 148 customDataNone = 0, 149 customData8bit = 1, 150 transform3d = 1, 151 color8bit = 1, 152 colorFloat = 2, 153 customDataFloat = 2, 154 } 155 /** 156 157 */ 158 PoolColorArray _getColorArray() const 159 { 160 Array _GODOT_args = Array.make(); 161 String _GODOT_method_name = String("_get_color_array"); 162 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!PoolColorArray); 163 } 164 /** 165 166 */ 167 PoolColorArray _getCustomDataArray() const 168 { 169 Array _GODOT_args = Array.make(); 170 String _GODOT_method_name = String("_get_custom_data_array"); 171 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!PoolColorArray); 172 } 173 /** 174 175 */ 176 PoolVector2Array _getTransform2dArray() const 177 { 178 Array _GODOT_args = Array.make(); 179 String _GODOT_method_name = String("_get_transform_2d_array"); 180 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!PoolVector2Array); 181 } 182 /** 183 184 */ 185 PoolVector3Array _getTransformArray() const 186 { 187 Array _GODOT_args = Array.make(); 188 String _GODOT_method_name = String("_get_transform_array"); 189 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!PoolVector3Array); 190 } 191 /** 192 193 */ 194 void _setColorArray(in PoolColorArray arg0) 195 { 196 Array _GODOT_args = Array.make(); 197 _GODOT_args.append(arg0); 198 String _GODOT_method_name = String("_set_color_array"); 199 this.callv(_GODOT_method_name, _GODOT_args); 200 } 201 /** 202 203 */ 204 void _setCustomDataArray(in PoolColorArray arg0) 205 { 206 Array _GODOT_args = Array.make(); 207 _GODOT_args.append(arg0); 208 String _GODOT_method_name = String("_set_custom_data_array"); 209 this.callv(_GODOT_method_name, _GODOT_args); 210 } 211 /** 212 213 */ 214 void _setTransform2dArray(in PoolVector2Array arg0) 215 { 216 Array _GODOT_args = Array.make(); 217 _GODOT_args.append(arg0); 218 String _GODOT_method_name = String("_set_transform_2d_array"); 219 this.callv(_GODOT_method_name, _GODOT_args); 220 } 221 /** 222 223 */ 224 void _setTransformArray(in PoolVector3Array arg0) 225 { 226 Array _GODOT_args = Array.make(); 227 _GODOT_args.append(arg0); 228 String _GODOT_method_name = String("_set_transform_array"); 229 this.callv(_GODOT_method_name, _GODOT_args); 230 } 231 /** 232 Returns the visibility axis-aligned bounding box in local space. See also $(D VisualInstance.getTransformedAabb). 233 */ 234 AABB getAabb() const 235 { 236 checkClassBinding!(typeof(this))(); 237 return ptrcall!(AABB)(GDNativeClassBinding.getAabb, _godot_object); 238 } 239 /** 240 241 */ 242 MultiMesh.ColorFormat getColorFormat() const 243 { 244 checkClassBinding!(typeof(this))(); 245 return ptrcall!(MultiMesh.ColorFormat)(GDNativeClassBinding.getColorFormat, _godot_object); 246 } 247 /** 248 249 */ 250 MultiMesh.CustomDataFormat getCustomDataFormat() const 251 { 252 checkClassBinding!(typeof(this))(); 253 return ptrcall!(MultiMesh.CustomDataFormat)(GDNativeClassBinding.getCustomDataFormat, _godot_object); 254 } 255 /** 256 Gets a specific instance's color. 257 */ 258 Color getInstanceColor(in long instance) const 259 { 260 checkClassBinding!(typeof(this))(); 261 return ptrcall!(Color)(GDNativeClassBinding.getInstanceColor, _godot_object, instance); 262 } 263 /** 264 265 */ 266 long getInstanceCount() const 267 { 268 checkClassBinding!(typeof(this))(); 269 return ptrcall!(long)(GDNativeClassBinding.getInstanceCount, _godot_object); 270 } 271 /** 272 Returns the custom data that has been set for a specific instance. 273 */ 274 Color getInstanceCustomData(in long instance) const 275 { 276 checkClassBinding!(typeof(this))(); 277 return ptrcall!(Color)(GDNativeClassBinding.getInstanceCustomData, _godot_object, instance); 278 } 279 /** 280 Returns the $(D Transform) of a specific instance. 281 */ 282 Transform getInstanceTransform(in long instance) const 283 { 284 checkClassBinding!(typeof(this))(); 285 return ptrcall!(Transform)(GDNativeClassBinding.getInstanceTransform, _godot_object, instance); 286 } 287 /** 288 Returns the $(D Transform2D) of a specific instance. 289 */ 290 Transform2D getInstanceTransform2d(in long instance) const 291 { 292 checkClassBinding!(typeof(this))(); 293 return ptrcall!(Transform2D)(GDNativeClassBinding.getInstanceTransform2d, _godot_object, instance); 294 } 295 /** 296 297 */ 298 Ref!Mesh getMesh() const 299 { 300 checkClassBinding!(typeof(this))(); 301 return ptrcall!(Mesh)(GDNativeClassBinding.getMesh, _godot_object); 302 } 303 /** 304 305 */ 306 MultiMesh.TransformFormat getTransformFormat() const 307 { 308 checkClassBinding!(typeof(this))(); 309 return ptrcall!(MultiMesh.TransformFormat)(GDNativeClassBinding.getTransformFormat, _godot_object); 310 } 311 /** 312 313 */ 314 long getVisibleInstanceCount() const 315 { 316 checkClassBinding!(typeof(this))(); 317 return ptrcall!(long)(GDNativeClassBinding.getVisibleInstanceCount, _godot_object); 318 } 319 /** 320 Sets all data related to the instances in one go. This is especially useful when loading the data from disk or preparing the data from GDNative. 321 All data is packed in one large float array. An array may look like this: Transform for instance 1, color data for instance 1, custom data for instance 1, transform for instance 2, color data for instance 2, etc... 322 $(D Transform) is stored as 12 floats, $(D Transform2D) is stored as 8 floats, `COLOR_8BIT` / `CUSTOM_DATA_8BIT` is stored as 1 float (4 bytes as is) and `COLOR_FLOAT` / `CUSTOM_DATA_FLOAT` is stored as 4 floats. 323 */ 324 void setAsBulkArray(in PoolRealArray array) 325 { 326 checkClassBinding!(typeof(this))(); 327 ptrcall!(void)(GDNativeClassBinding.setAsBulkArray, _godot_object, array); 328 } 329 /** 330 331 */ 332 void setColorFormat(in long format) 333 { 334 checkClassBinding!(typeof(this))(); 335 ptrcall!(void)(GDNativeClassBinding.setColorFormat, _godot_object, format); 336 } 337 /** 338 339 */ 340 void setCustomDataFormat(in long format) 341 { 342 checkClassBinding!(typeof(this))(); 343 ptrcall!(void)(GDNativeClassBinding.setCustomDataFormat, _godot_object, format); 344 } 345 /** 346 Sets the color of a specific instance by $(I multiplying) the mesh's existing vertex colors. 347 For the color to take effect, ensure that $(D colorFormat) is non-`null` on the $(D MultiMesh) and $(D SpatialMaterial.vertexColorUseAsAlbedo) is `true` on the material. 348 */ 349 void setInstanceColor(in long instance, in Color color) 350 { 351 checkClassBinding!(typeof(this))(); 352 ptrcall!(void)(GDNativeClassBinding.setInstanceColor, _godot_object, instance, color); 353 } 354 /** 355 356 */ 357 void setInstanceCount(in long count) 358 { 359 checkClassBinding!(typeof(this))(); 360 ptrcall!(void)(GDNativeClassBinding.setInstanceCount, _godot_object, count); 361 } 362 /** 363 Sets custom data for a specific instance. Although $(D Color) is used, it is just a container for 4 floating point numbers. The format of the number can change depending on the $(D customdataformat) used. 364 */ 365 void setInstanceCustomData(in long instance, in Color custom_data) 366 { 367 checkClassBinding!(typeof(this))(); 368 ptrcall!(void)(GDNativeClassBinding.setInstanceCustomData, _godot_object, instance, custom_data); 369 } 370 /** 371 Sets the $(D Transform) for a specific instance. 372 */ 373 void setInstanceTransform(in long instance, in Transform transform) 374 { 375 checkClassBinding!(typeof(this))(); 376 ptrcall!(void)(GDNativeClassBinding.setInstanceTransform, _godot_object, instance, transform); 377 } 378 /** 379 Sets the $(D Transform2D) for a specific instance. 380 */ 381 void setInstanceTransform2d(in long instance, in Transform2D transform) 382 { 383 checkClassBinding!(typeof(this))(); 384 ptrcall!(void)(GDNativeClassBinding.setInstanceTransform2d, _godot_object, instance, transform); 385 } 386 /** 387 388 */ 389 void setMesh(Mesh mesh) 390 { 391 checkClassBinding!(typeof(this))(); 392 ptrcall!(void)(GDNativeClassBinding.setMesh, _godot_object, mesh); 393 } 394 /** 395 396 */ 397 void setTransformFormat(in long format) 398 { 399 checkClassBinding!(typeof(this))(); 400 ptrcall!(void)(GDNativeClassBinding.setTransformFormat, _godot_object, format); 401 } 402 /** 403 404 */ 405 void setVisibleInstanceCount(in long count) 406 { 407 checkClassBinding!(typeof(this))(); 408 ptrcall!(void)(GDNativeClassBinding.setVisibleInstanceCount, _godot_object, count); 409 } 410 /** 411 412 */ 413 @property PoolColorArray colorArray() 414 { 415 return _getColorArray(); 416 } 417 /// ditto 418 @property void colorArray(PoolColorArray v) 419 { 420 _setColorArray(v); 421 } 422 /** 423 Format of colors in color array that gets passed to shader. 424 */ 425 @property MultiMesh.ColorFormat colorFormat() 426 { 427 return getColorFormat(); 428 } 429 /// ditto 430 @property void colorFormat(long v) 431 { 432 setColorFormat(v); 433 } 434 /** 435 436 */ 437 @property PoolColorArray customDataArray() 438 { 439 return _getCustomDataArray(); 440 } 441 /// ditto 442 @property void customDataArray(PoolColorArray v) 443 { 444 _setCustomDataArray(v); 445 } 446 /** 447 Format of custom data in custom data array that gets passed to shader. 448 */ 449 @property MultiMesh.CustomDataFormat customDataFormat() 450 { 451 return getCustomDataFormat(); 452 } 453 /// ditto 454 @property void customDataFormat(long v) 455 { 456 setCustomDataFormat(v); 457 } 458 /** 459 Number of instances that will get drawn. This clears and (re)sizes the buffers. By default, all instances are drawn but you can limit this with $(D visibleInstanceCount). 460 */ 461 @property long instanceCount() 462 { 463 return getInstanceCount(); 464 } 465 /// ditto 466 @property void instanceCount(long v) 467 { 468 setInstanceCount(v); 469 } 470 /** 471 Mesh to be drawn. 472 */ 473 @property Mesh mesh() 474 { 475 return getMesh(); 476 } 477 /// ditto 478 @property void mesh(Mesh v) 479 { 480 setMesh(v); 481 } 482 /** 483 484 */ 485 @property PoolVector2Array transform2dArray() 486 { 487 return _getTransform2dArray(); 488 } 489 /// ditto 490 @property void transform2dArray(PoolVector2Array v) 491 { 492 _setTransform2dArray(v); 493 } 494 /** 495 496 */ 497 @property PoolVector3Array transformArray() 498 { 499 return _getTransformArray(); 500 } 501 /// ditto 502 @property void transformArray(PoolVector3Array v) 503 { 504 _setTransformArray(v); 505 } 506 /** 507 Format of transform used to transform mesh, either 2D or 3D. 508 */ 509 @property MultiMesh.TransformFormat transformFormat() 510 { 511 return getTransformFormat(); 512 } 513 /// ditto 514 @property void transformFormat(long v) 515 { 516 setTransformFormat(v); 517 } 518 /** 519 Limits the number of instances drawn, -1 draws all instances. Changing this does not change the sizes of the buffers. 520 */ 521 @property long visibleInstanceCount() 522 { 523 return getVisibleInstanceCount(); 524 } 525 /// ditto 526 @property void visibleInstanceCount(long v) 527 { 528 setVisibleInstanceCount(v); 529 } 530 }